diff --git a/Android.mk b/Android.mk new file mode 100755 index 0000000..f3b8b31 --- /dev/null +++ b/Android.mk @@ -0,0 +1,10 @@ +ifeq ($(call my-dir),$(call project-path-for,qcom-media)) + +QCOM_MEDIA_ROOT := $(call my-dir) +include $(QCOM_MEDIA_ROOT)/mm-core/Android.mk +include $(QCOM_MEDIA_ROOT)/libstagefrighthw/Android.mk + +#include $(QCOM_MEDIA_ROOT)/mm-video/Android.mk +#include $(QCOM_MEDIA_ROOT)/libI420colorconvert/Android.mk + +endif diff --git a/CleanSpec.mk b/CleanSpec.mk new file mode 100755 index 0000000..b84e1b6 --- /dev/null +++ b/CleanSpec.mk @@ -0,0 +1,49 @@ +# Copyright (C) 2007 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +# For example: +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) +#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) +#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ diff --git a/libI420colorconvert/Android.mk b/libI420colorconvert/Android.mk new file mode 100644 index 0000000..1994662 --- /dev/null +++ b/libI420colorconvert/Android.mk @@ -0,0 +1,20 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + ColorConvert.cpp + +LOCAL_C_INCLUDES:= \ + $(TOP)/frameworks/native/include/media/editor \ + $(TOP)/frameworks/av/include/media/stagefright \ + $(TARGET_OUT_HEADERS)/mm-core/omxcore + +LOCAL_SHARED_LIBRARIES := libutils \ + libdl \ + libcutils + +LOCAL_MODULE_TAGS := optional + +LOCAL_MODULE := libI420colorconvert + +include $(BUILD_SHARED_LIBRARY) diff --git a/libI420colorconvert/ColorConvert.cpp b/libI420colorconvert/ColorConvert.cpp new file mode 100644 index 0000000..4cb72a3 --- /dev/null +++ b/libI420colorconvert/ColorConvert.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * Copyright (C) 2012 Code Aurora Forum + * + * Not a Contribution, Apache license notifications and license are + * retained for attribution purposes only. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "II420ColorConverter.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1))) + +namespace android { + +class I420ColorConverterWrapper { +public: + I420ColorConverterWrapper(); + ~I420ColorConverterWrapper(); + + static void* mLibHandle; + static ConvertFn mConvert; + static int mRefCount; + + static int getDecoderOutputFormat() { + return QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; + } + + static int convertDecoderOutputToI420( + void* srcBits, int srcWidth, int srcHeight, + ARect srcRect, void* dstBits) { + + if (mConvert == NULL) { + openColorConverterLib(); + } + + ColorConvertParams inputCP; + inputCP.width = ALIGN(srcWidth, 128); + inputCP.height = ALIGN(srcHeight, 32); + inputCP.cropWidth = srcWidth; + inputCP.cropHeight = srcHeight; + inputCP.cropLeft = 0; + inputCP.cropRight = srcWidth; + inputCP.cropTop = 0; + inputCP.cropBottom = srcHeight; + inputCP.colorFormat = YCbCr420Tile; + inputCP.data = (uint8_t *)srcBits; + inputCP.flags = COLOR_CONVERT_ALIGN_NONE; + inputCP.fd = -1; + + ColorConvertParams outputCP; + outputCP.width = srcWidth; + outputCP.height = srcHeight; + outputCP.cropWidth = srcWidth; + outputCP.cropHeight = srcHeight; + outputCP.cropLeft = 0; + outputCP.cropRight = srcWidth; + outputCP.cropTop = 0; + outputCP.cropBottom = srcHeight; + outputCP.fd = -1; + + outputCP.flags = COLOR_CONVERT_ALIGN_NONE; + outputCP.colorFormat = YCbCr420P; + outputCP.data = (uint8_t *)dstBits; + + mConvert( inputCP, outputCP, NULL); + + return 0; + } + + static int getEncoderInputFormat() { + return OMX_COLOR_FormatYUV420SemiPlanar; + } + + static int convertI420ToEncoderInput( + void* srcBits, int srcWidth, int srcHeight, + int dstWidth, int dstHeight, ARect dstRect, + void* dstBits) { + + if (mConvert == NULL) { + openColorConverterLib(); + } + + ColorConvertParams inputCP; + inputCP.width = srcWidth; + inputCP.height = srcHeight; + inputCP.cropWidth = srcWidth; + inputCP.cropHeight = srcHeight; + inputCP.cropLeft = 0; + inputCP.cropRight = srcWidth; + inputCP.cropTop = 0; + inputCP.cropBottom = srcHeight; + inputCP.colorFormat = YCbCr420P; + inputCP.flags = COLOR_CONVERT_ALIGN_NONE; + inputCP.data = (uint8_t *)srcBits; + inputCP.fd = -1; + + ColorConvertParams outputCP; + outputCP.width = dstWidth; + outputCP.height = dstHeight; + outputCP.cropWidth = dstWidth; + outputCP.cropHeight = dstHeight; + outputCP.cropLeft = 0; + outputCP.cropRight = dstWidth; + outputCP.cropTop = 0; + outputCP.cropBottom = dstHeight; + outputCP.colorFormat = YCbCr420SP; + outputCP.flags = COLOR_CONVERT_ALIGN_2048; + outputCP.data = (uint8_t *)dstBits; + outputCP.fd = -1; + + mConvert( inputCP, outputCP, NULL); + + return 0; + } + + static int getEncoderInputBufferInfo( + int actualWidth, int actualHeight, + int* encoderWidth, int* encoderHeight, + ARect* encoderRect, int* encoderBufferSize) { + + *encoderWidth = actualWidth; + *encoderHeight = actualHeight; + encoderRect->left = 0; + encoderRect->top = 0; + encoderRect->right = actualWidth - 1; + encoderRect->bottom = actualHeight - 1; + unsigned long sizeY = ALIGN(actualWidth*actualHeight,2048); + unsigned long sizeU = ALIGN(actualWidth*actualHeight/2, 2048); + unsigned long size = sizeY + sizeU; + + *encoderBufferSize = (size); + + return 0; + } + + static void openColorConverterLib() { + + int prevRefCount = android_atomic_inc(&mRefCount); + if (prevRefCount > 0) { + return; + } + + mLibHandle = dlopen("libmm-color-convertor.so", RTLD_NOW); + mConvert = NULL; + + if (mLibHandle) { + mConvert = (ConvertFn)dlsym(mLibHandle, + "_ZN7android7convertENS_18ColorConvertParamsES0_Ph"); + if(mConvert != NULL) { + ALOGV("Successfully acquired mConvert symbol"); + } + } + else { + ALOGE("Could not get yuvconversion lib handle"); + CHECK(0); + } + } + + static void closeColorConverterLib() { + + int prevRefCount = android_atomic_dec(&mRefCount); + if (prevRefCount > 1) { + return; + } + + dlclose(mLibHandle); + mLibHandle = NULL; + mConvert = NULL; + } +}; + +ConvertFn I420ColorConverterWrapper::mConvert = NULL; +void * I420ColorConverterWrapper::mLibHandle = NULL; +int I420ColorConverterWrapper::mRefCount = 0; + +} // namespace - android + +extern "C" void getI420ColorConverter(II420ColorConverter *converter) { + converter->getDecoderOutputFormat = android::I420ColorConverterWrapper::getDecoderOutputFormat; + converter->convertDecoderOutputToI420 = android::I420ColorConverterWrapper::convertDecoderOutputToI420; + converter->getEncoderInputFormat = android::I420ColorConverterWrapper::getEncoderInputFormat; + converter->convertI420ToEncoderInput = android::I420ColorConverterWrapper::convertI420ToEncoderInput; + converter->getEncoderInputBufferInfo = android::I420ColorConverterWrapper::getEncoderInputBufferInfo; + converter->openColorConverterLib = android::I420ColorConverterWrapper::openColorConverterLib; + converter->closeColorConverterLib = android::I420ColorConverterWrapper::closeColorConverterLib; +} + diff --git a/libstagefrighthw/Android.mk b/libstagefrighthw/Android.mk new file mode 100755 index 0000000..2a307ef --- /dev/null +++ b/libstagefrighthw/Android.mk @@ -0,0 +1,39 @@ +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + QComOMXPlugin.cpp \ + +LOCAL_CFLAGS := $(PV_CFLAGS_MINUS_VISIBILITY) + +LOCAL_C_INCLUDES:= \ + frameworks/native/include/media/openmax \ + frameworks/native/include/media/hardware + +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + libutils \ + libcutils \ + libdl \ + libui \ + +LOCAL_MODULE := libstagefrighthw + +include $(BUILD_SHARED_LIBRARY) + diff --git a/libstagefrighthw/MODULE_LICENSE_APACHE2 b/libstagefrighthw/MODULE_LICENSE_APACHE2 new file mode 100755 index 0000000..e69de29 diff --git a/libstagefrighthw/NOTICE b/libstagefrighthw/NOTICE new file mode 100755 index 0000000..a94ca1f --- /dev/null +++ b/libstagefrighthw/NOTICE @@ -0,0 +1,189 @@ + Copyright (c) 2009, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/libstagefrighthw/QComOMXMetadata.h b/libstagefrighthw/QComOMXMetadata.h new file mode 100755 index 0000000..e5c1457 --- /dev/null +++ b/libstagefrighthw/QComOMXMetadata.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 The Code Aurora Forum. All rights reserved. + * Copyright (c) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +namespace android { + typedef struct encoder_media_buffer_type { + MetadataBufferType buffer_type; + buffer_handle_t meta_handle; + } encoder_media_buffer_type; +} diff --git a/libstagefrighthw/QComOMXPlugin.cpp b/libstagefrighthw/QComOMXPlugin.cpp new file mode 100755 index 0000000..9446dcf --- /dev/null +++ b/libstagefrighthw/QComOMXPlugin.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "QComOMXPlugin.h" + +#include + +#include + +namespace android { + +OMXPluginBase *createOMXPlugin() { + return new QComOMXPlugin; +} + +QComOMXPlugin::QComOMXPlugin() + : mLibHandle(dlopen("libOmxCore.so", RTLD_NOW)), + mInit(NULL), + mDeinit(NULL), + mComponentNameEnum(NULL), + mGetHandle(NULL), + mFreeHandle(NULL), + mGetRolesOfComponentHandle(NULL) { + if (mLibHandle != NULL) { + mInit = (InitFunc)dlsym(mLibHandle, "OMX_Init"); + mDeinit = (DeinitFunc)dlsym(mLibHandle, "OMX_Deinit"); + + mComponentNameEnum = + (ComponentNameEnumFunc)dlsym(mLibHandle, "OMX_ComponentNameEnum"); + + mGetHandle = (GetHandleFunc)dlsym(mLibHandle, "OMX_GetHandle"); + mFreeHandle = (FreeHandleFunc)dlsym(mLibHandle, "OMX_FreeHandle"); + + mGetRolesOfComponentHandle = + (GetRolesOfComponentFunc)dlsym( + mLibHandle, "OMX_GetRolesOfComponent"); + + (*mInit)(); + } +} + +QComOMXPlugin::~QComOMXPlugin() { + if (mLibHandle != NULL) { + (*mDeinit)(); + + dlclose(mLibHandle); + mLibHandle = NULL; + } +} + +OMX_ERRORTYPE QComOMXPlugin::makeComponentInstance( + const char *name, + const OMX_CALLBACKTYPE *callbacks, + OMX_PTR appData, + OMX_COMPONENTTYPE **component) { + if (mLibHandle == NULL) { + return OMX_ErrorUndefined; + } + + return (*mGetHandle)( + reinterpret_cast(component), + const_cast(name), + appData, const_cast(callbacks)); +} + +OMX_ERRORTYPE QComOMXPlugin::destroyComponentInstance( + OMX_COMPONENTTYPE *component) { + if (mLibHandle == NULL) { + return OMX_ErrorUndefined; + } + + return (*mFreeHandle)(reinterpret_cast(component)); +} + +OMX_ERRORTYPE QComOMXPlugin::enumerateComponents( + OMX_STRING name, + size_t size, + OMX_U32 index) { + if (mLibHandle == NULL) { + return OMX_ErrorUndefined; + } + + return (*mComponentNameEnum)(name, size, index); +} + +OMX_ERRORTYPE QComOMXPlugin::getRolesOfComponent( + const char *name, + Vector *roles) { + roles->clear(); + + if (mLibHandle == NULL) { + return OMX_ErrorUndefined; + } + + OMX_U32 numRoles; + OMX_ERRORTYPE err = (*mGetRolesOfComponentHandle)( + const_cast(name), &numRoles, NULL); + + if (err != OMX_ErrorNone) { + return err; + } + + if (numRoles > 0) { + OMX_U8 **array = new OMX_U8 *[numRoles]; + for (OMX_U32 i = 0; i < numRoles; ++i) { + array[i] = new OMX_U8[OMX_MAX_STRINGNAME_SIZE]; + } + + OMX_U32 numRoles2; + err = (*mGetRolesOfComponentHandle)( + const_cast(name), &numRoles2, array); + + if (err != OMX_ErrorNone) { + return err; + } + + if (numRoles2 != numRoles) { + return err; + } + + for (OMX_U32 i = 0; i < numRoles; ++i) { + String8 s((const char *)array[i]); + roles->push(s); + + delete[] array[i]; + array[i] = NULL; + } + + delete[] array; + array = NULL; + } + + return OMX_ErrorNone; +} + +} // namespace android diff --git a/libstagefrighthw/QComOMXPlugin.h b/libstagefrighthw/QComOMXPlugin.h new file mode 100755 index 0000000..fc623e3 --- /dev/null +++ b/libstagefrighthw/QComOMXPlugin.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef QCOM_OMX_PLUGIN_H_ + +#define QCOM_OMX_PLUGIN_H_ + +#include + +namespace android { + +struct QComOMXPlugin : public OMXPluginBase { + QComOMXPlugin(); + virtual ~QComOMXPlugin(); + + virtual OMX_ERRORTYPE makeComponentInstance( + const char *name, + const OMX_CALLBACKTYPE *callbacks, + OMX_PTR appData, + OMX_COMPONENTTYPE **component); + + virtual OMX_ERRORTYPE destroyComponentInstance( + OMX_COMPONENTTYPE *component); + + virtual OMX_ERRORTYPE enumerateComponents( + OMX_STRING name, + size_t size, + OMX_U32 index); + + virtual OMX_ERRORTYPE getRolesOfComponent( + const char *name, + Vector *roles); + +private: + void *mLibHandle; + + typedef OMX_ERRORTYPE (*InitFunc)(); + typedef OMX_ERRORTYPE (*DeinitFunc)(); + typedef OMX_ERRORTYPE (*ComponentNameEnumFunc)( + OMX_STRING, OMX_U32, OMX_U32); + + typedef OMX_ERRORTYPE (*GetHandleFunc)( + OMX_HANDLETYPE *, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE *); + + typedef OMX_ERRORTYPE (*FreeHandleFunc)(OMX_HANDLETYPE *); + + typedef OMX_ERRORTYPE (*GetRolesOfComponentFunc)( + OMX_STRING, OMX_U32 *, OMX_U8 **); + + InitFunc mInit; + DeinitFunc mDeinit; + ComponentNameEnumFunc mComponentNameEnum; + GetHandleFunc mGetHandle; + FreeHandleFunc mFreeHandle; + GetRolesOfComponentFunc mGetRolesOfComponentHandle; + + QComOMXPlugin(const QComOMXPlugin &); + QComOMXPlugin &operator=(const QComOMXPlugin &); +}; + +} // namespace android + +#endif // QCOM_OMX_PLUGIN_H_ diff --git a/mm-core/Android.mk b/mm-core/Android.mk new file mode 100644 index 0000000..22dff8b --- /dev/null +++ b/mm-core/Android.mk @@ -0,0 +1,103 @@ +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +OMXCORE_CFLAGS := -g -O3 -DVERBOSE +OMXCORE_CFLAGS += -O0 -fno-inline -fno-short-enums +OMXCORE_CFLAGS += -D_ANDROID_ +OMXCORE_CFLAGS += -U_ENABLE_QC_MSG_LOG_ + +#=============================================================================== +# Figure out the targets +#=============================================================================== + +ifeq ($(TARGET_BOARD_PLATFORM),msm7x27a) +MM_CORE_TARGET = 7627A +else ifeq ($(TARGET_BOARD_PLATFORM),msm7x30) +MM_CORE_TARGET = 7630 +else ifeq ($(TARGET_BOARD_PLATFORM),msm8660) +MM_CORE_TARGET = 8660 +#Comment out following line to disable drm.play component +OMXCORE_CFLAGS += -DENABLE_DRMPLAY +else ifeq ($(TARGET_BOARD_PLATFORM),msm8960) +MM_CORE_TARGET = 8960 +else ifeq ($(TARGET_BOARD_PLATFORM),msm8974) +MM_CORE_TARGET = 8974 +else ifeq ($(TARGET_BOARD_PLATFORM),qsd8k) +MM_CORE_TARGET = 8250 +else +MM_CORE_TARGET = default +endif + +#=============================================================================== +# Deploy the headers that can be exposed +#=============================================================================== + +LOCAL_COPY_HEADERS_TO := mm-core/omxcore +LOCAL_COPY_HEADERS := inc/OMX_Audio.h +LOCAL_COPY_HEADERS += inc/OMX_Component.h +LOCAL_COPY_HEADERS += inc/OMX_ContentPipe.h +LOCAL_COPY_HEADERS += inc/OMX_Core.h +LOCAL_COPY_HEADERS += inc/OMX_Image.h +LOCAL_COPY_HEADERS += inc/OMX_Index.h +LOCAL_COPY_HEADERS += inc/OMX_IVCommon.h +LOCAL_COPY_HEADERS += inc/OMX_Other.h +LOCAL_COPY_HEADERS += inc/OMX_QCOMExtns.h +LOCAL_COPY_HEADERS += inc/OMX_Types.h +LOCAL_COPY_HEADERS += inc/OMX_Video.h +LOCAL_COPY_HEADERS += inc/qc_omx_common.h +LOCAL_COPY_HEADERS += inc/qc_omx_component.h +LOCAL_COPY_HEADERS += inc/qc_omx_msg.h +LOCAL_COPY_HEADERS += inc/QOMX_AudioExtensions.h +LOCAL_COPY_HEADERS += inc/QOMX_AudioIndexExtensions.h +LOCAL_COPY_HEADERS += inc/OMX_CoreExt.h +LOCAL_COPY_HEADERS += inc/QOMX_CoreExtensions.h +LOCAL_COPY_HEADERS += inc/QOMX_FileFormatExtensions.h +LOCAL_COPY_HEADERS += inc/QOMX_IVCommonExtensions.h +LOCAL_COPY_HEADERS += inc/QOMX_SourceExtensions.h +LOCAL_COPY_HEADERS += inc/QOMX_VideoExtensions.h +LOCAL_COPY_HEADERS += inc/OMX_IndexExt.h +LOCAL_COPY_HEADERS += inc/QOMX_StreamingExtensions.h +LOCAL_COPY_HEADERS += inc/QCMediaDefs.h +LOCAL_COPY_HEADERS += inc/QCMetaData.h + +#=============================================================================== +# LIBRARY for Android apps +#=============================================================================== + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/src/common +LOCAL_C_INCLUDES += $(LOCAL_PATH)/inc +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOmxCore +LOCAL_MODULE_TAGS := optional +LOCAL_SHARED_LIBRARIES := liblog libdl +LOCAL_CFLAGS := $(OMXCORE_CFLAGS) + +LOCAL_SRC_FILES := src/common/omx_core_cmp.cpp +LOCAL_SRC_FILES += src/common/qc_omx_core.c +LOCAL_SRC_FILES += src/$(MM_CORE_TARGET)/qc_registry_table_android.c + +include $(BUILD_SHARED_LIBRARY) + +#=============================================================================== +# LIBRARY for command line test apps +#=============================================================================== + +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/src/common +LOCAL_C_INCLUDES += $(LOCAL_PATH)/inc +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libmm-omxcore +LOCAL_MODULE_TAGS := optional +LOCAL_SHARED_LIBRARIES := liblog libdl +LOCAL_CFLAGS := $(OMXCORE_CFLAGS) + +LOCAL_SRC_FILES := src/common/omx_core_cmp.cpp +LOCAL_SRC_FILES += src/common/qc_omx_core.c +LOCAL_SRC_FILES += src/$(MM_CORE_TARGET)/qc_registry_table.c + +include $(BUILD_SHARED_LIBRARY) + +endif #BUILD_TINY_ANDROID diff --git a/mm-core/inc/OMX_Audio.h b/mm-core/inc/OMX_Audio.h new file mode 100755 index 0000000..0d45576 --- /dev/null +++ b/mm-core/inc/OMX_Audio.h @@ -0,0 +1,1312 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** @file OMX_Audio.h - OpenMax IL version 1.1.2 + * The structures needed by Audio components to exchange + * parameters and configuration data with the componenmilts. + */ + +#ifndef OMX_Audio_h +#define OMX_Audio_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include + +/** @defgroup midi MIDI + * @ingroup audio + */ + +/** @defgroup effects Audio effects + * @ingroup audio + */ + +/** @defgroup audio OpenMAX IL Audio Domain + * Structures for OpenMAX IL Audio domain + * @{ + */ + +/** Enumeration used to define the possible audio codings. + * If "OMX_AUDIO_CodingUnused" is selected, the coding selection must + * be done in a vendor specific way. Since this is for an audio + * processing element this enum is relevant. However, for another + * type of component other enums would be in this area. + */ +typedef enum OMX_AUDIO_CODINGTYPE { + OMX_AUDIO_CodingUnused = 0, /**< Placeholder value when coding is N/A */ + OMX_AUDIO_CodingAutoDetect, /**< auto detection of audio format */ + OMX_AUDIO_CodingPCM, /**< Any variant of PCM coding */ + OMX_AUDIO_CodingADPCM, /**< Any variant of ADPCM encoded data */ + OMX_AUDIO_CodingAMR, /**< Any variant of AMR encoded data */ + OMX_AUDIO_CodingGSMFR, /**< Any variant of GSM fullrate (i.e. GSM610) */ + OMX_AUDIO_CodingGSMEFR, /**< Any variant of GSM Enhanced Fullrate encoded data*/ + OMX_AUDIO_CodingGSMHR, /**< Any variant of GSM Halfrate encoded data */ + OMX_AUDIO_CodingPDCFR, /**< Any variant of PDC Fullrate encoded data */ + OMX_AUDIO_CodingPDCEFR, /**< Any variant of PDC Enhanced Fullrate encoded data */ + OMX_AUDIO_CodingPDCHR, /**< Any variant of PDC Halfrate encoded data */ + OMX_AUDIO_CodingTDMAFR, /**< Any variant of TDMA Fullrate encoded data (TIA/EIA-136-420) */ + OMX_AUDIO_CodingTDMAEFR, /**< Any variant of TDMA Enhanced Fullrate encoded data (TIA/EIA-136-410) */ + OMX_AUDIO_CodingQCELP8, /**< Any variant of QCELP 8kbps encoded data */ + OMX_AUDIO_CodingQCELP13, /**< Any variant of QCELP 13kbps encoded data */ + OMX_AUDIO_CodingEVRC, /**< Any variant of EVRC encoded data */ + OMX_AUDIO_CodingSMV, /**< Any variant of SMV encoded data */ + OMX_AUDIO_CodingG711, /**< Any variant of G.711 encoded data */ + OMX_AUDIO_CodingG723, /**< Any variant of G.723 dot 1 encoded data */ + OMX_AUDIO_CodingG726, /**< Any variant of G.726 encoded data */ + OMX_AUDIO_CodingG729, /**< Any variant of G.729 encoded data */ + OMX_AUDIO_CodingAAC, /**< Any variant of AAC encoded data */ + OMX_AUDIO_CodingMP3, /**< Any variant of MP3 encoded data */ + OMX_AUDIO_CodingSBC, /**< Any variant of SBC encoded data */ + OMX_AUDIO_CodingVORBIS, /**< Any variant of VORBIS encoded data */ + OMX_AUDIO_CodingWMA, /**< Any variant of WMA encoded data */ + OMX_AUDIO_CodingRA, /**< Any variant of RA encoded data */ + OMX_AUDIO_CodingMIDI, /**< Any variant of MIDI encoded data */ + OMX_AUDIO_CodingAC3, /**< Any variant of AC3 encoded data */ + OMX_AUDIO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_CodingMax = 0x7FFFFFFF +} OMX_AUDIO_CODINGTYPE; + + +/** The PortDefinition structure is used to define all of the parameters + * necessary for the compliant component to setup an input or an output audio + * path. If additional information is needed to define the parameters of the + * port (such as frequency), additional structures must be sent such as the + * OMX_AUDIO_PARAM_PCMMODETYPE structure to supply the extra parameters for the port. + */ +typedef struct OMX_AUDIO_PORTDEFINITIONTYPE { + OMX_STRING cMIMEType; /**< MIME type of data for the port */ + OMX_NATIVE_DEVICETYPE pNativeRender; /** < platform specific reference + for an output device, + otherwise this field is 0 */ + OMX_BOOL bFlagErrorConcealment; /**< Turns on error concealment if it is + supported by the OMX component */ + OMX_AUDIO_CODINGTYPE eEncoding; /**< Type of data expected for this + port (e.g. PCM, AMR, MP3, etc) */ +} OMX_AUDIO_PORTDEFINITIONTYPE; + + +/** Port format parameter. This structure is used to enumerate + * the various data input/output format supported by the port. + */ +typedef struct OMX_AUDIO_PARAM_PORTFORMATTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Indicates which port to set */ + OMX_U32 nIndex; /**< Indicates the enumeration index for the format from 0x0 to N-1 */ + OMX_AUDIO_CODINGTYPE eEncoding; /**< Type of data expected for this port (e.g. PCM, AMR, MP3, etc) */ +} OMX_AUDIO_PARAM_PORTFORMATTYPE; + + +/** PCM mode type */ +typedef enum OMX_AUDIO_PCMMODETYPE { + OMX_AUDIO_PCMModeLinear = 0, /**< Linear PCM encoded data */ + OMX_AUDIO_PCMModeALaw, /**< A law PCM encoded data (G.711) */ + OMX_AUDIO_PCMModeMULaw, /**< Mu law PCM encoded data (G.711) */ + OMX_AUDIO_PCMModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_PCMModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_PCMModeMax = 0x7FFFFFFF +} OMX_AUDIO_PCMMODETYPE; + + +typedef enum OMX_AUDIO_CHANNELTYPE { + OMX_AUDIO_ChannelNone = 0x0, /**< Unused or empty */ + OMX_AUDIO_ChannelLF = 0x1, /**< Left front */ + OMX_AUDIO_ChannelRF = 0x2, /**< Right front */ + OMX_AUDIO_ChannelCF = 0x3, /**< Center front */ + OMX_AUDIO_ChannelLS = 0x4, /**< Left surround */ + OMX_AUDIO_ChannelRS = 0x5, /**< Right surround */ + OMX_AUDIO_ChannelLFE = 0x6, /**< Low frequency effects */ + OMX_AUDIO_ChannelCS = 0x7, /**< Back surround */ + OMX_AUDIO_ChannelLR = 0x8, /**< Left rear. */ + OMX_AUDIO_ChannelRR = 0x9, /**< Right rear. */ + OMX_AUDIO_ChannelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_ChannelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_ChannelMax = 0x7FFFFFFF +} OMX_AUDIO_CHANNELTYPE; + +#define OMX_AUDIO_MAXCHANNELS 16 /**< maximum number distinct audio channels that a buffer may contain */ +#define OMX_MIN_PCMPAYLOAD_MSEC 5 /**< Minimum audio buffer payload size for uncompressed (PCM) audio */ + +/** PCM format description */ +typedef struct OMX_AUDIO_PARAM_PCMMODETYPE { + OMX_U32 nSize; /**< Size of this structure, in Bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels (e.g. 2 for stereo) */ + OMX_NUMERICALDATATYPE eNumData; /**< indicates PCM data as signed or unsigned */ + OMX_ENDIANTYPE eEndian; /**< indicates PCM data as little or big endian */ + OMX_BOOL bInterleaved; /**< True for normal interleaved data; false for + non-interleaved data (e.g. block data) */ + OMX_U32 nBitPerSample; /**< Bit per sample */ + OMX_U32 nSamplingRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ + OMX_AUDIO_PCMMODETYPE ePCMMode; /**< PCM mode enumeration */ + OMX_AUDIO_CHANNELTYPE eChannelMapping[OMX_AUDIO_MAXCHANNELS]; /**< Slot i contains channel defined by eChannelMap[i] */ + +} OMX_AUDIO_PARAM_PCMMODETYPE; + + +/** Audio channel mode. This is used by both AAC and MP3, although the names are more appropriate + * for the MP3. For example, JointStereo for MP3 is CouplingChannels for AAC. + */ +typedef enum OMX_AUDIO_CHANNELMODETYPE { + OMX_AUDIO_ChannelModeStereo = 0, /**< 2 channels, the bitrate allocation between those + two channels changes accordingly to each channel information */ + OMX_AUDIO_ChannelModeJointStereo, /**< mode that takes advantage of what is common between + 2 channels for higher compression gain */ + OMX_AUDIO_ChannelModeDual, /**< 2 mono-channels, each channel is encoded with half + the bitrate of the overall bitrate */ + OMX_AUDIO_ChannelModeMono, /**< Mono channel mode */ + OMX_AUDIO_ChannelModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_ChannelModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_ChannelModeMax = 0x7FFFFFFF +} OMX_AUDIO_CHANNELMODETYPE; + + +typedef enum OMX_AUDIO_MP3STREAMFORMATTYPE { + OMX_AUDIO_MP3StreamFormatMP1Layer3 = 0, /**< MP3 Audio MPEG 1 Layer 3 Stream format */ + OMX_AUDIO_MP3StreamFormatMP2Layer3, /**< MP3 Audio MPEG 2 Layer 3 Stream format */ + OMX_AUDIO_MP3StreamFormatMP2_5Layer3, /**< MP3 Audio MPEG2.5 Layer 3 Stream format */ + OMX_AUDIO_MP3StreamFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_MP3StreamFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_MP3StreamFormatMax = 0x7FFFFFFF +} OMX_AUDIO_MP3STREAMFORMATTYPE; + +/** MP3 params */ +typedef struct OMX_AUDIO_PARAM_MP3TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable + rate or unknown bit rates */ + OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ + OMX_U32 nAudioBandWidth; /**< Audio band width (in Hz) to which an encoder should + limit the audio signal. Use 0 to let encoder decide */ + OMX_AUDIO_CHANNELMODETYPE eChannelMode; /**< Channel mode enumeration */ + OMX_AUDIO_MP3STREAMFORMATTYPE eFormat; /**< MP3 stream format */ +} OMX_AUDIO_PARAM_MP3TYPE; + + +typedef enum OMX_AUDIO_AACSTREAMFORMATTYPE { + OMX_AUDIO_AACStreamFormatMP2ADTS = 0, /**< AAC Audio Data Transport Stream 2 format */ + OMX_AUDIO_AACStreamFormatMP4ADTS, /**< AAC Audio Data Transport Stream 4 format */ + OMX_AUDIO_AACStreamFormatMP4LOAS, /**< AAC Low Overhead Audio Stream format */ + OMX_AUDIO_AACStreamFormatMP4LATM, /**< AAC Low overhead Audio Transport Multiplex */ + OMX_AUDIO_AACStreamFormatADIF, /**< AAC Audio Data Interchange Format */ + OMX_AUDIO_AACStreamFormatMP4FF, /**< AAC inside MPEG-4/ISO File Format */ + OMX_AUDIO_AACStreamFormatRAW, /**< AAC Raw Format */ + OMX_AUDIO_AACStreamFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_AACStreamFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_AACStreamFormatMax = 0x7FFFFFFF +} OMX_AUDIO_AACSTREAMFORMATTYPE; + + +/** AAC mode type. Note that the term profile is used with the MPEG-2 + * standard and the term object type and profile is used with MPEG-4 */ +typedef enum OMX_AUDIO_AACPROFILETYPE{ + OMX_AUDIO_AACObjectNull = 0, /**< Null, not used */ + OMX_AUDIO_AACObjectMain = 1, /**< AAC Main object */ + OMX_AUDIO_AACObjectLC, /**< AAC Low Complexity object (AAC profile) */ + OMX_AUDIO_AACObjectSSR, /**< AAC Scalable Sample Rate object */ + OMX_AUDIO_AACObjectLTP, /**< AAC Long Term Prediction object */ + OMX_AUDIO_AACObjectHE, /**< AAC High Efficiency (object type SBR, HE-AAC profile) */ + OMX_AUDIO_AACObjectScalable, /**< AAC Scalable object */ + OMX_AUDIO_AACObjectERLC = 17, /**< ER AAC Low Complexity object (Error Resilient AAC-LC) */ + OMX_AUDIO_AACObjectLD = 23, /**< AAC Low Delay object (Error Resilient) */ + OMX_AUDIO_AACObjectHE_PS = 29, /**< AAC High Efficiency with Parametric Stereo coding (HE-AAC v2, object type PS) */ + OMX_AUDIO_AACObjectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_AACObjectVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_AACObjectMax = 0x7FFFFFFF +} OMX_AUDIO_AACPROFILETYPE; + + +/** AAC tool usage (for nAACtools in OMX_AUDIO_PARAM_AACPROFILETYPE). + * Required for encoder configuration and optional as decoder info output. + * For MP3, OMX_AUDIO_CHANNELMODETYPE is sufficient. */ +#define OMX_AUDIO_AACToolNone 0x00000000 /**< no AAC tools allowed (encoder config) or active (decoder info output) */ +#define OMX_AUDIO_AACToolMS 0x00000001 /**< MS: Mid/side joint coding tool allowed or active */ +#define OMX_AUDIO_AACToolIS 0x00000002 /**< IS: Intensity stereo tool allowed or active */ +#define OMX_AUDIO_AACToolTNS 0x00000004 /**< TNS: Temporal Noise Shaping tool allowed or active */ +#define OMX_AUDIO_AACToolPNS 0x00000008 /**< PNS: MPEG-4 Perceptual Noise substitution tool allowed or active */ +#define OMX_AUDIO_AACToolLTP 0x00000010 /**< LTP: MPEG-4 Long Term Prediction tool allowed or active */ +#define OMX_AUDIO_AACToolAll 0x7FFFFFFF /**< all AAC tools allowed or active (*/ + +/** MPEG-4 AAC error resilience (ER) tool usage (for nAACERtools in OMX_AUDIO_PARAM_AACPROFILETYPE). + * Required for ER encoder configuration and optional as decoder info output */ +#define OMX_AUDIO_AACERNone 0x00000000 /**< no AAC ER tools allowed/used */ +#define OMX_AUDIO_AACERVCB11 0x00000001 /**< VCB11: Virtual Code Books for AAC section data */ +#define OMX_AUDIO_AACERRVLC 0x00000002 /**< RVLC: Reversible Variable Length Coding */ +#define OMX_AUDIO_AACERHCR 0x00000004 /**< HCR: Huffman Codeword Reordering */ +#define OMX_AUDIO_AACERAll 0x7FFFFFFF /**< all AAC ER tools allowed/used */ + + +/** AAC params */ +typedef struct OMX_AUDIO_PARAM_AACPROFILETYPE { + OMX_U32 nSize; /**< Size of this structure, in Bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ + OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable + rate or unknown bit rates */ + OMX_U32 nAudioBandWidth; /**< Audio band width (in Hz) to which an encoder should + limit the audio signal. Use 0 to let encoder decide */ + OMX_U32 nFrameLength; /**< Frame length (in audio samples per channel) of the codec. + Can be 1024 or 960 (AAC-LC), 2048 (HE-AAC), 480 or 512 (AAC-LD). + Use 0 to let encoder decide */ + OMX_U32 nAACtools; /**< AAC tool usage */ + OMX_U32 nAACERtools; /**< MPEG-4 AAC error resilience tool usage */ + OMX_AUDIO_AACPROFILETYPE eAACProfile; /**< AAC profile enumeration */ + OMX_AUDIO_AACSTREAMFORMATTYPE eAACStreamFormat; /**< AAC stream format enumeration */ + OMX_AUDIO_CHANNELMODETYPE eChannelMode; /**< Channel mode enumeration */ +} OMX_AUDIO_PARAM_AACPROFILETYPE; + + +/** VORBIS params */ +typedef struct OMX_AUDIO_PARAM_VORBISTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nBitRate; /**< Bit rate of the encoded data data. Use 0 for variable + rate or unknown bit rates. Encoding is set to the + bitrate closest to specified value (in bps) */ + OMX_U32 nMinBitRate; /**< Sets minimum bitrate (in bps). */ + OMX_U32 nMaxBitRate; /**< Sets maximum bitrate (in bps). */ + + OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ + OMX_U32 nAudioBandWidth; /**< Audio band width (in Hz) to which an encoder should + limit the audio signal. Use 0 to let encoder decide */ + OMX_S32 nQuality; /**< Sets encoding quality to n, between -1 (low) and 10 (high). + In the default mode of operation, teh quality level is 3. + Normal quality range is 0 - 10. */ + OMX_BOOL bManaged; /**< Set bitrate management mode. This turns off the + normal VBR encoding, but allows hard or soft bitrate + constraints to be enforced by the encoder. This mode can + be slower, and may also be lower quality. It is + primarily useful for streaming. */ + OMX_BOOL bDownmix; /**< Downmix input from stereo to mono (has no effect on + non-stereo streams). Useful for lower-bitrate encoding. */ +} OMX_AUDIO_PARAM_VORBISTYPE; + + +/** WMA Version */ +typedef enum OMX_AUDIO_WMAFORMATTYPE { + OMX_AUDIO_WMAFormatUnused = 0, /**< format unused or unknown */ + OMX_AUDIO_WMAFormat7, /**< Windows Media Audio format 7 */ + OMX_AUDIO_WMAFormat8, /**< Windows Media Audio format 8 */ + OMX_AUDIO_WMAFormat9, /**< Windows Media Audio format 9 */ + OMX_AUDIO_WMAFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_WMAFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_WMAFormatMax = 0x7FFFFFFF +} OMX_AUDIO_WMAFORMATTYPE; + + +/** WMA Profile */ +typedef enum OMX_AUDIO_WMAPROFILETYPE { + OMX_AUDIO_WMAProfileUnused = 0, /**< profile unused or unknown */ + OMX_AUDIO_WMAProfileL1, /**< Windows Media audio version 9 profile L1 */ + OMX_AUDIO_WMAProfileL2, /**< Windows Media audio version 9 profile L2 */ + OMX_AUDIO_WMAProfileL3, /**< Windows Media audio version 9 profile L3 */ + OMX_AUDIO_WMAProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_WMAProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_WMAProfileMax = 0x7FFFFFFF +} OMX_AUDIO_WMAPROFILETYPE; + + +/** WMA params */ +typedef struct OMX_AUDIO_PARAM_WMATYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U16 nChannels; /**< Number of channels */ + OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable + rate or unknown bit rates */ + OMX_AUDIO_WMAFORMATTYPE eFormat; /**< Version of WMA stream / data */ + OMX_AUDIO_WMAPROFILETYPE eProfile; /**< Profile of WMA stream / data */ + OMX_U32 nSamplingRate; /**< Sampling rate of the source data */ + OMX_U16 nBlockAlign; /**< is the block alignment, or block size, in bytes of the audio codec */ + OMX_U16 nEncodeOptions; /**< WMA Type-specific data */ + OMX_U32 nSuperBlockAlign; /**< WMA Type-specific data */ +} OMX_AUDIO_PARAM_WMATYPE; + +/** + * RealAudio format + */ +typedef enum OMX_AUDIO_RAFORMATTYPE { + OMX_AUDIO_RAFormatUnused = 0, /**< Format unused or unknown */ + OMX_AUDIO_RA8, /**< RealAudio 8 codec */ + OMX_AUDIO_RA9, /**< RealAudio 9 codec */ + OMX_AUDIO_RA10_AAC, /**< MPEG-4 AAC codec for bitrates of more than 128kbps */ + OMX_AUDIO_RA10_CODEC, /**< RealAudio codec for bitrates less than 128 kbps */ + OMX_AUDIO_RA10_LOSSLESS, /**< RealAudio Lossless */ + OMX_AUDIO_RA10_MULTICHANNEL, /**< RealAudio Multichannel */ + OMX_AUDIO_RA10_VOICE, /**< RealAudio Voice for bitrates below 15 kbps */ + OMX_AUDIO_RAFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_RAFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_RAFormatMax = 0x7FFFFFFF +} OMX_AUDIO_RAFORMATTYPE; + +/** RA (Real Audio) params */ +typedef struct OMX_AUDIO_PARAM_RATYPE { + OMX_U32 nSize; /**< Size of this structure, in Bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nSamplingRate; /**< is the sampling rate of the source data */ + OMX_U32 nBitsPerFrame; /**< is the value for bits per frame */ + OMX_U32 nSamplePerFrame; /**< is the value for samples per frame */ + OMX_U32 nCouplingQuantBits; /**< is the number of coupling quantization bits in the stream */ + OMX_U32 nCouplingStartRegion; /**< is the coupling start region in the stream */ + OMX_U32 nNumRegions; /**< is the number of regions value */ + OMX_AUDIO_RAFORMATTYPE eFormat; /**< is the RealAudio audio format */ +} OMX_AUDIO_PARAM_RATYPE; + + +/** SBC Allocation Method Type */ +typedef enum OMX_AUDIO_SBCALLOCMETHODTYPE { + OMX_AUDIO_SBCAllocMethodLoudness, /**< Loudness allocation method */ + OMX_AUDIO_SBCAllocMethodSNR, /**< SNR allocation method */ + OMX_AUDIO_SBCAllocMethodKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_SBCAllocMethodVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_SBCAllocMethodMax = 0x7FFFFFFF +} OMX_AUDIO_SBCALLOCMETHODTYPE; + + +/** SBC params */ +typedef struct OMX_AUDIO_PARAM_SBCTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable + rate or unknown bit rates */ + OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ + OMX_U32 nBlocks; /**< Number of blocks */ + OMX_U32 nSubbands; /**< Number of subbands */ + OMX_U32 nBitPool; /**< Bitpool value */ + OMX_BOOL bEnableBitrate; /**< Use bitrate value instead of bitpool */ + OMX_AUDIO_CHANNELMODETYPE eChannelMode; /**< Channel mode enumeration */ + OMX_AUDIO_SBCALLOCMETHODTYPE eSBCAllocType; /**< SBC Allocation method type */ +} OMX_AUDIO_PARAM_SBCTYPE; + + +/** ADPCM stream format parameters */ +typedef struct OMX_AUDIO_PARAM_ADPCMTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_U32 nBitsPerSample; /**< Number of bits in each sample */ + OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ +} OMX_AUDIO_PARAM_ADPCMTYPE; + + +/** G723 rate */ +typedef enum OMX_AUDIO_G723RATE { + OMX_AUDIO_G723ModeUnused = 0, /**< AMRNB Mode unused / unknown */ + OMX_AUDIO_G723ModeLow, /**< 5300 bps */ + OMX_AUDIO_G723ModeHigh, /**< 6300 bps */ + OMX_AUDIO_G723ModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_G723ModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_G723ModeMax = 0x7FFFFFFF +} OMX_AUDIO_G723RATE; + + +/** G723 - Sample rate must be 8 KHz */ +typedef struct OMX_AUDIO_PARAM_G723TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_AUDIO_G723RATE eBitRate; /**< todo: Should this be moved to a config? */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ + OMX_BOOL bPostFilter; /**< Enable Post Filter */ +} OMX_AUDIO_PARAM_G723TYPE; + + +/** ITU G726 (ADPCM) rate */ +typedef enum OMX_AUDIO_G726MODE { + OMX_AUDIO_G726ModeUnused = 0, /**< G726 Mode unused / unknown */ + OMX_AUDIO_G726Mode16, /**< 16 kbps */ + OMX_AUDIO_G726Mode24, /**< 24 kbps */ + OMX_AUDIO_G726Mode32, /**< 32 kbps, most common rate, also G721 */ + OMX_AUDIO_G726Mode40, /**< 40 kbps */ + OMX_AUDIO_G726ModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_G726ModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_G726ModeMax = 0x7FFFFFFF +} OMX_AUDIO_G726MODE; + + +/** G.726 stream format parameters - must be at 8KHz */ +typedef struct OMX_AUDIO_PARAM_G726TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_AUDIO_G726MODE eG726Mode; +} OMX_AUDIO_PARAM_G726TYPE; + + +/** G729 coder type */ +typedef enum OMX_AUDIO_G729TYPE { + OMX_AUDIO_G729 = 0, /**< ITU G.729 encoded data */ + OMX_AUDIO_G729A, /**< ITU G.729 annex A encoded data */ + OMX_AUDIO_G729B, /**< ITU G.729 with annex B encoded data */ + OMX_AUDIO_G729AB, /**< ITU G.729 annexes A and B encoded data */ + OMX_AUDIO_G729KhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_G729VendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_G729Max = 0x7FFFFFFF +} OMX_AUDIO_G729TYPE; + + +/** G729 stream format parameters - fixed 6KHz sample rate */ +typedef struct OMX_AUDIO_PARAM_G729TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_AUDIO_G729TYPE eBitType; +} OMX_AUDIO_PARAM_G729TYPE; + + +/** AMR Frame format */ +typedef enum OMX_AUDIO_AMRFRAMEFORMATTYPE { + OMX_AUDIO_AMRFrameFormatConformance = 0, /**< Frame Format is AMR Conformance + (Standard) Format */ + OMX_AUDIO_AMRFrameFormatIF1, /**< Frame Format is AMR Interface + Format 1 */ + OMX_AUDIO_AMRFrameFormatIF2, /**< Frame Format is AMR Interface + Format 2*/ + OMX_AUDIO_AMRFrameFormatFSF, /**< Frame Format is AMR File Storage + Format */ + OMX_AUDIO_AMRFrameFormatRTPPayload, /**< Frame Format is AMR Real-Time + Transport Protocol Payload Format */ + OMX_AUDIO_AMRFrameFormatITU, /**< Frame Format is ITU Format (added at Motorola request) */ + OMX_AUDIO_AMRFrameFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_AMRFrameFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_AMRFrameFormatMax = 0x7FFFFFFF +} OMX_AUDIO_AMRFRAMEFORMATTYPE; + + +/** AMR band mode */ +typedef enum OMX_AUDIO_AMRBANDMODETYPE { + OMX_AUDIO_AMRBandModeUnused = 0, /**< AMRNB Mode unused / unknown */ + OMX_AUDIO_AMRBandModeNB0, /**< AMRNB Mode 0 = 4750 bps */ + OMX_AUDIO_AMRBandModeNB1, /**< AMRNB Mode 1 = 5150 bps */ + OMX_AUDIO_AMRBandModeNB2, /**< AMRNB Mode 2 = 5900 bps */ + OMX_AUDIO_AMRBandModeNB3, /**< AMRNB Mode 3 = 6700 bps */ + OMX_AUDIO_AMRBandModeNB4, /**< AMRNB Mode 4 = 7400 bps */ + OMX_AUDIO_AMRBandModeNB5, /**< AMRNB Mode 5 = 7950 bps */ + OMX_AUDIO_AMRBandModeNB6, /**< AMRNB Mode 6 = 10200 bps */ + OMX_AUDIO_AMRBandModeNB7, /**< AMRNB Mode 7 = 12200 bps */ + OMX_AUDIO_AMRBandModeWB0, /**< AMRWB Mode 0 = 6600 bps */ + OMX_AUDIO_AMRBandModeWB1, /**< AMRWB Mode 1 = 8850 bps */ + OMX_AUDIO_AMRBandModeWB2, /**< AMRWB Mode 2 = 12650 bps */ + OMX_AUDIO_AMRBandModeWB3, /**< AMRWB Mode 3 = 14250 bps */ + OMX_AUDIO_AMRBandModeWB4, /**< AMRWB Mode 4 = 15850 bps */ + OMX_AUDIO_AMRBandModeWB5, /**< AMRWB Mode 5 = 18250 bps */ + OMX_AUDIO_AMRBandModeWB6, /**< AMRWB Mode 6 = 19850 bps */ + OMX_AUDIO_AMRBandModeWB7, /**< AMRWB Mode 7 = 23050 bps */ + OMX_AUDIO_AMRBandModeWB8, /**< AMRWB Mode 8 = 23850 bps */ + OMX_AUDIO_AMRBandModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_AMRBandModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_AMRBandModeMax = 0x7FFFFFFF +} OMX_AUDIO_AMRBANDMODETYPE; + + +/** AMR Discontinuous Transmission mode */ +typedef enum OMX_AUDIO_AMRDTXMODETYPE { + OMX_AUDIO_AMRDTXModeOff = 0, /**< AMR Discontinuous Transmission Mode is disabled */ + OMX_AUDIO_AMRDTXModeOnVAD1, /**< AMR Discontinuous Transmission Mode using + Voice Activity Detector 1 (VAD1) is enabled */ + OMX_AUDIO_AMRDTXModeOnVAD2, /**< AMR Discontinuous Transmission Mode using + Voice Activity Detector 2 (VAD2) is enabled */ + OMX_AUDIO_AMRDTXModeOnAuto, /**< The codec will automatically select between + Off, VAD1 or VAD2 modes */ + + OMX_AUDIO_AMRDTXasEFR, /**< DTX as EFR instead of AMR standard (3GPP 26.101, frame type =8,9,10) */ + + OMX_AUDIO_AMRDTXModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_AMRDTXModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_AMRDTXModeMax = 0x7FFFFFFF +} OMX_AUDIO_AMRDTXMODETYPE; + + +/** AMR params */ +typedef struct OMX_AUDIO_PARAM_AMRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nBitRate; /**< Bit rate read only field */ + OMX_AUDIO_AMRBANDMODETYPE eAMRBandMode; /**< AMR Band Mode enumeration */ + OMX_AUDIO_AMRDTXMODETYPE eAMRDTXMode; /**< AMR DTX Mode enumeration */ + OMX_AUDIO_AMRFRAMEFORMATTYPE eAMRFrameFormat; /**< AMR frame format enumeration */ +} OMX_AUDIO_PARAM_AMRTYPE; + + +/** GSM_FR (ETSI 06.10, 3GPP 46.010) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_GSMFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_GSMFRTYPE; + + +/** GSM-HR (ETSI 06.20, 3GPP 46.020) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_GSMHRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_GSMHRTYPE; + + +/** GSM-EFR (ETSI 06.60, 3GPP 46.060) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_GSMEFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_GSMEFRTYPE; + + +/** TDMA FR (TIA/EIA-136-420, VSELP 7.95kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_TDMAFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_TDMAFRTYPE; + + +/** TDMA EFR (TIA/EIA-136-410, ACELP 7.4kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_TDMAEFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_TDMAEFRTYPE; + + +/** PDC FR ( RCR-27, VSELP 6.7kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_PDCFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_PDCFRTYPE; + + +/** PDC EFR ( RCR-27, ACELP 6.7kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_PDCEFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_PDCEFRTYPE; + +/** PDC HR ( RCR-27, PSI-CELP 3.45kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_PDCHRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_PDCHRTYPE; + + +/** CDMA Rate types */ +typedef enum OMX_AUDIO_CDMARATETYPE { + OMX_AUDIO_CDMARateBlank = 0, /**< CDMA encoded frame is blank */ + OMX_AUDIO_CDMARateFull, /**< CDMA encoded frame in full rate */ + OMX_AUDIO_CDMARateHalf, /**< CDMA encoded frame in half rate */ + OMX_AUDIO_CDMARateQuarter, /**< CDMA encoded frame in quarter rate */ + OMX_AUDIO_CDMARateEighth, /**< CDMA encoded frame in eighth rate (DTX)*/ + OMX_AUDIO_CDMARateErasure, /**< CDMA erasure frame */ + OMX_AUDIO_CDMARateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_CDMARateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_CDMARateMax = 0x7FFFFFFF +} OMX_AUDIO_CDMARATETYPE; + + +/** QCELP8 (TIA/EIA-96, up to 8kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_QCELP8TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable + rate or unknown bit rates */ + OMX_AUDIO_CDMARATETYPE eCDMARate; /**< Frame rate */ + OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 */ + OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 */ +} OMX_AUDIO_PARAM_QCELP8TYPE; + + +/** QCELP13 ( CDMA, EIA/TIA-733, 13.3kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_QCELP13TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_AUDIO_CDMARATETYPE eCDMARate; /**< Frame rate */ + OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 */ + OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 */ +} OMX_AUDIO_PARAM_QCELP13TYPE; + + +/** EVRC ( CDMA, EIA/TIA-127, RCELP up to 8.55kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_EVRCTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_AUDIO_CDMARATETYPE eCDMARate; /**< actual Frame rate */ + OMX_BOOL bRATE_REDUCon; /**< RATE_REDUCtion is requested for this frame */ + OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 */ + OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 */ + OMX_BOOL bHiPassFilter; /**< Enable encoder's High Pass Filter */ + OMX_BOOL bNoiseSuppressor; /**< Enable encoder's noise suppressor pre-processing */ + OMX_BOOL bPostFilter; /**< Enable decoder's post Filter */ +} OMX_AUDIO_PARAM_EVRCTYPE; + + +/** SMV ( up to 8.55kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_SMVTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_AUDIO_CDMARATETYPE eCDMARate; /**< Frame rate */ + OMX_BOOL bRATE_REDUCon; /**< RATE_REDUCtion is requested for this frame */ + OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 ??*/ + OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 ??*/ + OMX_BOOL bHiPassFilter; /**< Enable encoder's High Pass Filter ??*/ + OMX_BOOL bNoiseSuppressor; /**< Enable encoder's noise suppressor pre-processing */ + OMX_BOOL bPostFilter; /**< Enable decoder's post Filter ??*/ +} OMX_AUDIO_PARAM_SMVTYPE; + + +/** MIDI Format + * @ingroup midi + */ +typedef enum OMX_AUDIO_MIDIFORMATTYPE +{ + OMX_AUDIO_MIDIFormatUnknown = 0, /**< MIDI Format unknown or don't care */ + OMX_AUDIO_MIDIFormatSMF0, /**< Standard MIDI File Type 0 */ + OMX_AUDIO_MIDIFormatSMF1, /**< Standard MIDI File Type 1 */ + OMX_AUDIO_MIDIFormatSMF2, /**< Standard MIDI File Type 2 */ + OMX_AUDIO_MIDIFormatSPMIDI, /**< SP-MIDI */ + OMX_AUDIO_MIDIFormatXMF0, /**< eXtensible Music Format type 0 */ + OMX_AUDIO_MIDIFormatXMF1, /**< eXtensible Music Format type 1 */ + OMX_AUDIO_MIDIFormatMobileXMF, /**< Mobile XMF (eXtensible Music Format type 2) */ + OMX_AUDIO_MIDIFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_MIDIFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_MIDIFormatMax = 0x7FFFFFFF +} OMX_AUDIO_MIDIFORMATTYPE; + + +/** MIDI params + * @ingroup midi + */ +typedef struct OMX_AUDIO_PARAM_MIDITYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nFileSize; /**< size of the MIDI file in bytes, where the entire + MIDI file passed in, otherwise if 0x0, the MIDI data + is merged and streamed (instead of passed as an + entire MIDI file) */ + OMX_BU32 sMaxPolyphony; /**< Specifies the maximum simultaneous polyphonic + voices. A value of zero indicates that the default + polyphony of the device is used */ + OMX_BOOL bLoadDefaultSound; /**< Whether to load default sound + bank at initialization */ + OMX_AUDIO_MIDIFORMATTYPE eMidiFormat; /**< Version of the MIDI file */ +} OMX_AUDIO_PARAM_MIDITYPE; + + +/** Type of the MIDI sound bank + * @ingroup midi + */ +typedef enum OMX_AUDIO_MIDISOUNDBANKTYPE { + OMX_AUDIO_MIDISoundBankUnused = 0, /**< unused/unknown soundbank type */ + OMX_AUDIO_MIDISoundBankDLS1, /**< DLS version 1 */ + OMX_AUDIO_MIDISoundBankDLS2, /**< DLS version 2 */ + OMX_AUDIO_MIDISoundBankMobileDLSBase, /**< Mobile DLS, using the base functionality */ + OMX_AUDIO_MIDISoundBankMobileDLSPlusOptions, /**< Mobile DLS, using the specification-defined optional feature set */ + OMX_AUDIO_MIDISoundBankKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_MIDISoundBankVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_MIDISoundBankMax = 0x7FFFFFFF +} OMX_AUDIO_MIDISOUNDBANKTYPE; + + +/** Bank Layout describes how bank MSB & LSB are used in the DLS instrument definitions sound bank + * @ingroup midi + */ +typedef enum OMX_AUDIO_MIDISOUNDBANKLAYOUTTYPE { + OMX_AUDIO_MIDISoundBankLayoutUnused = 0, /**< unused/unknown soundbank type */ + OMX_AUDIO_MIDISoundBankLayoutGM, /**< GS layout (based on bank MSB 0x00) */ + OMX_AUDIO_MIDISoundBankLayoutGM2, /**< General MIDI 2 layout (using MSB 0x78/0x79, LSB 0x00) */ + OMX_AUDIO_MIDISoundBankLayoutUser, /**< Does not conform to any bank numbering standards */ + OMX_AUDIO_MIDISoundBankLayoutKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_MIDISoundBankLayoutVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_MIDISoundBankLayoutMax = 0x7FFFFFFF +} OMX_AUDIO_MIDISOUNDBANKLAYOUTTYPE; + + +/** MIDI params to load/unload user soundbank + * @ingroup midi + */ +typedef struct OMX_AUDIO_PARAM_MIDILOADUSERSOUNDTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nDLSIndex; /**< DLS file index to be loaded */ + OMX_U32 nDLSSize; /**< Size in bytes */ + OMX_PTR pDLSData; /**< Pointer to DLS file data */ + OMX_AUDIO_MIDISOUNDBANKTYPE eMidiSoundBank; /**< Midi sound bank type enumeration */ + OMX_AUDIO_MIDISOUNDBANKLAYOUTTYPE eMidiSoundBankLayout; /**< Midi sound bank layout enumeration */ +} OMX_AUDIO_PARAM_MIDILOADUSERSOUNDTYPE; + + +/** Structure for Live MIDI events and MIP messages. + * (MIP = Maximum Instantaneous Polyphony; part of the SP-MIDI standard.) + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDIIMMEDIATEEVENTTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_U32 nMidiEventSize; /**< Size of immediate MIDI events or MIP message in bytes */ + OMX_U8 nMidiEvents[1]; /**< MIDI event array to be rendered immediately, or an + array for the MIP message buffer, where the size is + indicated by nMidiEventSize */ +} OMX_AUDIO_CONFIG_MIDIIMMEDIATEEVENTTYPE; + + +/** MIDI sound bank/ program pair in a given channel + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDISOUNDBANKPROGRAMTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_U32 nChannel; /**< Valid channel values range from 1 to 16 */ + OMX_U16 nIDProgram; /**< Valid program ID range is 1 to 128 */ + OMX_U16 nIDSoundBank; /**< Sound bank ID */ + OMX_U32 nUserSoundBankIndex;/**< User soundbank index, easier to access soundbanks + by index if multiple banks are present */ +} OMX_AUDIO_CONFIG_MIDISOUNDBANKPROGRAMTYPE; + + +/** MIDI control + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDICONTROLTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BS32 sPitchTransposition; /**< Pitch transposition in semitones, stored as Q22.10 + format based on JAVA MMAPI (JSR-135) requirement */ + OMX_BU32 sPlayBackRate; /**< Relative playback rate, stored as Q14.17 fixed-point + number based on JSR-135 requirement */ + OMX_BU32 sTempo ; /**< Tempo in beats per minute (BPM), stored as Q22.10 + fixed-point number based on JSR-135 requirement */ + OMX_U32 nMaxPolyphony; /**< Specifies the maximum simultaneous polyphonic + voices. A value of zero indicates that the default + polyphony of the device is used */ + OMX_U32 nNumRepeat; /**< Number of times to repeat playback */ + OMX_U32 nStopTime; /**< Time in milliseconds to indicate when playback + will stop automatically. Set to zero if not used */ + OMX_U16 nChannelMuteMask; /**< 16 bit mask for channel mute status */ + OMX_U16 nChannelSoloMask; /**< 16 bit mask for channel solo status */ + OMX_U32 nTrack0031MuteMask; /**< 32 bit mask for track mute status. Note: This is for tracks 0-31 */ + OMX_U32 nTrack3263MuteMask; /**< 32 bit mask for track mute status. Note: This is for tracks 32-63 */ + OMX_U32 nTrack0031SoloMask; /**< 32 bit mask for track solo status. Note: This is for tracks 0-31 */ + OMX_U32 nTrack3263SoloMask; /**< 32 bit mask for track solo status. Note: This is for tracks 32-63 */ + +} OMX_AUDIO_CONFIG_MIDICONTROLTYPE; + + +/** MIDI Playback States + * @ingroup midi + */ +typedef enum OMX_AUDIO_MIDIPLAYBACKSTATETYPE { + OMX_AUDIO_MIDIPlayBackStateUnknown = 0, /**< Unknown state or state does not map to + other defined states */ + OMX_AUDIO_MIDIPlayBackStateClosedEngaged, /**< No MIDI resource is currently open. + The MIDI engine is currently processing + MIDI events. */ + OMX_AUDIO_MIDIPlayBackStateParsing, /**< A MIDI resource is open and is being + primed. The MIDI engine is currently + processing MIDI events. */ + OMX_AUDIO_MIDIPlayBackStateOpenEngaged, /**< A MIDI resource is open and primed but + not playing. The MIDI engine is currently + processing MIDI events. The transition to + this state is only possible from the + OMX_AUDIO_MIDIPlayBackStatePlaying state, + when the 'playback head' reaches the end + of media data or the playback stops due + to stop time set.*/ + OMX_AUDIO_MIDIPlayBackStatePlaying, /**< A MIDI resource is open and currently + playing. The MIDI engine is currently + processing MIDI events.*/ + OMX_AUDIO_MIDIPlayBackStatePlayingPartially, /**< Best-effort playback due to SP-MIDI/DLS + resource constraints */ + OMX_AUDIO_MIDIPlayBackStatePlayingSilently, /**< Due to system resource constraints and + SP-MIDI content constraints, there is + no audible MIDI content during playback + currently. The situation may change if + resources are freed later.*/ + OMX_AUDIO_MIDIPlayBackStateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_MIDIPlayBackStateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_MIDIPlayBackStateMax = 0x7FFFFFFF +} OMX_AUDIO_MIDIPLAYBACKSTATETYPE; + + +/** MIDI status + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDISTATUSTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U16 nNumTracks; /**< Number of MIDI tracks in the file, read only field. + NOTE: May not return a meaningful value until the entire + file is parsed and buffered. */ + OMX_U32 nDuration; /**< The length of the currently open MIDI resource + in milliseconds. NOTE: May not return a meaningful value + until the entire file is parsed and buffered. */ + OMX_U32 nPosition; /**< Current Position of the MIDI resource being played + in milliseconds */ + OMX_BOOL bVibra; /**< Does Vibra track exist? NOTE: May not return a meaningful + value until the entire file is parsed and buffered. */ + OMX_U32 nNumMetaEvents; /**< Total number of MIDI Meta Events in the currently + open MIDI resource. NOTE: May not return a meaningful value + until the entire file is parsed and buffered. */ + OMX_U32 nNumActiveVoices; /**< Number of active voices in the currently playing + MIDI resource. NOTE: May not return a meaningful value until + the entire file is parsed and buffered. */ + OMX_AUDIO_MIDIPLAYBACKSTATETYPE eMIDIPlayBackState; /**< MIDI playback state enumeration, read only field */ +} OMX_AUDIO_CONFIG_MIDISTATUSTYPE; + + +/** MIDI Meta Event structure one per Meta Event. + * MIDI Meta Events are like audio metadata, except that they are interspersed + * with the MIDI content throughout the file and are not localized in the header. + * As such, it is necessary to retrieve information about these Meta Events from + * the engine, as it encounters these Meta Events within the MIDI content. + * For example, SMF files can have up to 14 types of MIDI Meta Events (copyright, + * author, default tempo, etc.) scattered throughout the file. + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDIMETAEVENTTYPE{ + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nIndex; /**< Index of Meta Event */ + OMX_U8 nMetaEventType; /**< Meta Event Type, 7bits (i.e. 0 - 127) */ + OMX_U32 nMetaEventSize; /**< size of the Meta Event in bytes */ + OMX_U32 nTrack; /**< track number for the meta event */ + OMX_U32 nPosition; /**< Position of the meta-event in milliseconds */ +} OMX_AUDIO_CONFIG_MIDIMETAEVENTTYPE; + + +/** MIDI Meta Event Data structure - one per Meta Event. + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDIMETAEVENTDATATYPE{ + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nIndex; /**< Index of Meta Event */ + OMX_U32 nMetaEventSize; /**< size of the Meta Event in bytes */ + OMX_U8 nData[1]; /**< array of one or more bytes of meta data + as indicated by the nMetaEventSize field */ +} OMX_AUDIO_CONFIG__MIDIMETAEVENTDATATYPE; + + +/** Audio Volume adjustment for a port */ +typedef struct OMX_AUDIO_CONFIG_VOLUMETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port index indicating which port to + set. Select the input port to set + just that port's volume. Select the + output port to adjust the master + volume. */ + OMX_BOOL bLinear; /**< Is the volume to be set in linear (0.100) + or logarithmic scale (mB) */ + OMX_BS32 sVolume; /**< Volume linear setting in the 0..100 range, OR + Volume logarithmic setting for this port. The values + for volume are in mB (millibels = 1/100 dB) relative + to a gain of 1 (e.g. the output is the same as the + input level). Values are in mB from nMax + (maximum volume) to nMin mB (typically negative). + Since the volume is "voltage" + and not a "power", it takes a setting of + -600 mB to decrease the volume by 1/2. If + a component cannot accurately set the + volume to the requested value, it must + set the volume to the closest value BELOW + the requested value. When getting the + volume setting, the current actual volume + must be returned. */ +} OMX_AUDIO_CONFIG_VOLUMETYPE; + + +/** Audio Volume adjustment for a channel */ +typedef struct OMX_AUDIO_CONFIG_CHANNELVOLUMETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port index indicating which port to + set. Select the input port to set + just that port's volume. Select the + output port to adjust the master + volume. */ + OMX_U32 nChannel; /**< channel to select from 0 to N-1, + using OMX_ALL to apply volume settings + to all channels */ + OMX_BOOL bLinear; /**< Is the volume to be set in linear (0.100) or + logarithmic scale (mB) */ + OMX_BS32 sVolume; /**< Volume linear setting in the 0..100 range, OR + Volume logarithmic setting for this port. + The values for volume are in mB + (millibels = 1/100 dB) relative to a gain + of 1 (e.g. the output is the same as the + input level). Values are in mB from nMax + (maximum volume) to nMin mB (typically negative). + Since the volume is "voltage" + and not a "power", it takes a setting of + -600 mB to decrease the volume by 1/2. If + a component cannot accurately set the + volume to the requested value, it must + set the volume to the closest value BELOW + the requested value. When getting the + volume setting, the current actual volume + must be returned. */ + OMX_BOOL bIsMIDI; /**< TRUE if nChannel refers to a MIDI channel, + FALSE otherwise */ +} OMX_AUDIO_CONFIG_CHANNELVOLUMETYPE; + + +/** Audio balance setting */ +typedef struct OMX_AUDIO_CONFIG_BALANCETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port index indicating which port to + set. Select the input port to set + just that port's balance. Select the + output port to adjust the master + balance. */ + OMX_S32 nBalance; /**< balance setting for this port + (-100 to 100, where -100 indicates + all left, and no right */ +} OMX_AUDIO_CONFIG_BALANCETYPE; + + +/** Audio Port mute */ +typedef struct OMX_AUDIO_CONFIG_MUTETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port index indicating which port to + set. Select the input port to set + just that port's mute. Select the + output port to adjust the master + mute. */ + OMX_BOOL bMute; /**< Mute setting for this port */ +} OMX_AUDIO_CONFIG_MUTETYPE; + + +/** Audio Channel mute */ +typedef struct OMX_AUDIO_CONFIG_CHANNELMUTETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannel; /**< channel to select from 0 to N-1, + using OMX_ALL to apply mute settings + to all channels */ + OMX_BOOL bMute; /**< Mute setting for this channel */ + OMX_BOOL bIsMIDI; /**< TRUE if nChannel refers to a MIDI channel, + FALSE otherwise */ +} OMX_AUDIO_CONFIG_CHANNELMUTETYPE; + + + +/** Enable / Disable for loudness control, which boosts bass and to a + * smaller extent high end frequencies to compensate for hearing + * ability at the extreme ends of the audio spectrum + */ +typedef struct OMX_AUDIO_CONFIG_LOUDNESSTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bLoudness; /**< Enable/disable for loudness */ +} OMX_AUDIO_CONFIG_LOUDNESSTYPE; + + +/** Enable / Disable for bass, which controls low frequencies + */ +typedef struct OMX_AUDIO_CONFIG_BASSTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for bass control */ + OMX_S32 nBass; /**< bass setting for the port, as a + continuous value from -100 to 100 + (0 means no change in bass level)*/ +} OMX_AUDIO_CONFIG_BASSTYPE; + + +/** Enable / Disable for treble, which controls high frequencies tones + */ +typedef struct OMX_AUDIO_CONFIG_TREBLETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for treble control */ + OMX_S32 nTreble; /**< treble setting for the port, as a + continuous value from -100 to 100 + (0 means no change in treble level) */ +} OMX_AUDIO_CONFIG_TREBLETYPE; + + +/** An equalizer is typically used for two reasons: to compensate for an + * sub-optimal frequency response of a system to make it sound more natural + * or to create intentionally some unnatural coloring to the sound to create + * an effect. + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_EQUALIZERTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for equalizer */ + OMX_BU32 sBandIndex; /**< Band number to be set. Upper Limit is + N-1, where N is the number of bands, lower limit is 0 */ + OMX_BU32 sCenterFreq; /**< Center frequecies in Hz. This is a + read only element and is used to determine + the lower, center and upper frequency of + this band. */ + OMX_BS32 sBandLevel; /**< band level in millibels */ +} OMX_AUDIO_CONFIG_EQUALIZERTYPE; + + +/** Stereo widening mode type + * @ingroup effects + */ +typedef enum OMX_AUDIO_STEREOWIDENINGTYPE { + OMX_AUDIO_StereoWideningHeadphones, /**< Stereo widening for loudspeakers */ + OMX_AUDIO_StereoWideningLoudspeakers, /**< Stereo widening for closely spaced loudspeakers */ + OMX_AUDIO_StereoWideningKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_StereoWideningVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_StereoWideningMax = 0x7FFFFFFF +} OMX_AUDIO_STEREOWIDENINGTYPE; + + +/** Control for stereo widening, which is a special 2-channel + * case of the audio virtualizer effect. For example, for 5.1-channel + * output, it translates to virtual surround sound. + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_STEREOWIDENINGTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for stereo widening control */ + OMX_AUDIO_STEREOWIDENINGTYPE eWideningType; /**< Stereo widening algorithm type */ + OMX_U32 nStereoWidening; /**< stereo widening setting for the port, + as a continuous value from 0 to 100 */ +} OMX_AUDIO_CONFIG_STEREOWIDENINGTYPE; + + +/** The chorus effect (or ``choralizer'') is any signal processor which makes + * one sound source (such as a voice) sound like many such sources singing + * (or playing) in unison. Since performance in unison is never exact, chorus + * effects simulate this by making independently modified copies of the input + * signal. Modifications may include (1) delay, (2) frequency shift, and + * (3) amplitude modulation. + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_CHORUSTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for chorus */ + OMX_BU32 sDelay; /**< average delay in milliseconds */ + OMX_BU32 sModulationRate; /**< rate of modulation in millihertz */ + OMX_U32 nModulationDepth; /**< depth of modulation as a percentage of + delay (i.e. 0 to 100) */ + OMX_BU32 nFeedback; /**< Feedback from chorus output to input in percentage */ +} OMX_AUDIO_CONFIG_CHORUSTYPE; + + +/** Reverberation is part of the reflected sound that follows the early + * reflections. In a typical room, this consists of a dense succession of + * echoes whose energy decays exponentially. The reverberation effect structure + * as defined here includes both (early) reflections as well as (late) reverberations. + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_REVERBERATIONTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for reverberation control */ + OMX_BS32 sRoomLevel; /**< Intensity level for the whole room effect + (i.e. both early reflections and late + reverberation) in millibels */ + OMX_BS32 sRoomHighFreqLevel; /**< Attenuation at high frequencies + relative to the intensity at low + frequencies in millibels */ + OMX_BS32 sReflectionsLevel; /**< Intensity level of early reflections + (relative to room value), in millibels */ + OMX_BU32 sReflectionsDelay; /**< Delay time of the first reflection relative + to the direct path, in milliseconds */ + OMX_BS32 sReverbLevel; /**< Intensity level of late reverberation + relative to room level, in millibels */ + OMX_BU32 sReverbDelay; /**< Time delay from the first early reflection + to the beginning of the late reverberation + section, in milliseconds */ + OMX_BU32 sDecayTime; /**< Late reverberation decay time at low + frequencies, in milliseconds */ + OMX_BU32 nDecayHighFreqRatio; /**< Ratio of high frequency decay time relative + to low frequency decay time in percent */ + OMX_U32 nDensity; /**< Modal density in the late reverberation decay, + in percent (i.e. 0 - 100) */ + OMX_U32 nDiffusion; /**< Echo density in the late reverberation decay, + in percent (i.e. 0 - 100) */ + OMX_BU32 sReferenceHighFreq; /**< Reference high frequency in Hertz. This is + the frequency used as the reference for all + the high-frequency settings above */ + +} OMX_AUDIO_CONFIG_REVERBERATIONTYPE; + + +/** Possible settings for the Echo Cancelation structure to use + * @ingroup effects + */ +typedef enum OMX_AUDIO_ECHOCANTYPE { + OMX_AUDIO_EchoCanOff = 0, /**< Echo Cancellation is disabled */ + OMX_AUDIO_EchoCanNormal, /**< Echo Cancellation normal operation - + echo from plastics and face */ + OMX_AUDIO_EchoCanHFree, /**< Echo Cancellation optimized for + Hands Free operation */ + OMX_AUDIO_EchoCanCarKit, /**< Echo Cancellation optimized for + Car Kit (longer echo) */ + OMX_AUDIO_EchoCanKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_EchoCanVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_EchoCanMax = 0x7FFFFFFF +} OMX_AUDIO_ECHOCANTYPE; + + +/** Enable / Disable for echo cancelation, which removes undesired echo's + * from the audio + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_ECHOCANCELATIONTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_AUDIO_ECHOCANTYPE eEchoCancelation; /**< Echo cancelation settings */ +} OMX_AUDIO_CONFIG_ECHOCANCELATIONTYPE; + + +/** Enable / Disable for noise reduction, which undesired noise from + * the audio + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_NOISEREDUCTIONTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bNoiseReduction; /**< Enable/disable for noise reduction */ +} OMX_AUDIO_CONFIG_NOISEREDUCTIONTYPE; + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ + diff --git a/mm-core/inc/OMX_Component.h b/mm-core/inc/OMX_Component.h new file mode 100755 index 0000000..d595640 --- /dev/null +++ b/mm-core/inc/OMX_Component.h @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_Component.h - OpenMax IL version 1.1.2 + * The OMX_Component header file contains the definitions used to define + * the public interface of a component. This header file is intended to + * be used by both the application and the component. + */ + +#ifndef OMX_Component_h +#define OMX_Component_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + + +/* Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include +#include +#include +#include + +/** @ingroup comp */ +typedef enum OMX_PORTDOMAINTYPE { + OMX_PortDomainAudio, + OMX_PortDomainVideo, + OMX_PortDomainImage, + OMX_PortDomainOther, + OMX_PortDomainKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_PortDomainVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_PortDomainMax = 0x7ffffff +} OMX_PORTDOMAINTYPE; + +/** @ingroup comp */ +typedef struct OMX_PARAM_PORTDEFINITIONTYPE { + OMX_U32 nSize; /**< Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port number the structure applies to */ + OMX_DIRTYPE eDir; /**< Direction (input or output) of this port */ + OMX_U32 nBufferCountActual; /**< The actual number of buffers allocated on this port */ + OMX_U32 nBufferCountMin; /**< The minimum number of buffers this port requires */ + OMX_U32 nBufferSize; /**< Size, in bytes, for buffers to be used for this channel */ + OMX_BOOL bEnabled; /**< Ports default to enabled and are enabled/disabled by + OMX_CommandPortEnable/OMX_CommandPortDisable. + When disabled a port is unpopulated. A disabled port + is not populated with buffers on a transition to IDLE. */ + OMX_BOOL bPopulated; /**< Port is populated with all of its buffers as indicated by + nBufferCountActual. A disabled port is always unpopulated. + An enabled port is populated on a transition to OMX_StateIdle + and unpopulated on a transition to loaded. */ + OMX_PORTDOMAINTYPE eDomain; /**< Domain of the port. Determines the contents of metadata below. */ + union { + OMX_AUDIO_PORTDEFINITIONTYPE audio; + OMX_VIDEO_PORTDEFINITIONTYPE video; + OMX_IMAGE_PORTDEFINITIONTYPE image; + OMX_OTHER_PORTDEFINITIONTYPE other; + } format; + OMX_BOOL bBuffersContiguous; + OMX_U32 nBufferAlignment; +} OMX_PARAM_PORTDEFINITIONTYPE; + +/** @ingroup comp */ +typedef struct OMX_PARAM_U32TYPE { + OMX_U32 nSize; /**< Size of this structure, in Bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nU32; /**< U32 value */ +} OMX_PARAM_U32TYPE; + +/** @ingroup rpm */ +typedef enum OMX_SUSPENSIONPOLICYTYPE { + OMX_SuspensionDisabled, /**< No suspension; v1.0 behavior */ + OMX_SuspensionEnabled, /**< Suspension allowed */ + OMX_SuspensionPolicyKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_SuspensionPolicyStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_SuspensionPolicyMax = 0x7fffffff +} OMX_SUSPENSIONPOLICYTYPE; + +/** @ingroup rpm */ +typedef struct OMX_PARAM_SUSPENSIONPOLICYTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_SUSPENSIONPOLICYTYPE ePolicy; +} OMX_PARAM_SUSPENSIONPOLICYTYPE; + +/** @ingroup rpm */ +typedef enum OMX_SUSPENSIONTYPE { + OMX_NotSuspended, /**< component is not suspended */ + OMX_Suspended, /**< component is suspended */ + OMX_SuspensionKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_SuspensionVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_SuspendMax = 0x7FFFFFFF +} OMX_SUSPENSIONTYPE; + +/** @ingroup rpm */ +typedef struct OMX_PARAM_SUSPENSIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_SUSPENSIONTYPE eType; +} OMX_PARAM_SUSPENSIONTYPE ; + +typedef struct OMX_CONFIG_BOOLEANTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bEnabled; +} OMX_CONFIG_BOOLEANTYPE; + +/* Parameter specifying the content uri to use. */ +/** @ingroup cp */ +typedef struct OMX_PARAM_CONTENTURITYPE +{ + OMX_U32 nSize; /**< size of the structure in bytes, including + actual URI name */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U8 contentURI[1]; /**< The URI name */ +} OMX_PARAM_CONTENTURITYPE; + +/* Parameter specifying the pipe to use. */ +/** @ingroup cp */ +typedef struct OMX_PARAM_CONTENTPIPETYPE +{ + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_HANDLETYPE hPipe; /**< The pipe handle*/ +} OMX_PARAM_CONTENTPIPETYPE; + +/** @ingroup rpm */ +typedef struct OMX_RESOURCECONCEALMENTTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bResourceConcealmentForbidden; /**< disallow the use of resource concealment + methods (like degrading algorithm quality to + lower resource consumption or functional bypass) + on a component as a resolution to resource conflicts. */ +} OMX_RESOURCECONCEALMENTTYPE; + + +/** @ingroup metadata */ +typedef enum OMX_METADATACHARSETTYPE { + OMX_MetadataCharsetUnknown = 0, + OMX_MetadataCharsetASCII, + OMX_MetadataCharsetBinary, + OMX_MetadataCharsetCodePage1252, + OMX_MetadataCharsetUTF8, + OMX_MetadataCharsetJavaConformantUTF8, + OMX_MetadataCharsetUTF7, + OMX_MetadataCharsetImapUTF7, + OMX_MetadataCharsetUTF16LE, + OMX_MetadataCharsetUTF16BE, + OMX_MetadataCharsetGB12345, + OMX_MetadataCharsetHZGB2312, + OMX_MetadataCharsetGB2312, + OMX_MetadataCharsetGB18030, + OMX_MetadataCharsetGBK, + OMX_MetadataCharsetBig5, + OMX_MetadataCharsetISO88591, + OMX_MetadataCharsetISO88592, + OMX_MetadataCharsetISO88593, + OMX_MetadataCharsetISO88594, + OMX_MetadataCharsetISO88595, + OMX_MetadataCharsetISO88596, + OMX_MetadataCharsetISO88597, + OMX_MetadataCharsetISO88598, + OMX_MetadataCharsetISO88599, + OMX_MetadataCharsetISO885910, + OMX_MetadataCharsetISO885913, + OMX_MetadataCharsetISO885914, + OMX_MetadataCharsetISO885915, + OMX_MetadataCharsetShiftJIS, + OMX_MetadataCharsetISO2022JP, + OMX_MetadataCharsetISO2022JP1, + OMX_MetadataCharsetISOEUCJP, + OMX_MetadataCharsetSMS7Bit, + OMX_MetadataCharsetKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MetadataCharsetVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_MetadataCharsetTypeMax= 0x7FFFFFFF +} OMX_METADATACHARSETTYPE; + +/** @ingroup metadata */ +typedef enum OMX_METADATASCOPETYPE +{ + OMX_MetadataScopeAllLevels, + OMX_MetadataScopeTopLevel, + OMX_MetadataScopePortLevel, + OMX_MetadataScopeNodeLevel, + OMX_MetadataScopeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MetadataScopeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_MetadataScopeTypeMax = 0x7fffffff +} OMX_METADATASCOPETYPE; + +/** @ingroup metadata */ +typedef enum OMX_METADATASEARCHMODETYPE +{ + OMX_MetadataSearchValueSizeByIndex, + OMX_MetadataSearchItemByIndex, + OMX_MetadataSearchNextItemByKey, + OMX_MetadataSearchKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MetadataSearchVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_MetadataSearchTypeMax = 0x7fffffff +} OMX_METADATASEARCHMODETYPE; +/** @ingroup metadata */ +typedef struct OMX_CONFIG_METADATAITEMCOUNTTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_METADATASCOPETYPE eScopeMode; + OMX_U32 nScopeSpecifier; + OMX_U32 nMetadataItemCount; +} OMX_CONFIG_METADATAITEMCOUNTTYPE; + +/** @ingroup metadata */ +typedef struct OMX_CONFIG_METADATAITEMTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_METADATASCOPETYPE eScopeMode; + OMX_U32 nScopeSpecifier; + OMX_U32 nMetadataItemIndex; + OMX_METADATASEARCHMODETYPE eSearchMode; + OMX_METADATACHARSETTYPE eKeyCharset; + OMX_U8 nKeySizeUsed; + OMX_U8 nKey[128]; + OMX_METADATACHARSETTYPE eValueCharset; + OMX_STRING sLanguageCountry; + OMX_U32 nValueMaxSize; + OMX_U32 nValueSizeUsed; + OMX_U8 nValue[1]; +} OMX_CONFIG_METADATAITEMTYPE; + +/* @ingroup metadata */ +typedef struct OMX_CONFIG_CONTAINERNODECOUNTTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bAllKeys; + OMX_U32 nParentNodeID; + OMX_U32 nNumNodes; +} OMX_CONFIG_CONTAINERNODECOUNTTYPE; + +/** @ingroup metadata */ +typedef struct OMX_CONFIG_CONTAINERNODEIDTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bAllKeys; + OMX_U32 nParentNodeID; + OMX_U32 nNodeIndex; + OMX_U32 nNodeID; + OMX_STRING cNodeName; + OMX_BOOL bIsLeafType; +} OMX_CONFIG_CONTAINERNODEIDTYPE; + +/** @ingroup metadata */ +typedef struct OMX_PARAM_METADATAFILTERTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bAllKeys; /* if true then this structure refers to all keys and + * the three key fields below are ignored */ + OMX_METADATACHARSETTYPE eKeyCharset; + OMX_U32 nKeySizeUsed; + OMX_U8 nKey [128]; + OMX_U32 nLanguageCountrySizeUsed; + OMX_U8 nLanguageCountry[128]; + OMX_BOOL bEnabled; /* if true then key is part of filter (e.g. + * retained for query later). If false then + * key is not part of filter */ +} OMX_PARAM_METADATAFILTERTYPE; + +/** The OMX_HANDLETYPE structure defines the component handle. The component + * handle is used to access all of the component's public methods and also + * contains pointers to the component's private data area. The component + * handle is initialized by the OMX core (with help from the component) + * during the process of loading the component. After the component is + * successfully loaded, the application can safely access any of the + * component's public functions (although some may return an error because + * the state is inappropriate for the access). + * + * @ingroup comp + */ +typedef struct OMX_COMPONENTTYPE +{ + /** The size of this structure, in bytes. It is the responsibility + of the allocator of this structure to fill in this value. Since + this structure is allocated by the GetHandle function, this + function will fill in this value. */ + OMX_U32 nSize; + + /** nVersion is the version of the OMX specification that the structure + is built against. It is the responsibility of the creator of this + structure to initialize this value and every user of this structure + should verify that it knows how to use the exact version of + this structure found herein. */ + OMX_VERSIONTYPE nVersion; + + /** pComponentPrivate is a pointer to the component private data area. + This member is allocated and initialized by the component when the + component is first loaded. The application should not access this + data area. */ + OMX_PTR pComponentPrivate; + + /** pApplicationPrivate is a pointer that is a parameter to the + OMX_GetHandle method, and contains an application private value + provided by the IL client. This application private data is + returned to the IL Client by OMX in all callbacks */ + OMX_PTR pApplicationPrivate; + + /** refer to OMX_GetComponentVersion in OMX_core.h or the OMX IL + specification for details on the GetComponentVersion method. + */ + OMX_ERRORTYPE (*GetComponentVersion)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STRING pComponentName, + OMX_OUT OMX_VERSIONTYPE* pComponentVersion, + OMX_OUT OMX_VERSIONTYPE* pSpecVersion, + OMX_OUT OMX_UUIDTYPE* pComponentUUID); + + /** refer to OMX_SendCommand in OMX_core.h or the OMX IL + specification for details on the SendCommand method. + */ + OMX_ERRORTYPE (*SendCommand)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_COMMANDTYPE Cmd, + OMX_IN OMX_U32 nParam1, + OMX_IN OMX_PTR pCmdData); + + /** refer to OMX_GetParameter in OMX_core.h or the OMX IL + specification for details on the GetParameter method. + */ + OMX_ERRORTYPE (*GetParameter)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure); + + + /** refer to OMX_SetParameter in OMX_core.h or the OMX IL + specification for details on the SetParameter method. + */ + OMX_ERRORTYPE (*SetParameter)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure); + + + /** refer to OMX_GetConfig in OMX_core.h or the OMX IL + specification for details on the GetConfig method. + */ + OMX_ERRORTYPE (*GetConfig)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_INOUT OMX_PTR pComponentConfigStructure); + + + /** refer to OMX_SetConfig in OMX_core.h or the OMX IL + specification for details on the SetConfig method. + */ + OMX_ERRORTYPE (*SetConfig)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure); + + + /** refer to OMX_GetExtensionIndex in OMX_core.h or the OMX IL + specification for details on the GetExtensionIndex method. + */ + OMX_ERRORTYPE (*GetExtensionIndex)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE* pIndexType); + + + /** refer to OMX_GetState in OMX_core.h or the OMX IL + specification for details on the GetState method. + */ + OMX_ERRORTYPE (*GetState)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STATETYPE* pState); + + + /** The ComponentTunnelRequest method will interact with another OMX + component to determine if tunneling is possible and to setup the + tunneling. The return codes for this method can be used to + determine if tunneling is not possible, or if tunneling is not + supported. + + Base profile components (i.e. non-interop) do not support this + method and should return OMX_ErrorNotImplemented + + The interop profile component MUST support tunneling to another + interop profile component with a compatible port parameters. + A component may also support proprietary communication. + + If proprietary communication is supported the negotiation of + proprietary communication is done outside of OMX in a vendor + specific way. It is only required that the proper result be + returned and the details of how the setup is done is left + to the component implementation. + + When this method is invoked when nPort in an output port, the + component will: + 1. Populate the pTunnelSetup structure with the output port's + requirements and constraints for the tunnel. + + When this method is invoked when nPort in an input port, the + component will: + 1. Query the necessary parameters from the output port to + determine if the ports are compatible for tunneling + 2. If the ports are compatible, the component should store + the tunnel step provided by the output port + 3. Determine which port (either input or output) is the buffer + supplier, and call OMX_SetParameter on the output port to + indicate this selection. + + The component will return from this call within 5 msec. + + @param [in] hComp + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle method. + @param [in] nPort + nPort is used to select the port on the component to be used + for tunneling. + @param [in] hTunneledComp + Handle of the component to tunnel with. This is the component + handle returned by the call to the OMX_GetHandle method. When + this parameter is 0x0 the component should setup the port for + communication with the application / IL Client. + @param [in] nPortOutput + nPortOutput is used indicate the port the component should + tunnel with. + @param [in] pTunnelSetup + Pointer to the tunnel setup structure. When nPort is an output port + the component should populate the fields of this structure. When + When nPort is an input port the component should review the setup + provided by the component with the output port. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup tun + */ + + OMX_ERRORTYPE (*ComponentTunnelRequest)( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 nPort, + OMX_IN OMX_HANDLETYPE hTunneledComp, + OMX_IN OMX_U32 nTunneledPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup); + + /** refer to OMX_UseBuffer in OMX_core.h or the OMX IL + specification for details on the UseBuffer method. + @ingroup buf + */ + OMX_ERRORTYPE (*UseBuffer)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8* pBuffer); + + /** refer to OMX_AllocateBuffer in OMX_core.h or the OMX IL + specification for details on the AllocateBuffer method. + @ingroup buf + */ + OMX_ERRORTYPE (*AllocateBuffer)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes); + + /** refer to OMX_FreeBuffer in OMX_core.h or the OMX IL + specification for details on the FreeBuffer method. + @ingroup buf + */ + OMX_ERRORTYPE (*FreeBuffer)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + + /** refer to OMX_EmptyThisBuffer in OMX_core.h or the OMX IL + specification for details on the EmptyThisBuffer method. + @ingroup buf + */ + OMX_ERRORTYPE (*EmptyThisBuffer)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + + /** refer to OMX_FillThisBuffer in OMX_core.h or the OMX IL + specification for details on the FillThisBuffer method. + @ingroup buf + */ + OMX_ERRORTYPE (*FillThisBuffer)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + + /** The SetCallbacks method is used by the core to specify the callback + structure from the application to the component. This is a blocking + call. The component will return from this call within 5 msec. + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the GetHandle function. + @param [in] pCallbacks + pointer to an OMX_CALLBACKTYPE structure used to provide the + callback information to the component + @param [in] pAppData + pointer to an application defined value. It is anticipated that + the application will pass a pointer to a data structure or a "this + pointer" in this area to allow the callback (in the application) + to determine the context of the call + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + */ + OMX_ERRORTYPE (*SetCallbacks)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_CALLBACKTYPE* pCallbacks, + OMX_IN OMX_PTR pAppData); + + /** ComponentDeInit method is used to deinitialize the component + providing a means to free any resources allocated at component + initialization. NOTE: After this call the component handle is + not valid for further use. + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the GetHandle function. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + */ + OMX_ERRORTYPE (*ComponentDeInit)( + OMX_IN OMX_HANDLETYPE hComponent); + + /** @ingroup buf */ + OMX_ERRORTYPE (*UseEGLImage)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN void* eglImage); + + OMX_ERRORTYPE (*ComponentRoleEnum)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_U8 *cRole, + OMX_IN OMX_U32 nIndex); + +} OMX_COMPONENTTYPE; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ diff --git a/mm-core/inc/OMX_ContentPipe.h b/mm-core/inc/OMX_ContentPipe.h new file mode 100755 index 0000000..5f6310c --- /dev/null +++ b/mm-core/inc/OMX_ContentPipe.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_ContentPipe.h - OpenMax IL version 1.1.2 + * The OMX_ContentPipe header file contains the definitions used to define + * the public interface for content piples. This header file is intended to + * be used by the component. + */ + +#ifndef OMX_CONTENTPIPE_H +#define OMX_CONTENTPIPE_H + +#ifndef KD_EACCES +/* OpenKODE error codes. CPResult values may be zero (indicating success + or one of the following values) */ +#define KD_EACCES (1) +#define KD_EADDRINUSE (2) +#define KD_EAGAIN (5) +#define KD_EBADF (7) +#define KD_EBUSY (8) +#define KD_ECONNREFUSED (9) +#define KD_ECONNRESET (10) +#define KD_EDEADLK (11) +#define KD_EDESTADDRREQ (12) +#define KD_ERANGE (35) +#define KD_EEXIST (13) +#define KD_EFBIG (14) +#define KD_EHOSTUNREACH (15) +#define KD_EINVAL (17) +#define KD_EIO (18) +#define KD_EISCONN (20) +#define KD_EISDIR (21) +#define KD_EMFILE (22) +#define KD_ENAMETOOLONG (23) +#define KD_ENOENT (24) +#define KD_ENOMEM (25) +#define KD_ENOSPC (26) +#define KD_ENOSYS (27) +#define KD_ENOTCONN (28) +#define KD_EPERM (33) +#define KD_ETIMEDOUT (36) +#define KD_EILSEQ (19) +#endif + +/** Map types from OMX standard types only here so interface is as generic as possible. */ +typedef OMX_U32 CPresult; +typedef char * CPstring; +typedef void * CPhandle; +typedef OMX_U32 CPuint; +typedef OMX_S32 CPint; +typedef char CPbyte; +typedef OMX_BOOL CPbool; + +/** enumeration of origin types used in the CP_PIPETYPE's Seek function + * @ingroup cp + */ +typedef enum CP_ORIGINTYPE { + CP_OriginBegin, + CP_OriginCur, + CP_OriginEnd, + CP_OriginKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + CP_OriginVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + CP_OriginMax = 0X7FFFFFFF +} CP_ORIGINTYPE; + +/** enumeration of contact access types used in the CP_PIPETYPE's Open function + * @ingroup cp + */ +typedef enum CP_ACCESSTYPE { + CP_AccessRead, + CP_AccessWrite, + CP_AccessReadWrite , + CP_AccessKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + CP_AccessVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + CP_AccessMax = 0X7FFFFFFF +} CP_ACCESSTYPE; + +/** enumeration of results returned by the CP_PIPETYPE's CheckAvailableBytes function + * @ingroup cp + */ +typedef enum CP_CHECKBYTESRESULTTYPE +{ + CP_CheckBytesOk, /**< There are at least the request number + of bytes available */ + CP_CheckBytesNotReady, /**< The pipe is still retrieving bytes + and presently lacks sufficient bytes. + Client will be called when they are + sufficient bytes are available. */ + CP_CheckBytesInsufficientBytes , /**< The pipe has retrieved all bytes + but those available are less than those + requested */ + CP_CheckBytesAtEndOfStream, /**< The pipe has reached the end of stream + and no more bytes are available. */ + CP_CheckBytesOutOfBuffers, /**< All read/write buffers are currently in use. */ + CP_CheckBytesKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + CP_CheckBytesVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + CP_CheckBytesMax = 0X7FFFFFFF +} CP_CHECKBYTESRESULTTYPE; + +/** enumeration of content pipe events sent to the client callback. + * @ingroup cp + */ +typedef enum CP_EVENTTYPE{ + CP_BytesAvailable, /** bytes requested in a CheckAvailableBytes call are now available*/ + CP_Overflow, /** enumeration of content pipe events sent to the client callback*/ + CP_PipeDisconnected , /** enumeration of content pipe events sent to the client callback*/ + CP_EventKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + CP_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + CP_EventMax = 0X7FFFFFFF +} CP_EVENTTYPE; + +/** content pipe definition + * @ingroup cp + */ +typedef struct CP_PIPETYPE +{ + /** Open a content stream for reading or writing. */ + CPresult (*Open)( CPhandle* hContent, CPstring szURI, CP_ACCESSTYPE eAccess ); + + /** Close a content stream. */ + CPresult (*Close)( CPhandle hContent ); + + /** Create a content source and open it for writing. */ + CPresult (*Create)( CPhandle *hContent, CPstring szURI ); + + /** Check the that specified number of bytes are available for reading or writing (depending on access type).*/ + CPresult (*CheckAvailableBytes)( CPhandle hContent, CPuint nBytesRequested, CP_CHECKBYTESRESULTTYPE *eResult ); + + /** Seek to certain position in the content relative to the specified origin. */ + CPresult (*SetPosition)( CPhandle hContent, CPint nOffset, CP_ORIGINTYPE eOrigin); + + /** Retrieve the current position relative to the start of the content. */ + CPresult (*GetPosition)( CPhandle hContent, CPuint *pPosition); + + /** Retrieve data of the specified size from the content stream (advance content pointer by size of data). + Note: pipe client provides pointer. This function is appropriate for small high frequency reads. */ + CPresult (*Read)( CPhandle hContent, CPbyte *pData, CPuint nSize); + + /** Retrieve a buffer allocated by the pipe that contains the requested number of bytes. + Buffer contains the next block of bytes, as specified by nSize, of the content. nSize also + returns the size of the block actually read. Content pointer advances the by the returned size. + Note: pipe provides pointer. This function is appropriate for large reads. The client must call + ReleaseReadBuffer when done with buffer. + + In some cases the requested block may not reside in contiguous memory within the + pipe implementation. For instance if the pipe leverages a circular buffer then the requested + block may straddle the boundary of the circular buffer. By default a pipe implementation + performs a copy in this case to provide the block to the pipe client in one contiguous buffer. + If, however, the client sets bForbidCopy, then the pipe returns only those bytes preceding the memory + boundary. Here the client may retrieve the data in segments over successive calls. */ + CPresult (*ReadBuffer)( CPhandle hContent, CPbyte **ppBuffer, CPuint *nSize, CPbool bForbidCopy); + + /** Release a buffer obtained by ReadBuffer back to the pipe. */ + CPresult (*ReleaseReadBuffer)(CPhandle hContent, CPbyte *pBuffer); + + /** Write data of the specified size to the content (advance content pointer by size of data). + Note: pipe client provides pointer. This function is appropriate for small high frequency writes. */ + CPresult (*Write)( CPhandle hContent, CPbyte *data, CPuint nSize); + + /** Retrieve a buffer allocated by the pipe used to write data to the content. + Client will fill buffer with output data. Note: pipe provides pointer. This function is appropriate + for large writes. The client must call WriteBuffer when done it has filled the buffer with data.*/ + CPresult (*GetWriteBuffer)( CPhandle hContent, CPbyte **ppBuffer, CPuint nSize); + + /** Deliver a buffer obtained via GetWriteBuffer to the pipe. Pipe will write the + the contents of the buffer to content and advance content pointer by the size of the buffer */ + CPresult (*WriteBuffer)( CPhandle hContent, CPbyte *pBuffer, CPuint nFilledSize); + + /** Register a per-handle client callback with the content pipe. */ + CPresult (*RegisterCallback)( CPhandle hContent, CPresult (*ClientCallback)(CP_EVENTTYPE eEvent, CPuint iParam)); + +} CP_PIPETYPE; + +#endif + diff --git a/mm-core/inc/OMX_Core.h b/mm-core/inc/OMX_Core.h new file mode 100755 index 0000000..a076f2f --- /dev/null +++ b/mm-core/inc/OMX_Core.h @@ -0,0 +1,1431 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_Core.h - OpenMax IL version 1.1.2 + * The OMX_Core header file contains the definitions used by both the + * application and the component to access common items. + */ + +#ifndef OMX_Core_h +#define OMX_Core_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* Each OMX header shall include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include + + +/** The OMX_COMMANDTYPE enumeration is used to specify the action in the + * OMX_SendCommand macro. + * @ingroup core + */ +typedef enum OMX_COMMANDTYPE +{ + OMX_CommandStateSet, /**< Change the component state */ + OMX_CommandFlush, /**< Flush the data queue(s) of a component */ + OMX_CommandPortDisable, /**< Disable a port on a component. */ + OMX_CommandPortEnable, /**< Enable a port on a component. */ + OMX_CommandMarkBuffer, /**< Mark a component/buffer for observation */ + OMX_CommandKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_CommandVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_CommandMax = 0X7FFFFFFF +} OMX_COMMANDTYPE; + + + +/** The OMX_STATETYPE enumeration is used to indicate or change the component + * state. This enumeration reflects the current state of the component when + * used with the OMX_GetState macro or becomes the parameter in a state change + * command when used with the OMX_SendCommand macro. + * + * The component will be in the Loaded state after the component is initially + * loaded into memory. In the Loaded state, the component is not allowed to + * allocate or hold resources other than to build it's internal parameter + * and configuration tables. The application will send one or more + * SetParameters/GetParameters and SetConfig/GetConfig commands to the + * component and the component will record each of these parameter and + * configuration changes for use later. When the application sends the + * Idle command, the component will acquire the resources needed for the + * specified configuration and will transition to the idle state if the + * allocation is successful. If the component cannot successfully + * transition to the idle state for any reason, the state of the component + * shall be fully rolled back to the Loaded state (e.g. all allocated + * resources shall be released). When the component receives the command + * to go to the Executing state, it shall begin processing buffers by + * sending all input buffers it holds to the application. While + * the component is in the Idle state, the application may also send the + * Pause command. If the component receives the pause command while in the + * Idle state, the component shall send all input buffers it holds to the + * application, but shall not begin processing buffers. This will allow the + * application to prefill buffers. + * + * @ingroup comp + */ + +typedef enum OMX_STATETYPE +{ + OMX_StateInvalid, /**< component has detected that it's internal data + structures are corrupted to the point that + it cannot determine it's state properly */ + OMX_StateLoaded, /**< component has been loaded but has not completed + initialization. The OMX_SetParameter macro + and the OMX_GetParameter macro are the only + valid macros allowed to be sent to the + component in this state. */ + OMX_StateIdle, /**< component initialization has been completed + successfully and the component is ready to + to start. */ + OMX_StateExecuting, /**< component has accepted the start command and + is processing data (if data is available) */ + OMX_StatePause, /**< component has received pause command */ + OMX_StateWaitForResources, /**< component is waiting for resources, either after + preemption or before it gets the resources requested. + See specification for complete details. */ + OMX_StateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_StateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_StateMax = 0X7FFFFFFF +} OMX_STATETYPE; + +/** The OMX_ERRORTYPE enumeration defines the standard OMX Errors. These + * errors should cover most of the common failure cases. However, + * vendors are free to add additional error messages of their own as + * long as they follow these rules: + * 1. Vendor error messages shall be in the range of 0x90000000 to + * 0x9000FFFF. + * 2. Vendor error messages shall be defined in a header file provided + * with the component. No error messages are allowed that are + * not defined. + */ +typedef enum OMX_ERRORTYPE +{ + OMX_ErrorNone = 0, + + /** There were insufficient resources to perform the requested operation */ + OMX_ErrorInsufficientResources = (OMX_S32) 0x80001000, + + /** There was an error, but the cause of the error could not be determined */ + OMX_ErrorUndefined = (OMX_S32) 0x80001001, + + /** The component name string was not valid */ + OMX_ErrorInvalidComponentName = (OMX_S32) 0x80001002, + + /** No component with the specified name string was found */ + OMX_ErrorComponentNotFound = (OMX_S32) 0x80001003, + + /** The component specified did not have a "OMX_ComponentInit" or + "OMX_ComponentDeInit entry point */ + OMX_ErrorInvalidComponent = (OMX_S32) 0x80001004, + + /** One or more parameters were not valid */ + OMX_ErrorBadParameter = (OMX_S32) 0x80001005, + + /** The requested function is not implemented */ + OMX_ErrorNotImplemented = (OMX_S32) 0x80001006, + + /** The buffer was emptied before the next buffer was ready */ + OMX_ErrorUnderflow = (OMX_S32) 0x80001007, + + /** The buffer was not available when it was needed */ + OMX_ErrorOverflow = (OMX_S32) 0x80001008, + + /** The hardware failed to respond as expected */ + OMX_ErrorHardware = (OMX_S32) 0x80001009, + + /** The component is in the state OMX_StateInvalid */ + OMX_ErrorInvalidState = (OMX_S32) 0x8000100A, + + /** Stream is found to be corrupt */ + OMX_ErrorStreamCorrupt = (OMX_S32) 0x8000100B, + + /** Ports being connected are not compatible */ + OMX_ErrorPortsNotCompatible = (OMX_S32) 0x8000100C, + + /** Resources allocated to an idle component have been + lost resulting in the component returning to the loaded state */ + OMX_ErrorResourcesLost = (OMX_S32) 0x8000100D, + + /** No more indicies can be enumerated */ + OMX_ErrorNoMore = (OMX_S32) 0x8000100E, + + /** The component detected a version mismatch */ + OMX_ErrorVersionMismatch = (OMX_S32) 0x8000100F, + + /** The component is not ready to return data at this time */ + OMX_ErrorNotReady = (OMX_S32) 0x80001010, + + /** There was a timeout that occurred */ + OMX_ErrorTimeout = (OMX_S32) 0x80001011, + + /** This error occurs when trying to transition into the state you are already in */ + OMX_ErrorSameState = (OMX_S32) 0x80001012, + + /** Resources allocated to an executing or paused component have been + preempted, causing the component to return to the idle state */ + OMX_ErrorResourcesPreempted = (OMX_S32) 0x80001013, + + /** A non-supplier port sends this error to the IL client (via the EventHandler callback) + during the allocation of buffers (on a transition from the LOADED to the IDLE state or + on a port restart) when it deems that it has waited an unusually long time for the supplier + to send it an allocated buffer via a UseBuffer call. */ + OMX_ErrorPortUnresponsiveDuringAllocation = (OMX_S32) 0x80001014, + + /** A non-supplier port sends this error to the IL client (via the EventHandler callback) + during the deallocation of buffers (on a transition from the IDLE to LOADED state or + on a port stop) when it deems that it has waited an unusually long time for the supplier + to request the deallocation of a buffer header via a FreeBuffer call. */ + OMX_ErrorPortUnresponsiveDuringDeallocation = (OMX_S32) 0x80001015, + + /** A supplier port sends this error to the IL client (via the EventHandler callback) + during the stopping of a port (either on a transition from the IDLE to LOADED + state or a port stop) when it deems that it has waited an unusually long time for + the non-supplier to return a buffer via an EmptyThisBuffer or FillThisBuffer call. */ + OMX_ErrorPortUnresponsiveDuringStop = (OMX_S32) 0x80001016, + + /** Attempting a state transtion that is not allowed */ + OMX_ErrorIncorrectStateTransition = (OMX_S32) 0x80001017, + + /* Attempting a command that is not allowed during the present state. */ + OMX_ErrorIncorrectStateOperation = (OMX_S32) 0x80001018, + + /** The values encapsulated in the parameter or config structure are not supported. */ + OMX_ErrorUnsupportedSetting = (OMX_S32) 0x80001019, + + /** The parameter or config indicated by the given index is not supported. */ + OMX_ErrorUnsupportedIndex = (OMX_S32) 0x8000101A, + + /** The port index supplied is incorrect. */ + OMX_ErrorBadPortIndex = (OMX_S32) 0x8000101B, + + /** The port has lost one or more of its buffers and it thus unpopulated. */ + OMX_ErrorPortUnpopulated = (OMX_S32) 0x8000101C, + + /** Component suspended due to temporary loss of resources */ + OMX_ErrorComponentSuspended = (OMX_S32) 0x8000101D, + + /** Component suspended due to an inability to acquire dynamic resources */ + OMX_ErrorDynamicResourcesUnavailable = (OMX_S32) 0x8000101E, + + /** When the macroblock error reporting is enabled the component returns new error + for every frame that has errors */ + OMX_ErrorMbErrorsInFrame = (OMX_S32) 0x8000101F, + + /** A component reports this error when it cannot parse or determine the format of an input stream. */ + OMX_ErrorFormatNotDetected = (OMX_S32) 0x80001020, + + /** The content open operation failed. */ + OMX_ErrorContentPipeOpenFailed = (OMX_S32) 0x80001021, + + /** The content creation operation failed. */ + OMX_ErrorContentPipeCreationFailed = (OMX_S32) 0x80001022, + + /** Separate table information is being used */ + OMX_ErrorSeperateTablesUsed = (OMX_S32) 0x80001023, + + /** Tunneling is unsupported by the component*/ + OMX_ErrorTunnelingUnsupported = (OMX_S32) 0x80001024, + + OMX_ErrorKhronosExtensions = (OMX_S32)0x8F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ErrorVendorStartUnused = (OMX_S32)0x90000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_ErrorMax = 0x7FFFFFFF +} OMX_ERRORTYPE; + +/** @ingroup core */ +typedef OMX_ERRORTYPE (* OMX_COMPONENTINITTYPE)(OMX_IN OMX_HANDLETYPE hComponent); + +/** @ingroup core */ +typedef struct OMX_COMPONENTREGISTERTYPE +{ + const char * pName; /* Component name, 128 byte limit (including '\0') applies */ + OMX_COMPONENTINITTYPE pInitialize; /* Component instance initialization function */ +} OMX_COMPONENTREGISTERTYPE; + +/** @ingroup core */ +extern OMX_COMPONENTREGISTERTYPE OMX_ComponentRegistered[]; + +/** @ingroup rpm */ +typedef struct OMX_PRIORITYMGMTTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nGroupPriority; /**< Priority of the component group */ + OMX_U32 nGroupID; /**< ID of the component group */ +} OMX_PRIORITYMGMTTYPE; + +/* Component name and Role names are limited to 128 characters including the terminating '\0'. */ +#define OMX_MAX_STRINGNAME_SIZE 128 + +/** @ingroup comp */ +typedef struct OMX_PARAM_COMPONENTROLETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U8 cRole[OMX_MAX_STRINGNAME_SIZE]; /**< name of standard component which defines component role */ +} OMX_PARAM_COMPONENTROLETYPE; + +/** End of Stream Buffer Flag: + * + * A component sets EOS when it has no more data to emit on a particular + * output port. Thus an output port shall set EOS on the last buffer it + * emits. A component's determination of when an output port should + * cease sending data is implemenation specific. + * @ingroup buf + */ + +#define OMX_BUFFERFLAG_EOS 0x00000001 + +/** Start Time Buffer Flag: + * + * The source of a stream (e.g. a demux component) sets the STARTTIME + * flag on the buffer that contains the starting timestamp for the + * stream. The starting timestamp corresponds to the first data that + * should be displayed at startup or after a seek. + * The first timestamp of the stream is not necessarily the start time. + * For instance, in the case of a seek to a particular video frame, + * the target frame may be an interframe. Thus the first buffer of + * the stream will be the intra-frame preceding the target frame and + * the starttime will occur with the target frame (with any other + * required frames required to reconstruct the target intervening). + * + * The STARTTIME flag is directly associated with the buffer's + * timestamp ' thus its association to buffer data and its + * propagation is identical to the timestamp's. + * + * When a Sync Component client receives a buffer with the + * STARTTIME flag it shall perform a SetConfig on its sync port + * using OMX_ConfigTimeClientStartTime and passing the buffer's + * timestamp. + * + * @ingroup buf + */ + +#define OMX_BUFFERFLAG_STARTTIME 0x00000002 + + + +/** Decode Only Buffer Flag: + * + * The source of a stream (e.g. a demux component) sets the DECODEONLY + * flag on any buffer that should shall be decoded but should not be + * displayed. This flag is used, for instance, when a source seeks to + * a target interframe that requires the decode of frames preceding the + * target to facilitate the target's reconstruction. In this case the + * source would emit the frames preceding the target downstream + * but mark them as decode only. + * + * The DECODEONLY is associated with buffer data and propagated in a + * manner identical to the buffer timestamp. + * + * A component that renders data should ignore all buffers with + * the DECODEONLY flag set. + * + * @ingroup buf + */ + +#define OMX_BUFFERFLAG_DECODEONLY 0x00000004 + + +/* Data Corrupt Flag: This flag is set when the IL client believes the data in the associated buffer is corrupt + * @ingroup buf + */ + +#define OMX_BUFFERFLAG_DATACORRUPT 0x00000008 + +/* End of Frame: The buffer contains exactly one end of frame and no data + * occurs after the end of frame. This flag is an optional hint. The absence + * of this flag does not imply the absence of an end of frame within the buffer. + * @ingroup buf +*/ +#define OMX_BUFFERFLAG_ENDOFFRAME 0x00000010 + +/* Sync Frame Flag: This flag is set when the buffer content contains a coded sync frame ' + * a frame that has no dependency on any other frame information + * @ingroup buf + */ +#define OMX_BUFFERFLAG_SYNCFRAME 0x00000020 + +/* Extra data present flag: there is extra data appended to the data stream + * residing in the buffer + * @ingroup buf + */ +#define OMX_BUFFERFLAG_EXTRADATA 0x00000040 + +/** Codec Config Buffer Flag: +* OMX_BUFFERFLAG_CODECCONFIG is an optional flag that is set by an +* output port when all bytes in the buffer form part or all of a set of +* codec specific configuration data. Examples include SPS/PPS nal units +* for OMX_VIDEO_CodingAVC or AudioSpecificConfig data for +* OMX_AUDIO_CodingAAC. Any component that for a given stream sets +* OMX_BUFFERFLAG_CODECCONFIG shall not mix codec configuration bytes +* with frame data in the same buffer, and shall send all buffers +* containing codec configuration bytes before any buffers containing +* frame data that those configurations bytes describe. +* If the stream format for a particular codec has a frame specific +* header at the start of each frame, for example OMX_AUDIO_CodingMP3 or +* OMX_AUDIO_CodingAAC in ADTS mode, then these shall be presented as +* normal without setting OMX_BUFFERFLAG_CODECCONFIG. + * @ingroup buf + */ +#define OMX_BUFFERFLAG_CODECCONFIG 0x00000080 + + + +/** @ingroup buf */ +typedef struct OMX_BUFFERHEADERTYPE +{ + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U8* pBuffer; /**< Pointer to actual block of memory + that is acting as the buffer */ + OMX_U32 nAllocLen; /**< size of the buffer allocated, in bytes */ + OMX_U32 nFilledLen; /**< number of bytes currently in the + buffer */ + OMX_U32 nOffset; /**< start offset of valid data in bytes from + the start of the buffer */ + OMX_PTR pAppPrivate; /**< pointer to any data the application + wants to associate with this buffer */ + OMX_PTR pPlatformPrivate; /**< pointer to any data the platform + wants to associate with this buffer */ + OMX_PTR pInputPortPrivate; /**< pointer to any data the input port + wants to associate with this buffer */ + OMX_PTR pOutputPortPrivate; /**< pointer to any data the output port + wants to associate with this buffer */ + OMX_HANDLETYPE hMarkTargetComponent; /**< The component that will generate a + mark event upon processing this buffer. */ + OMX_PTR pMarkData; /**< Application specific data associated with + the mark sent on a mark event to disambiguate + this mark from others. */ + OMX_U32 nTickCount; /**< Optional entry that the component and + application can update with a tick count + when they access the component. This + value should be in microseconds. Since + this is a value relative to an arbitrary + starting point, this value cannot be used + to determine absolute time. This is an + optional entry and not all components + will update it.*/ + OMX_TICKS nTimeStamp; /**< Timestamp corresponding to the sample + starting at the first logical sample + boundary in the buffer. Timestamps of + successive samples within the buffer may + be inferred by adding the duration of the + of the preceding buffer to the timestamp + of the preceding buffer.*/ + OMX_U32 nFlags; /**< buffer specific flags */ + OMX_U32 nOutputPortIndex; /**< The index of the output port (if any) using + this buffer */ + OMX_U32 nInputPortIndex; /**< The index of the input port (if any) using + this buffer */ +} OMX_BUFFERHEADERTYPE; + +/** The OMX_EXTRADATATYPE enumeration is used to define the + * possible extra data payload types. + * NB: this enum is binary backwards compatible with the previous + * OMX_EXTRADATA_QUANT define. This should be replaced with + * OMX_ExtraDataQuantization. + */ +typedef enum OMX_EXTRADATATYPE +{ + OMX_ExtraDataNone = 0, /**< Indicates that no more extra data sections follow */ + OMX_ExtraDataQuantization, /**< The data payload contains quantization data */ + OMX_ExtraDataKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ExtraDataVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_ExtraDataMax = 0x7FFFFFFF +} OMX_EXTRADATATYPE; + + +typedef struct OMX_OTHER_EXTRADATATYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_EXTRADATATYPE eType; /* Extra Data type */ + OMX_U32 nDataSize; /* Size of the supporting data to follow */ + OMX_U8 data[1]; /* Supporting data hint */ +} OMX_OTHER_EXTRADATATYPE; + +/** @ingroup comp */ +typedef struct OMX_PORT_PARAM_TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPorts; /**< The number of ports for this component */ + OMX_U32 nStartPortNumber; /** first port number for this type of port */ +} OMX_PORT_PARAM_TYPE; + +/** @ingroup comp */ +typedef enum OMX_EVENTTYPE +{ + OMX_EventCmdComplete, /**< component has sucessfully completed a command */ + OMX_EventError, /**< component has detected an error condition */ + OMX_EventMark, /**< component has detected a buffer mark */ + OMX_EventPortSettingsChanged, /**< component is reported a port settings change */ + OMX_EventBufferFlag, /**< component has detected an EOS */ + OMX_EventResourcesAcquired, /**< component has been granted resources and is + automatically starting the state change from + OMX_StateWaitForResources to OMX_StateIdle. */ + OMX_EventComponentResumed, /**< Component resumed due to reacquisition of resources */ + OMX_EventDynamicResourcesAvailable, /**< Component has acquired previously unavailable dynamic resources */ + OMX_EventPortFormatDetected, /**< Component has detected a supported format. */ + OMX_EventKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_EventMax = 0x7FFFFFFF +} OMX_EVENTTYPE; + +typedef struct OMX_CALLBACKTYPE +{ + /** The EventHandler method is used to notify the application when an + event of interest occurs. Events are defined in the OMX_EVENTTYPE + enumeration. Please see that enumeration for details of what will + be returned for each type of event. Callbacks should not return + an error to the component, so if an error occurs, the application + shall handle it internally. This is a blocking call. + + The application should return from this call within 5 msec to avoid + blocking the component for an excessively long period of time. + + @param hComponent + handle of the component to access. This is the component + handle returned by the call to the GetHandle function. + @param pAppData + pointer to an application defined value that was provided in the + pAppData parameter to the OMX_GetHandle method for the component. + This application defined value is provided so that the application + can have a component specific context when receiving the callback. + @param eEvent + Event that the component wants to notify the application about. + @param nData1 + nData will be the OMX_ERRORTYPE for an error event and will be + an OMX_COMMANDTYPE for a command complete event and OMX_INDEXTYPE for a OMX_PortSettingsChanged event. + @param nData2 + nData2 will hold further information related to the event. Can be OMX_STATETYPE for + a OMX_CommandStateSet command or port index for a OMX_PortSettingsChanged event. + Default value is 0 if not used. ) + @param pEventData + Pointer to additional event-specific data (see spec for meaning). + */ + + OMX_ERRORTYPE (*EventHandler)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, + OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData); + + /** The EmptyBufferDone method is used to return emptied buffers from an + input port back to the application for reuse. This is a blocking call + so the application should not attempt to refill the buffers during this + call, but should queue them and refill them in another thread. There + is no error return, so the application shall handle any errors generated + internally. + + The application should return from this call within 5 msec. + + @param hComponent + handle of the component to access. This is the component + handle returned by the call to the GetHandle function. + @param pAppData + pointer to an application defined value that was provided in the + pAppData parameter to the OMX_GetHandle method for the component. + This application defined value is provided so that the application + can have a component specific context when receiving the callback. + @param pBuffer + pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer + or AllocateBuffer indicating the buffer that was emptied. + @ingroup buf + */ + OMX_ERRORTYPE (*EmptyBufferDone)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + + /** The FillBufferDone method is used to return filled buffers from an + output port back to the application for emptying and then reuse. + This is a blocking call so the application should not attempt to + empty the buffers during this call, but should queue the buffers + and empty them in another thread. There is no error return, so + the application shall handle any errors generated internally. The + application shall also update the buffer header to indicate the + number of bytes placed into the buffer. + + The application should return from this call within 5 msec. + + @param hComponent + handle of the component to access. This is the component + handle returned by the call to the GetHandle function. + @param pAppData + pointer to an application defined value that was provided in the + pAppData parameter to the OMX_GetHandle method for the component. + This application defined value is provided so that the application + can have a component specific context when receiving the callback. + @param pBuffer + pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer + or AllocateBuffer indicating the buffer that was filled. + @ingroup buf + */ + OMX_ERRORTYPE (*FillBufferDone)( + OMX_OUT OMX_HANDLETYPE hComponent, + OMX_OUT OMX_PTR pAppData, + OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer); + +} OMX_CALLBACKTYPE; + +/** The OMX_BUFFERSUPPLIERTYPE enumeration is used to dictate port supplier + preference when tunneling between two ports. + @ingroup tun buf +*/ +typedef enum OMX_BUFFERSUPPLIERTYPE +{ + OMX_BufferSupplyUnspecified = 0x0, /**< port supplying the buffers is unspecified, + or don't care */ + OMX_BufferSupplyInput, /**< input port supplies the buffers */ + OMX_BufferSupplyOutput, /**< output port supplies the buffers */ + OMX_BufferSupplyKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_BufferSupplyVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_BufferSupplyMax = 0x7FFFFFFF +} OMX_BUFFERSUPPLIERTYPE; + + +/** buffer supplier parameter + * @ingroup tun + */ +typedef struct OMX_PARAM_BUFFERSUPPLIERTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BUFFERSUPPLIERTYPE eBufferSupplier; /**< buffer supplier */ +} OMX_PARAM_BUFFERSUPPLIERTYPE; + + +/**< indicates that buffers received by an input port of a tunnel + may not modify the data in the buffers + @ingroup tun + */ +#define OMX_PORTTUNNELFLAG_READONLY 0x00000001 + + +/** The OMX_TUNNELSETUPTYPE structure is used to pass data from an output + port to an input port as part the two ComponentTunnelRequest calls + resulting from a OMX_SetupTunnel call from the IL Client. + @ingroup tun + */ +typedef struct OMX_TUNNELSETUPTYPE +{ + OMX_U32 nTunnelFlags; /**< bit flags for tunneling */ + OMX_BUFFERSUPPLIERTYPE eSupplier; /**< supplier preference */ +} OMX_TUNNELSETUPTYPE; + +/* OMX Component headers is included to enable the core to use + macros for functions into the component for OMX release 1.0. + Developers should not access any structures or data from within + the component header directly */ +/* TO BE REMOVED - #include */ + +/** GetComponentVersion will return information about the component. + This is a blocking call. This macro will go directly from the + application to the component (via a core macro). The + component will return from this call within 5 msec. + @param [in] hComponent + handle of component to execute the command + @param [out] pComponentName + pointer to an empty string of length 128 bytes. The component + will write its name into this string. The name will be + terminated by a single zero byte. The name of a component will + be 127 bytes or less to leave room for the trailing zero byte. + An example of a valid component name is "OMX.ABC.ChannelMixer\0". + @param [out] pComponentVersion + pointer to an OMX Version structure that the component will fill + in. The component will fill in a value that indicates the + component version. NOTE: the component version is NOT the same + as the OMX Specification version (found in all structures). The + component version is defined by the vendor of the component and + its value is entirely up to the component vendor. + @param [out] pSpecVersion + pointer to an OMX Version structure that the component will fill + in. The SpecVersion is the version of the specification that the + component was built against. Please note that this value may or + may not match the structure's version. For example, if the + component was built against the 2.0 specification, but the + application (which creates the structure is built against the + 1.0 specification the versions would be different. + @param [out] pComponentUUID + pointer to the UUID of the component which will be filled in by + the component. The UUID is a unique identifier that is set at + RUN time for the component and is unique to each instantion of + the component. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_GetComponentVersion( \ + hComponent, \ + pComponentName, \ + pComponentVersion, \ + pSpecVersion, \ + pComponentUUID) \ + ((OMX_COMPONENTTYPE*)hComponent)->GetComponentVersion( \ + hComponent, \ + pComponentName, \ + pComponentVersion, \ + pSpecVersion, \ + pComponentUUID) /* Macro End */ + + +/** Send a command to the component. This call is a non-blocking call. + The component should check the parameters and then queue the command + to the component thread to be executed. The component thread shall + send the EventHandler() callback at the conclusion of the command. + This macro will go directly from the application to the component (via + a core macro). The component will return from this call within 5 msec. + + When the command is "OMX_CommandStateSet" the component will queue a + state transition to the new state idenfied in nParam. + + When the command is "OMX_CommandFlush", to flush a port's buffer queues, + the command will force the component to return all buffers NOT CURRENTLY + BEING PROCESSED to the application, in the order in which the buffers + were received. + + When the command is "OMX_CommandPortDisable" or + "OMX_CommandPortEnable", the component's port (given by the value of + nParam) will be stopped or restarted. + + When the command "OMX_CommandMarkBuffer" is used to mark a buffer, the + pCmdData will point to a OMX_MARKTYPE structure containing the component + handle of the component to examine the buffer chain for the mark. nParam1 + contains the index of the port on which the buffer mark is applied. + + Specification text for more details. + + @param [in] hComponent + handle of component to execute the command + @param [in] Cmd + Command for the component to execute + @param [in] nParam + Parameter for the command to be executed. When Cmd has the value + OMX_CommandStateSet, value is a member of OMX_STATETYPE. When Cmd has + the value OMX_CommandFlush, value of nParam indicates which port(s) + to flush. -1 is used to flush all ports a single port index will + only flush that port. When Cmd has the value "OMX_CommandPortDisable" + or "OMX_CommandPortEnable", the component's port is given by + the value of nParam. When Cmd has the value "OMX_CommandMarkBuffer" + the components pot is given by the value of nParam. + @param [in] pCmdData + Parameter pointing to the OMX_MARKTYPE structure when Cmd has the value + "OMX_CommandMarkBuffer". + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_SendCommand( \ + hComponent, \ + Cmd, \ + nParam, \ + pCmdData) \ + ((OMX_COMPONENTTYPE*)hComponent)->SendCommand( \ + hComponent, \ + Cmd, \ + nParam, \ + pCmdData) /* Macro End */ + + +/** The OMX_GetParameter macro will get one of the current parameter + settings from the component. This macro cannot only be invoked when + the component is in the OMX_StateInvalid state. The nParamIndex + parameter is used to indicate which structure is being requested from + the component. The application shall allocate the correct structure + and shall fill in the structure size and version information before + invoking this macro. When the parameter applies to a port, the + caller shall fill in the appropriate nPortIndex value indicating the + port on which the parameter applies. If the component has not had + any settings changed, then the component should return a set of + valid DEFAULT parameters for the component. This is a blocking + call. + + The component should return from this call within 20 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] nParamIndex + Index of the structure to be filled. This value is from the + OMX_INDEXTYPE enumeration. + @param [in,out] pComponentParameterStructure + Pointer to application allocated structure to be filled by the + component. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_GetParameter( \ + hComponent, \ + nParamIndex, \ + pComponentParameterStructure) \ + ((OMX_COMPONENTTYPE*)hComponent)->GetParameter( \ + hComponent, \ + nParamIndex, \ + pComponentParameterStructure) /* Macro End */ + + +/** The OMX_SetParameter macro will send an initialization parameter + structure to a component. Each structure shall be sent one at a time, + in a separate invocation of the macro. This macro can only be + invoked when the component is in the OMX_StateLoaded state, or the + port is disabled (when the parameter applies to a port). The + nParamIndex parameter is used to indicate which structure is being + passed to the component. The application shall allocate the + correct structure and shall fill in the structure size and version + information (as well as the actual data) before invoking this macro. + The application is free to dispose of this structure after the call + as the component is required to copy any data it shall retain. This + is a blocking call. + + The component should return from this call within 20 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] nIndex + Index of the structure to be sent. This value is from the + OMX_INDEXTYPE enumeration. + @param [in] pComponentParameterStructure + pointer to application allocated structure to be used for + initialization by the component. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_SetParameter( \ + hComponent, \ + nParamIndex, \ + pComponentParameterStructure) \ + ((OMX_COMPONENTTYPE*)hComponent)->SetParameter( \ + hComponent, \ + nParamIndex, \ + pComponentParameterStructure) /* Macro End */ + + +/** The OMX_GetConfig macro will get one of the configuration structures + from a component. This macro can be invoked anytime after the + component has been loaded. The nParamIndex call parameter is used to + indicate which structure is being requested from the component. The + application shall allocate the correct structure and shall fill in the + structure size and version information before invoking this macro. + If the component has not had this configuration parameter sent before, + then the component should return a set of valid DEFAULT values for the + component. This is a blocking call. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] nIndex + Index of the structure to be filled. This value is from the + OMX_INDEXTYPE enumeration. + @param [in,out] pComponentConfigStructure + pointer to application allocated structure to be filled by the + component. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp +*/ +#define OMX_GetConfig( \ + hComponent, \ + nConfigIndex, \ + pComponentConfigStructure) \ + ((OMX_COMPONENTTYPE*)hComponent)->GetConfig( \ + hComponent, \ + nConfigIndex, \ + pComponentConfigStructure) /* Macro End */ + + +/** The OMX_SetConfig macro will send one of the configuration + structures to a component. Each structure shall be sent one at a time, + each in a separate invocation of the macro. This macro can be invoked + anytime after the component has been loaded. The application shall + allocate the correct structure and shall fill in the structure size + and version information (as well as the actual data) before invoking + this macro. The application is free to dispose of this structure after + the call as the component is required to copy any data it shall retain. + This is a blocking call. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] nConfigIndex + Index of the structure to be sent. This value is from the + OMX_INDEXTYPE enumeration above. + @param [in] pComponentConfigStructure + pointer to application allocated structure to be used for + initialization by the component. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_SetConfig( \ + hComponent, \ + nConfigIndex, \ + pComponentConfigStructure) \ + ((OMX_COMPONENTTYPE*)hComponent)->SetConfig( \ + hComponent, \ + nConfigIndex, \ + pComponentConfigStructure) /* Macro End */ + + +/** The OMX_GetExtensionIndex macro will invoke a component to translate + a vendor specific configuration or parameter string into an OMX + structure index. There is no requirement for the vendor to support + this command for the indexes already found in the OMX_INDEXTYPE + enumeration (this is done to save space in small components). The + component shall support all vendor supplied extension indexes not found + in the master OMX_INDEXTYPE enumeration. This is a blocking call. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the GetHandle function. + @param [in] cParameterName + OMX_STRING that shall be less than 128 characters long including + the trailing null byte. This is the string that will get + translated by the component into a configuration index. + @param [out] pIndexType + a pointer to a OMX_INDEXTYPE to receive the index value. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_GetExtensionIndex( \ + hComponent, \ + cParameterName, \ + pIndexType) \ + ((OMX_COMPONENTTYPE*)hComponent)->GetExtensionIndex( \ + hComponent, \ + cParameterName, \ + pIndexType) /* Macro End */ + + +/** The OMX_GetState macro will invoke the component to get the current + state of the component and place the state value into the location + pointed to by pState. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [out] pState + pointer to the location to receive the state. The value returned + is one of the OMX_STATETYPE members + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_GetState( \ + hComponent, \ + pState) \ + ((OMX_COMPONENTTYPE*)hComponent)->GetState( \ + hComponent, \ + pState) /* Macro End */ + + +/** The OMX_UseBuffer macro will request that the component use + a buffer (and allocate its own buffer header) already allocated + by another component, or by the IL Client. This is a blocking + call. + + The component should return from this call within 20 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [out] ppBuffer + pointer to an OMX_BUFFERHEADERTYPE structure used to receive the + pointer to the buffer header + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ + +#define OMX_UseBuffer( \ + hComponent, \ + ppBufferHdr, \ + nPortIndex, \ + pAppPrivate, \ + nSizeBytes, \ + pBuffer) \ + ((OMX_COMPONENTTYPE*)hComponent)->UseBuffer( \ + hComponent, \ + ppBufferHdr, \ + nPortIndex, \ + pAppPrivate, \ + nSizeBytes, \ + pBuffer) + + +/** The OMX_AllocateBuffer macro will request that the component allocate + a new buffer and buffer header. The component will allocate the + buffer and the buffer header and return a pointer to the buffer + header. This is a blocking call. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [out] ppBuffer + pointer to an OMX_BUFFERHEADERTYPE structure used to receive + the pointer to the buffer header + @param [in] nPortIndex + nPortIndex is used to select the port on the component the buffer will + be used with. The port can be found by using the nPortIndex + value as an index into the Port Definition array of the component. + @param [in] pAppPrivate + pAppPrivate is used to initialize the pAppPrivate member of the + buffer header structure. + @param [in] nSizeBytes + size of the buffer to allocate. Used when bAllocateNew is true. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ +#define OMX_AllocateBuffer( \ + hComponent, \ + ppBuffer, \ + nPortIndex, \ + pAppPrivate, \ + nSizeBytes) \ + ((OMX_COMPONENTTYPE*)hComponent)->AllocateBuffer( \ + hComponent, \ + ppBuffer, \ + nPortIndex, \ + pAppPrivate, \ + nSizeBytes) /* Macro End */ + + +/** The OMX_FreeBuffer macro will release a buffer header from the component + which was allocated using either OMX_AllocateBuffer or OMX_UseBuffer. If + the component allocated the buffer (see the OMX_UseBuffer macro) then + the component shall free the buffer and buffer header. This is a + blocking call. + + The component should return from this call within 20 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] nPortIndex + nPortIndex is used to select the port on the component the buffer will + be used with. + @param [in] pBuffer + pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer + or AllocateBuffer. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ +#define OMX_FreeBuffer( \ + hComponent, \ + nPortIndex, \ + pBuffer) \ + ((OMX_COMPONENTTYPE*)hComponent)->FreeBuffer( \ + hComponent, \ + nPortIndex, \ + pBuffer) /* Macro End */ + + +/** The OMX_EmptyThisBuffer macro will send a buffer full of data to an + input port of a component. The buffer will be emptied by the component + and returned to the application via the EmptyBufferDone call back. + This is a non-blocking call in that the component will record the buffer + and return immediately and then empty the buffer, later, at the proper + time. As expected, this macro may be invoked only while the component + is in the OMX_StateExecuting. If nPortIndex does not specify an input + port, the component shall return an error. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] pBuffer + pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer + or AllocateBuffer. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ +#define OMX_EmptyThisBuffer( \ + hComponent, \ + pBuffer) \ + ((OMX_COMPONENTTYPE*)hComponent)->EmptyThisBuffer( \ + hComponent, \ + pBuffer) /* Macro End */ + + +/** The OMX_FillThisBuffer macro will send an empty buffer to an + output port of a component. The buffer will be filled by the component + and returned to the application via the FillBufferDone call back. + This is a non-blocking call in that the component will record the buffer + and return immediately and then fill the buffer, later, at the proper + time. As expected, this macro may be invoked only while the component + is in the OMX_ExecutingState. If nPortIndex does not specify an output + port, the component shall return an error. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] pBuffer + pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer + or AllocateBuffer. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ +#define OMX_FillThisBuffer( \ + hComponent, \ + pBuffer) \ + ((OMX_COMPONENTTYPE*)hComponent)->FillThisBuffer( \ + hComponent, \ + pBuffer) /* Macro End */ + + + +/** The OMX_UseEGLImage macro will request that the component use + a EGLImage provided by EGL (and allocate its own buffer header) + This is a blocking call. + + The component should return from this call within 20 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [out] ppBuffer + pointer to an OMX_BUFFERHEADERTYPE structure used to receive the + pointer to the buffer header. Note that the memory location used + for this buffer is NOT visible to the IL Client. + @param [in] nPortIndex + nPortIndex is used to select the port on the component the buffer will + be used with. The port can be found by using the nPortIndex + value as an index into the Port Definition array of the component. + @param [in] pAppPrivate + pAppPrivate is used to initialize the pAppPrivate member of the + buffer header structure. + @param [in] eglImage + eglImage contains the handle of the EGLImage to use as a buffer on the + specified port. The component is expected to validate properties of + the EGLImage against the configuration of the port to ensure the component + can use the EGLImage as a buffer. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ +#define OMX_UseEGLImage( \ + hComponent, \ + ppBufferHdr, \ + nPortIndex, \ + pAppPrivate, \ + eglImage) \ + ((OMX_COMPONENTTYPE*)hComponent)->UseEGLImage( \ + hComponent, \ + ppBufferHdr, \ + nPortIndex, \ + pAppPrivate, \ + eglImage) + +/** The OMX_Init method is used to initialize the OMX core. It shall be the + first call made into OMX and it should only be executed one time without + an interviening OMX_Deinit call. + + The core should return from this call within 20 msec. + + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void); + + +/** The OMX_Deinit method is used to deinitialize the OMX core. It shall be + the last call made into OMX. In the event that the core determines that + thare are components loaded when this call is made, the core may return + with an error rather than try to unload the components. + + The core should return from this call within 20 msec. + + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void); + + +/** The OMX_ComponentNameEnum method will enumerate through all the names of + recognised valid components in the system. This function is provided + as a means to detect all the components in the system run-time. There is + no strict ordering to the enumeration order of component names, although + each name will only be enumerated once. If the OMX core supports run-time + installation of new components, it is only requried to detect newly + installed components when the first call to enumerate component names + is made (i.e. when nIndex is 0x0). + + The core should return from this call in 20 msec. + + @param [out] cComponentName + pointer to a null terminated string with the component name. The + names of the components are strings less than 127 bytes in length + plus the trailing null for a maximum size of 128 bytes. An example + of a valid component name is "OMX.TI.AUDIO.DSP.MIXER\0". Names are + assigned by the vendor, but shall start with "OMX." and then have + the Vendor designation next. + @param [in] nNameLength + number of characters in the cComponentName string. With all + component name strings restricted to less than 128 characters + (including the trailing null) it is recomended that the caller + provide a input string for the cComponentName of 128 characters. + @param [in] nIndex + number containing the enumeration index for the component. + Multiple calls to OMX_ComponentNameEnum with increasing values + of nIndex will enumerate through the component names in the + system until OMX_ErrorNoMore is returned. The value of nIndex + is 0 to (N-1), where N is the number of valid installed components + in the system. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. When the value of nIndex exceeds the number of + components in the system minus 1, OMX_ErrorNoMore will be + returned. Otherwise the appropriate OMX error will be returned. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum( + OMX_OUT OMX_STRING cComponentName, + OMX_IN OMX_U32 nNameLength, + OMX_IN OMX_U32 nIndex); + + +/** The OMX_GetHandle method will locate the component specified by the + component name given, load that component into memory and then invoke + the component's methods to create an instance of the component. + + The core should return from this call within 20 msec. + + @param [out] pHandle + pointer to an OMX_HANDLETYPE pointer to be filled in by this method. + @param [in] cComponentName + pointer to a null terminated string with the component name. The + names of the components are strings less than 127 bytes in length + plus the trailing null for a maximum size of 128 bytes. An example + of a valid component name is "OMX.TI.AUDIO.DSP.MIXER\0". Names are + assigned by the vendor, but shall start with "OMX." and then have + the Vendor designation next. + @param [in] pAppData + pointer to an application defined value that will be returned + during callbacks so that the application can identify the source + of the callback. + @param [in] pCallBacks + pointer to a OMX_CALLBACKTYPE structure that will be passed to the + component to initialize it with. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle( + OMX_OUT OMX_HANDLETYPE* pHandle, + OMX_IN OMX_STRING cComponentName, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_CALLBACKTYPE* pCallBacks); + + +/** The OMX_FreeHandle method will free a handle allocated by the OMX_GetHandle + method. If the component reference count goes to zero, the component will + be unloaded from memory. + + The core should return from this call within 20 msec when the component is + in the OMX_StateLoaded state. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the GetHandle function. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( + OMX_IN OMX_HANDLETYPE hComponent); + + + +/** The OMX_SetupTunnel method will handle the necessary calls to the components + to setup the specified tunnel the two components. NOTE: This is + an actual method (not a #define macro). This method will make calls into + the component ComponentTunnelRequest method to do the actual tunnel + connection. + + The ComponentTunnelRequest method on both components will be called. + This method shall not be called unless the component is in the + OMX_StateLoaded state except when the ports used for the tunnel are + disabled. In this case, the component may be in the OMX_StateExecuting, + OMX_StatePause, or OMX_StateIdle states. + + The core should return from this call within 20 msec. + + @param [in] hOutput + Handle of the component to be accessed. Also this is the handle + of the component whose port, specified in the nPortOutput parameter + will be used the source for the tunnel. This is the component handle + returned by the call to the OMX_GetHandle function. There is a + requirement that hOutput be the source for the data when + tunelling (i.e. nPortOutput is an output port). If 0x0, the component + specified in hInput will have it's port specified in nPortInput + setup for communication with the application / IL client. + @param [in] nPortOutput + nPortOutput is used to select the source port on component to be + used in the tunnel. + @param [in] hInput + This is the component to setup the tunnel with. This is the handle + of the component whose port, specified in the nPortInput parameter + will be used the destination for the tunnel. This is the component handle + returned by the call to the OMX_GetHandle function. There is a + requirement that hInput be the destination for the data when + tunelling (i.e. nPortInut is an input port). If 0x0, the component + specified in hOutput will have it's port specified in nPortPOutput + setup for communication with the application / IL client. + @param [in] nPortInput + nPortInput is used to select the destination port on component to be + used in the tunnel. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + When OMX_ErrorNotImplemented is returned, one or both components is + a non-interop component and does not support tunneling. + + On failure, the ports of both components are setup for communication + with the application / IL Client. + @ingroup core tun + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel( + OMX_IN OMX_HANDLETYPE hOutput, + OMX_IN OMX_U32 nPortOutput, + OMX_IN OMX_HANDLETYPE hInput, + OMX_IN OMX_U32 nPortInput); + +/** @ingroup cp */ +OMX_API OMX_ERRORTYPE OMX_GetContentPipe( + OMX_OUT OMX_HANDLETYPE *hPipe, + OMX_IN OMX_STRING szURI); + +/** The OMX_GetComponentsOfRole method will return the number of components that support the given + role and (if the compNames field is non-NULL) the names of those components. The call will fail if + an insufficiently sized array of names is supplied. To ensure the array is sufficiently sized the + client should: + * first call this function with the compNames field NULL to determine the number of component names + * second call this function with the compNames field pointing to an array of names allocated + according to the number returned by the first call. + + The core should return from this call within 5 msec. + + @param [in] role + This is generic standard component name consisting only of component class + name and the type within that class (e.g. 'audio_decoder.aac'). + @param [inout] pNumComps + This is used both as input and output. + + If compNames is NULL, the input is ignored and the output specifies how many components support + the given role. + + If compNames is not NULL, on input it bounds the size of the input structure and + on output, it specifies the number of components string names listed within the compNames parameter. + @param [inout] compNames + If NULL this field is ignored. If non-NULL this points to an array of 128-byte strings which accepts + a list of the names of all physical components that implement the specified standard component name. + Each name is NULL terminated. numComps indicates the number of names. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole ( + OMX_IN OMX_STRING role, + OMX_INOUT OMX_U32 *pNumComps, + OMX_INOUT OMX_U8 **compNames); + +/** The OMX_GetRolesOfComponent method will return the number of roles supported by the given + component and (if the roles field is non-NULL) the names of those roles. The call will fail if + an insufficiently sized array of names is supplied. To ensure the array is sufficiently sized the + client should: + * first call this function with the roles field NULL to determine the number of role names + * second call this function with the roles field pointing to an array of names allocated + according to the number returned by the first call. + + The core should return from this call within 5 msec. + + @param [in] compName + This is the name of the component being queried about. + @param [inout] pNumRoles + This is used both as input and output. + + If roles is NULL, the input is ignored and the output specifies how many roles the component supports. + + If compNames is not NULL, on input it bounds the size of the input structure and + on output, it specifies the number of roles string names listed within the roles parameter. + @param [out] roles + If NULL this field is ignored. If non-NULL this points to an array of 128-byte strings + which accepts a list of the names of all standard components roles implemented on the + specified component name. numComps indicates the number of names. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent ( + OMX_IN OMX_STRING compName, + OMX_INOUT OMX_U32 *pNumRoles, + OMX_OUT OMX_U8 **roles); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ + diff --git a/mm-core/inc/OMX_CoreExt.h b/mm-core/inc/OMX_CoreExt.h new file mode 100755 index 0000000..3a18eb7 --- /dev/null +++ b/mm-core/inc/OMX_CoreExt.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_CoreExt.h - OpenMax IL version 1.1.2 + * The OMX_CoreExt header file contains extensions to the definitions used + * by both the application and the component to access common items. + */ + +#ifndef OMX_CoreExt_h +#define OMX_CoreExt_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Each OMX header shall include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ +#include + + +/** Event type extensions. */ +typedef enum OMX_EVENTEXTTYPE +{ + OMX_EventIndexSettingChanged = OMX_EventKhronosExtensions, /**< component signals the IL client of a change + in a param, config, or extension */ + OMX_EventExtMax = 0x7FFFFFFF +} OMX_EVENTEXTTYPE; + + +/** Enable or disable a callback event. */ +typedef struct OMX_CONFIG_CALLBACKREQUESTTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_INDEXTYPE nIndex; /**< the index the callback is requested for */ + OMX_BOOL bEnable; /**< enable (OMX_TRUE) or disable (OMX_FALSE) the callback */ +} OMX_CONFIG_CALLBACKREQUESTTYPE; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OMX_CoreExt_h */ +/* File EOF */ diff --git a/mm-core/inc/OMX_IVCommon.h b/mm-core/inc/OMX_IVCommon.h new file mode 100755 index 0000000..4c4995c --- /dev/null +++ b/mm-core/inc/OMX_IVCommon.h @@ -0,0 +1,920 @@ +/** + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file OMX_IVCommon.h - OpenMax IL version 1.1.2 + * The structures needed by Video and Image components to exchange + * parameters and configuration data with the components. + */ +#ifndef OMX_IVCommon_h +#define OMX_IVCommon_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * Each OMX header must include all required header files to allow the header + * to compile without errors. The includes below are required for this header + * file to compile successfully + */ + +#include + +/** @defgroup iv OpenMAX IL Imaging and Video Domain + * Common structures for OpenMAX IL Imaging and Video domains + * @{ + */ + + +/** + * Enumeration defining possible uncompressed image/video formats. + * + * ENUMS: + * Unused : Placeholder value when format is N/A + * Monochrome : black and white + * 8bitRGB332 : Red 7:5, Green 4:2, Blue 1:0 + * 12bitRGB444 : Red 11:8, Green 7:4, Blue 3:0 + * 16bitARGB4444 : Alpha 15:12, Red 11:8, Green 7:4, Blue 3:0 + * 16bitARGB1555 : Alpha 15, Red 14:10, Green 9:5, Blue 4:0 + * 16bitRGB565 : Red 15:11, Green 10:5, Blue 4:0 + * 16bitBGR565 : Blue 15:11, Green 10:5, Red 4:0 + * 18bitRGB666 : Red 17:12, Green 11:6, Blue 5:0 + * 18bitARGB1665 : Alpha 17, Red 16:11, Green 10:5, Blue 4:0 + * 19bitARGB1666 : Alpha 18, Red 17:12, Green 11:6, Blue 5:0 + * 24bitRGB888 : Red 24:16, Green 15:8, Blue 7:0 + * 24bitBGR888 : Blue 24:16, Green 15:8, Red 7:0 + * 24bitARGB1887 : Alpha 23, Red 22:15, Green 14:7, Blue 6:0 + * 25bitARGB1888 : Alpha 24, Red 23:16, Green 15:8, Blue 7:0 + * 32bitBGRA8888 : Blue 31:24, Green 23:16, Red 15:8, Alpha 7:0 + * 32bitARGB8888 : Alpha 31:24, Red 23:16, Green 15:8, Blue 7:0 + * YUV411Planar : U,Y are subsampled by a factor of 4 horizontally + * YUV411PackedPlanar : packed per payload in planar slices + * YUV420Planar : Three arrays Y,U,V. + * YUV420PackedPlanar : packed per payload in planar slices + * YUV420SemiPlanar : Two arrays, one is all Y, the other is U and V + * YUV422Planar : Three arrays Y,U,V. + * YUV422PackedPlanar : packed per payload in planar slices + * YUV422SemiPlanar : Two arrays, one is all Y, the other is U and V + * YCbYCr : Organized as 16bit YUYV (i.e. YCbYCr) + * YCrYCb : Organized as 16bit YVYU (i.e. YCrYCb) + * CbYCrY : Organized as 16bit UYVY (i.e. CbYCrY) + * CrYCbY : Organized as 16bit VYUY (i.e. CrYCbY) + * YUV444Interleaved : Each pixel contains equal parts YUV + * RawBayer8bit : SMIA camera output format + * RawBayer10bit : SMIA camera output format + * RawBayer8bitcompressed : SMIA camera output format + */ +typedef enum OMX_COLOR_FORMATTYPE { + OMX_COLOR_FormatUnused, + OMX_COLOR_FormatMonochrome, + OMX_COLOR_Format8bitRGB332, + OMX_COLOR_Format12bitRGB444, + OMX_COLOR_Format16bitARGB4444, + OMX_COLOR_Format16bitARGB1555, + OMX_COLOR_Format16bitRGB565, + OMX_COLOR_Format16bitBGR565, + OMX_COLOR_Format18bitRGB666, + OMX_COLOR_Format18bitARGB1665, + OMX_COLOR_Format19bitARGB1666, + OMX_COLOR_Format24bitRGB888, + OMX_COLOR_Format24bitBGR888, + OMX_COLOR_Format24bitARGB1887, + OMX_COLOR_Format25bitARGB1888, + OMX_COLOR_Format32bitBGRA8888, + OMX_COLOR_Format32bitARGB8888, + OMX_COLOR_FormatYUV411Planar, + OMX_COLOR_FormatYUV411PackedPlanar, + OMX_COLOR_FormatYUV420Planar, + OMX_COLOR_FormatYUV420PackedPlanar, + OMX_COLOR_FormatYUV420SemiPlanar, + OMX_COLOR_FormatYUV422Planar, + OMX_COLOR_FormatYUV422PackedPlanar, + OMX_COLOR_FormatYUV422SemiPlanar, + OMX_COLOR_FormatYCbYCr, + OMX_COLOR_FormatYCrYCb, + OMX_COLOR_FormatCbYCrY, + OMX_COLOR_FormatCrYCbY, + OMX_COLOR_FormatYUV444Interleaved, + OMX_COLOR_FormatRawBayer8bit, + OMX_COLOR_FormatRawBayer10bit, + OMX_COLOR_FormatRawBayer8bitcompressed, + OMX_COLOR_FormatL2, + OMX_COLOR_FormatL4, + OMX_COLOR_FormatL8, + OMX_COLOR_FormatL16, + OMX_COLOR_FormatL24, + OMX_COLOR_FormatL32, + OMX_COLOR_FormatYUV420PackedSemiPlanar, + OMX_COLOR_FormatYUV422PackedSemiPlanar, + OMX_COLOR_Format18BitBGR666, + OMX_COLOR_Format24BitARGB6666, + OMX_COLOR_Format24BitABGR6666, + OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_COLOR_FormatMax = 0x7FFFFFFF +} OMX_COLOR_FORMATTYPE; + + +/** + * Defines the matrix for conversion from RGB to YUV or vice versa. + * iColorMatrix should be initialized with the fixed point values + * used in converting between formats. + */ +typedef struct OMX_CONFIG_COLORCONVERSIONTYPE { + OMX_U32 nSize; /**< Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version info */ + OMX_U32 nPortIndex; /**< Port that this struct applies to */ + OMX_S32 xColorMatrix[3][3]; /**< Stored in signed Q16 format */ + OMX_S32 xColorOffset[4]; /**< Stored in signed Q16 format */ +}OMX_CONFIG_COLORCONVERSIONTYPE; + + +/** + * Structure defining percent to scale each frame dimension. For example: + * To make the width 50% larger, use fWidth = 1.5 and to make the width + * 1/2 the original size, use fWidth = 0.5 + */ +typedef struct OMX_CONFIG_SCALEFACTORTYPE { + OMX_U32 nSize; /**< Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version info */ + OMX_U32 nPortIndex; /**< Port that this struct applies to */ + OMX_S32 xWidth; /**< Fixed point value stored as Q16 */ + OMX_S32 xHeight; /**< Fixed point value stored as Q16 */ +}OMX_CONFIG_SCALEFACTORTYPE; + + +/** + * Enumeration of possible image filter types + */ +typedef enum OMX_IMAGEFILTERTYPE { + OMX_ImageFilterNone, + OMX_ImageFilterNoise, + OMX_ImageFilterEmboss, + OMX_ImageFilterNegative, + OMX_ImageFilterSketch, + OMX_ImageFilterOilPaint, + OMX_ImageFilterHatch, + OMX_ImageFilterGpen, + OMX_ImageFilterAntialias, + OMX_ImageFilterDeRing, + OMX_ImageFilterSolarize, + OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ImageFilterVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_ImageFilterMax = 0x7FFFFFFF +} OMX_IMAGEFILTERTYPE; + + +/** + * Image filter configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eImageFilter : Image filter type enumeration + */ +typedef struct OMX_CONFIG_IMAGEFILTERTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_IMAGEFILTERTYPE eImageFilter; +} OMX_CONFIG_IMAGEFILTERTYPE; + + +/** + * Customized U and V for color enhancement + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bColorEnhancement : Enable/disable color enhancement + * nCustomizedU : Practical values: 16-240, range: 0-255, value set for + * U component + * nCustomizedV : Practical values: 16-240, range: 0-255, value set for + * V component + */ +typedef struct OMX_CONFIG_COLORENHANCEMENTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bColorEnhancement; + OMX_U8 nCustomizedU; + OMX_U8 nCustomizedV; +} OMX_CONFIG_COLORENHANCEMENTTYPE; + + +/** + * Define color key and color key mask + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nARGBColor : 32bit Alpha, Red, Green, Blue Color + * nARGBMask : 32bit Mask for Alpha, Red, Green, Blue channels + */ +typedef struct OMX_CONFIG_COLORKEYTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nARGBColor; + OMX_U32 nARGBMask; +} OMX_CONFIG_COLORKEYTYPE; + + +/** + * List of color blend types for pre/post processing + * + * ENUMS: + * None : No color blending present + * AlphaConstant : Function is (alpha_constant * src) + + * (1 - alpha_constant) * dst) + * AlphaPerPixel : Function is (alpha * src) + (1 - alpha) * dst) + * Alternate : Function is alternating pixels from src and dst + * And : Function is (src & dst) + * Or : Function is (src | dst) + * Invert : Function is ~src + */ +typedef enum OMX_COLORBLENDTYPE { + OMX_ColorBlendNone, + OMX_ColorBlendAlphaConstant, + OMX_ColorBlendAlphaPerPixel, + OMX_ColorBlendAlternate, + OMX_ColorBlendAnd, + OMX_ColorBlendOr, + OMX_ColorBlendInvert, + OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ColorBlendVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_ColorBlendMax = 0x7FFFFFFF +} OMX_COLORBLENDTYPE; + + +/** + * Color blend configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nRGBAlphaConstant : Constant global alpha values when global alpha is used + * eColorBlend : Color blend type enumeration + */ +typedef struct OMX_CONFIG_COLORBLENDTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nRGBAlphaConstant; + OMX_COLORBLENDTYPE eColorBlend; +} OMX_CONFIG_COLORBLENDTYPE; + + +/** + * Hold frame dimension + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nWidth : Frame width in pixels + * nHeight : Frame height in pixels + */ +typedef struct OMX_FRAMESIZETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nWidth; + OMX_U32 nHeight; +} OMX_FRAMESIZETYPE; + + +/** + * Rotation configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nRotation : +/- integer rotation value + */ +typedef struct OMX_CONFIG_ROTATIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nRotation; +} OMX_CONFIG_ROTATIONTYPE; + + +/** + * Possible mirroring directions for pre/post processing + * + * ENUMS: + * None : No mirroring + * Vertical : Vertical mirroring, flip on X axis + * Horizontal : Horizontal mirroring, flip on Y axis + * Both : Both vertical and horizontal mirroring + */ +typedef enum OMX_MIRRORTYPE { + OMX_MirrorNone = 0, + OMX_MirrorVertical, + OMX_MirrorHorizontal, + OMX_MirrorBoth, + OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MirrorVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_MirrorMax = 0x7FFFFFFF +} OMX_MIRRORTYPE; + + +/** + * Mirroring configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eMirror : Mirror type enumeration + */ +typedef struct OMX_CONFIG_MIRRORTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_MIRRORTYPE eMirror; +} OMX_CONFIG_MIRRORTYPE; + + +/** + * Position information only + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nX : X coordinate for the point + * nY : Y coordinate for the point + */ +typedef struct OMX_CONFIG_POINTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nX; + OMX_S32 nY; +} OMX_CONFIG_POINTTYPE; + + +/** + * Frame size plus position + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nLeft : X Coordinate of the top left corner of the rectangle + * nTop : Y Coordinate of the top left corner of the rectangle + * nWidth : Width of the rectangle + * nHeight : Height of the rectangle + */ +typedef struct OMX_CONFIG_RECTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nLeft; + OMX_S32 nTop; + OMX_U32 nWidth; + OMX_U32 nHeight; +} OMX_CONFIG_RECTTYPE; + + +/** + * Deblocking state; it is required to be set up before starting the codec + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bDeblocking : Enable/disable deblocking mode + */ +typedef struct OMX_PARAM_DEBLOCKINGTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bDeblocking; +} OMX_PARAM_DEBLOCKINGTYPE; + + +/** + * Stabilization state + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bStab : Enable/disable frame stabilization state + */ +typedef struct OMX_CONFIG_FRAMESTABTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bStab; +} OMX_CONFIG_FRAMESTABTYPE; + + +/** + * White Balance control type + * + * STRUCT MEMBERS: + * SunLight : Referenced in JSR-234 + * Flash : Optimal for device's integrated flash + */ +typedef enum OMX_WHITEBALCONTROLTYPE { + OMX_WhiteBalControlOff = 0, + OMX_WhiteBalControlAuto, + OMX_WhiteBalControlSunLight, + OMX_WhiteBalControlCloudy, + OMX_WhiteBalControlShade, + OMX_WhiteBalControlTungsten, + OMX_WhiteBalControlFluorescent, + OMX_WhiteBalControlIncandescent, + OMX_WhiteBalControlFlash, + OMX_WhiteBalControlHorizon, + OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_WhiteBalControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_WhiteBalControlMax = 0x7FFFFFFF +} OMX_WHITEBALCONTROLTYPE; + + +/** + * White Balance control configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eWhiteBalControl : White balance enumeration + */ +typedef struct OMX_CONFIG_WHITEBALCONTROLTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_WHITEBALCONTROLTYPE eWhiteBalControl; +} OMX_CONFIG_WHITEBALCONTROLTYPE; + + +/** + * Exposure control type + */ +typedef enum OMX_EXPOSURECONTROLTYPE { + OMX_ExposureControlOff = 0, + OMX_ExposureControlAuto, + OMX_ExposureControlNight, + OMX_ExposureControlBackLight, + OMX_ExposureControlSpotLight, + OMX_ExposureControlSports, + OMX_ExposureControlSnow, + OMX_ExposureControlBeach, + OMX_ExposureControlLargeAperture, + OMX_ExposureControlSmallApperture, + OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ExposureControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_ExposureControlMax = 0x7FFFFFFF +} OMX_EXPOSURECONTROLTYPE; + + +/** + * White Balance control configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eExposureControl : Exposure control enumeration + */ +typedef struct OMX_CONFIG_EXPOSURECONTROLTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_EXPOSURECONTROLTYPE eExposureControl; +} OMX_CONFIG_EXPOSURECONTROLTYPE; + + +/** + * Defines sensor supported mode. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nFrameRate : Single shot mode is indicated by a 0 + * bOneShot : Enable for single shot, disable for streaming + * sFrameSize : Framesize + */ +typedef struct OMX_PARAM_SENSORMODETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nFrameRate; + OMX_BOOL bOneShot; + OMX_FRAMESIZETYPE sFrameSize; +} OMX_PARAM_SENSORMODETYPE; + + +/** + * Defines contrast level + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nContrast : Values allowed for contrast -100 to 100, zero means no change + */ +typedef struct OMX_CONFIG_CONTRASTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nContrast; +} OMX_CONFIG_CONTRASTTYPE; + + +/** + * Defines brightness level + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nBrightness : 0-100% + */ +typedef struct OMX_CONFIG_BRIGHTNESSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nBrightness; +} OMX_CONFIG_BRIGHTNESSTYPE; + + +/** + * Defines backlight level configuration for a video sink, e.g. LCD panel + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nBacklight : Values allowed for backlight 0-100% + * nTimeout : Number of milliseconds before backlight automatically turns + * off. A value of 0x0 disables backight timeout + */ +typedef struct OMX_CONFIG_BACKLIGHTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nBacklight; + OMX_U32 nTimeout; +} OMX_CONFIG_BACKLIGHTTYPE; + + +/** + * Defines setting for Gamma + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nGamma : Values allowed for gamma -100 to 100, zero means no change + */ +typedef struct OMX_CONFIG_GAMMATYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nGamma; +} OMX_CONFIG_GAMMATYPE; + + +/** + * Define for setting saturation + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nSaturation : Values allowed for saturation -100 to 100, zero means + * no change + */ +typedef struct OMX_CONFIG_SATURATIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nSaturation; +} OMX_CONFIG_SATURATIONTYPE; + + +/** + * Define for setting Lightness + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nLightness : Values allowed for lightness -100 to 100, zero means no + * change + */ +typedef struct OMX_CONFIG_LIGHTNESSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nLightness; +} OMX_CONFIG_LIGHTNESSTYPE; + + +/** + * Plane blend configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Index of input port associated with the plane. + * nDepth : Depth of the plane in relation to the screen. Higher + * numbered depths are "behind" lower number depths. + * This number defaults to the Port Index number. + * nAlpha : Transparency blending component for the entire plane. + * See blending modes for more detail. + */ +typedef struct OMX_CONFIG_PLANEBLENDTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nDepth; + OMX_U32 nAlpha; +} OMX_CONFIG_PLANEBLENDTYPE; + + +/** + * Define interlace type + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bEnable : Enable control variable for this functionality + * (see below) + * nInterleavePortIndex : Index of input or output port associated with + * the interleaved plane. + * pPlanarPortIndexes[4] : Index of input or output planar ports. + */ +typedef struct OMX_PARAM_INTERLEAVETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnable; + OMX_U32 nInterleavePortIndex; +} OMX_PARAM_INTERLEAVETYPE; + + +/** + * Defines the picture effect used for an input picture + */ +typedef enum OMX_TRANSITIONEFFECTTYPE { + OMX_EffectNone, + OMX_EffectFadeFromBlack, + OMX_EffectFadeToBlack, + OMX_EffectUnspecifiedThroughConstantColor, + OMX_EffectDissolve, + OMX_EffectWipe, + OMX_EffectUnspecifiedMixOfTwoScenes, + OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_EffectVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_EffectMax = 0x7FFFFFFF +} OMX_TRANSITIONEFFECTTYPE; + + +/** + * Structure used to configure current transition effect + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eEffect : Effect to enable + */ +typedef struct OMX_CONFIG_TRANSITIONEFFECTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_TRANSITIONEFFECTTYPE eEffect; +} OMX_CONFIG_TRANSITIONEFFECTTYPE; + + +/** + * Defines possible data unit types for encoded video data. The data unit + * types are used both for encoded video input for playback as well as + * encoded video output from recording. + */ +typedef enum OMX_DATAUNITTYPE { + OMX_DataUnitCodedPicture, + OMX_DataUnitVideoSegment, + OMX_DataUnitSeveralSegments, + OMX_DataUnitArbitraryStreamSection, + OMX_DataUnitKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_DataUnitVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_DataUnitMax = 0x7FFFFFFF +} OMX_DATAUNITTYPE; + + +/** + * Defines possible encapsulation types for coded video data unit. The + * encapsulation information is used both for encoded video input for + * playback as well as encoded video output from recording. + */ +typedef enum OMX_DATAUNITENCAPSULATIONTYPE { + OMX_DataEncapsulationElementaryStream, + OMX_DataEncapsulationGenericPayload, + OMX_DataEncapsulationRtpPayload, + OMX_DataEncapsulationKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_DataEncapsulationVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_DataEncapsulationMax = 0x7FFFFFFF +} OMX_DATAUNITENCAPSULATIONTYPE; + + +/** + * Structure used to configure the type of being decoded/encoded + */ +typedef struct OMX_PARAM_DATAUNITTYPE { + OMX_U32 nSize; /**< Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_DATAUNITTYPE eUnitType; + OMX_DATAUNITENCAPSULATIONTYPE eEncapsulationType; +} OMX_PARAM_DATAUNITTYPE; + + +/** + * Defines dither types + */ +typedef enum OMX_DITHERTYPE { + OMX_DitherNone, + OMX_DitherOrdered, + OMX_DitherErrorDiffusion, + OMX_DitherOther, + OMX_DitherKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_DitherVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_DitherMax = 0x7FFFFFFF +} OMX_DITHERTYPE; + + +/** + * Structure used to configure current type of dithering + */ +typedef struct OMX_CONFIG_DITHERTYPE { + OMX_U32 nSize; /**< Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_DITHERTYPE eDither; /**< Type of dithering to use */ +} OMX_CONFIG_DITHERTYPE; + +typedef struct OMX_CONFIG_CAPTUREMODETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_BOOL bContinuous; /**< If true then ignore frame rate and emit capture + * data as fast as possible (otherwise obey port's frame rate). */ + OMX_BOOL bFrameLimited; /**< If true then terminate capture after the port emits the + * specified number of frames (otherwise the port does not + * terminate the capture until instructed to do so by the client). + * Even if set, the client may manually terminate the capture prior + * to reaching the limit. */ + OMX_U32 nFrameLimit; /**< Limit on number of frames emitted during a capture (only + * valid if bFrameLimited is set). */ +} OMX_CONFIG_CAPTUREMODETYPE; + +typedef enum OMX_METERINGTYPE { + + OMX_MeteringModeAverage, /**< Center-weighted average metering. */ + OMX_MeteringModeSpot, /**< Spot (partial) metering. */ + OMX_MeteringModeMatrix, /**< Matrix or evaluative metering. */ + + OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MeteringVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_EVModeMax = 0x7fffffff +} OMX_METERINGTYPE; + +typedef struct OMX_CONFIG_EXPOSUREVALUETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_METERINGTYPE eMetering; + OMX_S32 xEVCompensation; /**< Fixed point value stored as Q16 */ + OMX_U32 nApertureFNumber; /**< e.g. nApertureFNumber = 2 implies "f/2" - Q16 format */ + OMX_BOOL bAutoAperture; /**< Whether aperture number is defined automatically */ + OMX_U32 nShutterSpeedMsec; /**< Shutterspeed in milliseconds */ + OMX_BOOL bAutoShutterSpeed; /**< Whether shutter speed is defined automatically */ + OMX_U32 nSensitivity; /**< e.g. nSensitivity = 100 implies "ISO 100" */ + OMX_BOOL bAutoSensitivity; /**< Whether sensitivity is defined automatically */ +} OMX_CONFIG_EXPOSUREVALUETYPE; + +/** + * Focus region configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bCenter : Use center region as focus region of interest + * bLeft : Use left region as focus region of interest + * bRight : Use right region as focus region of interest + * bTop : Use top region as focus region of interest + * bBottom : Use bottom region as focus region of interest + * bTopLeft : Use top left region as focus region of interest + * bTopRight : Use top right region as focus region of interest + * bBottomLeft : Use bottom left region as focus region of interest + * bBottomRight : Use bottom right region as focus region of interest + */ +typedef struct OMX_CONFIG_FOCUSREGIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bCenter; + OMX_BOOL bLeft; + OMX_BOOL bRight; + OMX_BOOL bTop; + OMX_BOOL bBottom; + OMX_BOOL bTopLeft; + OMX_BOOL bTopRight; + OMX_BOOL bBottomLeft; + OMX_BOOL bBottomRight; +} OMX_CONFIG_FOCUSREGIONTYPE; + +/** + * Focus Status type + */ +typedef enum OMX_FOCUSSTATUSTYPE { + OMX_FocusStatusOff = 0, + OMX_FocusStatusRequest, + OMX_FocusStatusReached, + OMX_FocusStatusUnableToReach, + OMX_FocusStatusLost, + OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_FocusStatusVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_FocusStatusMax = 0x7FFFFFFF +} OMX_FOCUSSTATUSTYPE; + +/** + * Focus status configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFocusStatus : Specifies the focus status + * bCenterStatus : Use center region as focus region of interest + * bLeftStatus : Use left region as focus region of interest + * bRightStatus : Use right region as focus region of interest + * bTopStatus : Use top region as focus region of interest + * bBottomStatus : Use bottom region as focus region of interest + * bTopLeftStatus : Use top left region as focus region of interest + * bTopRightStatus : Use top right region as focus region of interest + * bBottomLeftStatus : Use bottom left region as focus region of interest + * bBottomRightStatus : Use bottom right region as focus region of interest + */ +typedef struct OMX_PARAM_FOCUSSTATUSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_FOCUSSTATUSTYPE eFocusStatus; + OMX_BOOL bCenterStatus; + OMX_BOOL bLeftStatus; + OMX_BOOL bRightStatus; + OMX_BOOL bTopStatus; + OMX_BOOL bBottomStatus; + OMX_BOOL bTopLeftStatus; + OMX_BOOL bTopRightStatus; + OMX_BOOL bBottomLeftStatus; + OMX_BOOL bBottomRightStatus; +} OMX_PARAM_FOCUSSTATUSTYPE; + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ diff --git a/mm-core/inc/OMX_Image.h b/mm-core/inc/OMX_Image.h new file mode 100755 index 0000000..a6d4666 --- /dev/null +++ b/mm-core/inc/OMX_Image.h @@ -0,0 +1,328 @@ +/** + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @file OMX_Image.h - OpenMax IL version 1.1.2 + * The structures needed by Image components to exchange parameters and + * configuration data with the components. + */ +#ifndef OMX_Image_h +#define OMX_Image_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/** + * Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include + +/** @defgroup imaging OpenMAX IL Imaging Domain + * @ingroup iv + * Structures for OpenMAX IL Imaging domain + * @{ + */ + +/** + * Enumeration used to define the possible image compression coding. + */ +typedef enum OMX_IMAGE_CODINGTYPE { + OMX_IMAGE_CodingUnused, /**< Value when format is N/A */ + OMX_IMAGE_CodingAutoDetect, /**< Auto detection of image format */ + OMX_IMAGE_CodingJPEG, /**< JPEG/JFIF image format */ + OMX_IMAGE_CodingJPEG2K, /**< JPEG 2000 image format */ + OMX_IMAGE_CodingEXIF, /**< EXIF image format */ + OMX_IMAGE_CodingTIFF, /**< TIFF image format */ + OMX_IMAGE_CodingGIF, /**< Graphics image format */ + OMX_IMAGE_CodingPNG, /**< PNG image format */ + OMX_IMAGE_CodingLZW, /**< LZW image format */ + OMX_IMAGE_CodingBMP, /**< Windows Bitmap format */ + OMX_IMAGE_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_IMAGE_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_IMAGE_CodingMax = 0x7FFFFFFF +} OMX_IMAGE_CODINGTYPE; + + +/** + * Data structure used to define an image path. The number of image paths + * for input and output will vary by type of the image component. + * + * Input (aka Source) : Zero Inputs, one Output, + * Splitter : One Input, 2 or more Outputs, + * Processing Element : One Input, one output, + * Mixer : 2 or more inputs, one output, + * Output (aka Sink) : One Input, zero outputs. + * + * The PortDefinition structure is used to define all of the parameters + * necessary for the compliant component to setup an input or an output + * image path. If additional vendor specific data is required, it should + * be transmitted to the component using the CustomCommand function. + * Compliant components will prepopulate this structure with optimal + * values during the OMX_GetParameter() command. + * + * STRUCT MEMBERS: + * cMIMEType : MIME type of data for the port + * pNativeRender : Platform specific reference for a display if a + * sync, otherwise this field is 0 + * nFrameWidth : Width of frame to be used on port if + * uncompressed format is used. Use 0 for + * unknown, don't care or variable + * nFrameHeight : Height of frame to be used on port if + * uncompressed format is used. Use 0 for + * unknown, don't care or variable + * nStride : Number of bytes per span of an image (i.e. + * indicates the number of bytes to get from + * span N to span N+1, where negative stride + * indicates the image is bottom up + * nSliceHeight : Height used when encoding in slices + * bFlagErrorConcealment : Turns on error concealment if it is supported by + * the OMX component + * eCompressionFormat : Compression format used in this instance of + * the component. When OMX_IMAGE_CodingUnused is + * specified, eColorFormat is valid + * eColorFormat : Decompressed format used by this component + * pNativeWindow : Platform specific reference for a window object if a + * display sink , otherwise this field is 0x0. + */ +typedef struct OMX_IMAGE_PORTDEFINITIONTYPE { + OMX_STRING cMIMEType; + OMX_NATIVE_DEVICETYPE pNativeRender; + OMX_U32 nFrameWidth; + OMX_U32 nFrameHeight; + OMX_S32 nStride; + OMX_U32 nSliceHeight; + OMX_BOOL bFlagErrorConcealment; + OMX_IMAGE_CODINGTYPE eCompressionFormat; + OMX_COLOR_FORMATTYPE eColorFormat; + OMX_NATIVE_WINDOWTYPE pNativeWindow; +} OMX_IMAGE_PORTDEFINITIONTYPE; + + +/** + * Port format parameter. This structure is used to enumerate the various + * data input/output format supported by the port. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Indicates which port to set + * nIndex : Indicates the enumeration index for the format from + * 0x0 to N-1 + * eCompressionFormat : Compression format used in this instance of the + * component. When OMX_IMAGE_CodingUnused is specified, + * eColorFormat is valid + * eColorFormat : Decompressed format used by this component + */ +typedef struct OMX_IMAGE_PARAM_PORTFORMATTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nIndex; + OMX_IMAGE_CODINGTYPE eCompressionFormat; + OMX_COLOR_FORMATTYPE eColorFormat; +} OMX_IMAGE_PARAM_PORTFORMATTYPE; + + +/** + * Flash control type + * + * ENUMS + * Torch : Flash forced constantly on + */ +typedef enum OMX_IMAGE_FLASHCONTROLTYPE { + OMX_IMAGE_FlashControlOn = 0, + OMX_IMAGE_FlashControlOff, + OMX_IMAGE_FlashControlAuto, + OMX_IMAGE_FlashControlRedEyeReduction, + OMX_IMAGE_FlashControlFillin, + OMX_IMAGE_FlashControlTorch, + OMX_IMAGE_FlashControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_IMAGE_FlashControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_IMAGE_FlashControlMax = 0x7FFFFFFF +} OMX_IMAGE_FLASHCONTROLTYPE; + + +/** + * Flash control configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFlashControl : Flash control type + */ +typedef struct OMX_IMAGE_PARAM_FLASHCONTROLTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_IMAGE_FLASHCONTROLTYPE eFlashControl; +} OMX_IMAGE_PARAM_FLASHCONTROLTYPE; + + +/** + * Focus control type + */ +typedef enum OMX_IMAGE_FOCUSCONTROLTYPE { + OMX_IMAGE_FocusControlOn = 0, + OMX_IMAGE_FocusControlOff, + OMX_IMAGE_FocusControlAuto, + OMX_IMAGE_FocusControlAutoLock, + OMX_IMAGE_FocusControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_IMAGE_FocusControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_IMAGE_FocusControlMax = 0x7FFFFFFF +} OMX_IMAGE_FOCUSCONTROLTYPE; + + +/** + * Focus control configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFocusControl : Focus control + * nFocusSteps : Focus can take on values from 0 mm to infinity. + * Interest is only in number of steps over this range. + * nFocusStepIndex : Current focus step index + */ +typedef struct OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_IMAGE_FOCUSCONTROLTYPE eFocusControl; + OMX_U32 nFocusSteps; + OMX_U32 nFocusStepIndex; +} OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE; + + +/** + * Q Factor for JPEG compression, which controls the tradeoff between image + * quality and size. Q Factor provides a more simple means of controlling + * JPEG compression quality, without directly programming Quantization + * tables for chroma and luma + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nQFactor : JPEG Q factor value in the range of 1-100. A factor of 1 + * produces the smallest, worst quality images, and a factor + * of 100 produces the largest, best quality images. A + * typical default is 75 for small good quality images + */ +typedef struct OMX_IMAGE_PARAM_QFACTORTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nQFactor; +} OMX_IMAGE_PARAM_QFACTORTYPE; + +/** + * Quantization table type + */ + +typedef enum OMX_IMAGE_QUANTIZATIONTABLETYPE { + OMX_IMAGE_QuantizationTableLuma = 0, + OMX_IMAGE_QuantizationTableChroma, + OMX_IMAGE_QuantizationTableChromaCb, + OMX_IMAGE_QuantizationTableChromaCr, + OMX_IMAGE_QuantizationTableKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_IMAGE_QuantizationTableVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_IMAGE_QuantizationTableMax = 0x7FFFFFFF +} OMX_IMAGE_QUANTIZATIONTABLETYPE; + +/** + * JPEG quantization tables are used to determine DCT compression for + * YUV data, as an alternative to specifying Q factor, providing exact + * control of compression + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eQuantizationTable : Quantization table type + * nQuantizationMatrix[64] : JPEG quantization table of coefficients stored + * in increasing columns then by rows of data (i.e. + * row 1, ... row 8). Quantization values are in + * the range 0-255 and stored in linear order + * (i.e. the component will zig-zag the + * quantization table data if required internally) + */ +typedef struct OMX_IMAGE_PARAM_QUANTIZATIONTABLETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_IMAGE_QUANTIZATIONTABLETYPE eQuantizationTable; + OMX_U8 nQuantizationMatrix[64]; +} OMX_IMAGE_PARAM_QUANTIZATIONTABLETYPE; + + +/** + * Huffman table type, the same Huffman table is applied for chroma and + * luma component + */ +typedef enum OMX_IMAGE_HUFFMANTABLETYPE { + OMX_IMAGE_HuffmanTableAC = 0, + OMX_IMAGE_HuffmanTableDC, + OMX_IMAGE_HuffmanTableACLuma, + OMX_IMAGE_HuffmanTableACChroma, + OMX_IMAGE_HuffmanTableDCLuma, + OMX_IMAGE_HuffmanTableDCChroma, + OMX_IMAGE_HuffmanTableKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_IMAGE_HuffmanTableVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_IMAGE_HuffmanTableMax = 0x7FFFFFFF +} OMX_IMAGE_HUFFMANTABLETYPE; + +/** + * JPEG Huffman table + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eHuffmanTable : Huffman table type + * nNumberOfHuffmanCodeOfLength[16] : 0-16, number of Huffman codes of each + * possible length + * nHuffmanTable[256] : 0-255, the size used for AC and DC + * HuffmanTable are 16 and 162 + */ +typedef struct OMX_IMAGE_PARAM_HUFFMANTTABLETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_IMAGE_HUFFMANTABLETYPE eHuffmanTable; + OMX_U8 nNumberOfHuffmanCodeOfLength[16]; + OMX_U8 nHuffmanTable[256]; +}OMX_IMAGE_PARAM_HUFFMANTTABLETYPE; + +/** @} */ +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ diff --git a/mm-core/inc/OMX_Index.h b/mm-core/inc/OMX_Index.h new file mode 100755 index 0000000..44d4ea7 --- /dev/null +++ b/mm-core/inc/OMX_Index.h @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** @file OMX_Index.h - OpenMax IL version 1.1.2 + * The OMX_Index header file contains the definitions for both applications + * and components . + */ + + +#ifndef OMX_Index_h +#define OMX_Index_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ +#include + + +/** The OMX_INDEXTYPE enumeration is used to select a structure when either + * getting or setting parameters and/or configuration data. Each entry in + * this enumeration maps to an OMX specified structure. When the + * OMX_GetParameter, OMX_SetParameter, OMX_GetConfig or OMX_SetConfig methods + * are used, the second parameter will always be an entry from this enumeration + * and the third entry will be the structure shown in the comments for the entry. + * For example, if the application is initializing a cropping function, the + * OMX_SetConfig command would have OMX_IndexConfigCommonInputCrop as the second parameter + * and would send a pointer to an initialized OMX_RECTTYPE structure as the + * third parameter. + * + * The enumeration entries named with the OMX_Config prefix are sent using + * the OMX_SetConfig command and the enumeration entries named with the + * OMX_PARAM_ prefix are sent using the OMX_SetParameter command. + */ +typedef enum OMX_INDEXTYPE { + + OMX_IndexComponentStartUnused = 0x01000000, + OMX_IndexParamPriorityMgmt, /**< reference: OMX_PRIORITYMGMTTYPE */ + OMX_IndexParamAudioInit, /**< reference: OMX_PORT_PARAM_TYPE */ + OMX_IndexParamImageInit, /**< reference: OMX_PORT_PARAM_TYPE */ + OMX_IndexParamVideoInit, /**< reference: OMX_PORT_PARAM_TYPE */ + OMX_IndexParamOtherInit, /**< reference: OMX_PORT_PARAM_TYPE */ + OMX_IndexParamNumAvailableStreams, /**< reference: OMX_PARAM_U32TYPE */ + OMX_IndexParamActiveStream, /**< reference: OMX_PARAM_U32TYPE */ + OMX_IndexParamSuspensionPolicy, /**< reference: OMX_PARAM_SUSPENSIONPOLICYTYPE */ + OMX_IndexParamComponentSuspended, /**< reference: OMX_PARAM_SUSPENSIONTYPE */ + OMX_IndexConfigCapturing, /**< reference: OMX_CONFIG_BOOLEANTYPE */ + OMX_IndexConfigCaptureMode, /**< reference: OMX_CONFIG_CAPTUREMODETYPE */ + OMX_IndexAutoPauseAfterCapture, /**< reference: OMX_CONFIG_BOOLEANTYPE */ + OMX_IndexParamContentURI, /**< reference: OMX_PARAM_CONTENTURITYPE */ + OMX_IndexParamCustomContentPipe, /**< reference: OMX_PARAM_CONTENTPIPETYPE */ + OMX_IndexParamDisableResourceConcealment, /**< reference: OMX_RESOURCECONCEALMENTTYPE */ + OMX_IndexConfigMetadataItemCount, /**< reference: OMX_CONFIG_METADATAITEMCOUNTTYPE */ + OMX_IndexConfigContainerNodeCount, /**< reference: OMX_CONFIG_CONTAINERNODECOUNTTYPE */ + OMX_IndexConfigMetadataItem, /**< reference: OMX_CONFIG_METADATAITEMTYPE */ + OMX_IndexConfigCounterNodeID, /**< reference: OMX_CONFIG_CONTAINERNODEIDTYPE */ + OMX_IndexParamMetadataFilterType, /**< reference: OMX_PARAM_METADATAFILTERTYPE */ + OMX_IndexParamMetadataKeyFilter, /**< reference: OMX_PARAM_METADATAFILTERTYPE */ + OMX_IndexConfigPriorityMgmt, /**< reference: OMX_PRIORITYMGMTTYPE */ + OMX_IndexParamStandardComponentRole, /**< reference: OMX_PARAM_COMPONENTROLETYPE */ + + OMX_IndexPortStartUnused = 0x02000000, + OMX_IndexParamPortDefinition, /**< reference: OMX_PARAM_PORTDEFINITIONTYPE */ + OMX_IndexParamCompBufferSupplier, /**< reference: OMX_PARAM_BUFFERSUPPLIERTYPE */ + OMX_IndexReservedStartUnused = 0x03000000, + + /* Audio parameters and configurations */ + OMX_IndexAudioStartUnused = 0x04000000, + OMX_IndexParamAudioPortFormat, /**< reference: OMX_AUDIO_PARAM_PORTFORMATTYPE */ + OMX_IndexParamAudioPcm, /**< reference: OMX_AUDIO_PARAM_PCMMODETYPE */ + OMX_IndexParamAudioAac, /**< reference: OMX_AUDIO_PARAM_AACPROFILETYPE */ + OMX_IndexParamAudioRa, /**< reference: OMX_AUDIO_PARAM_RATYPE */ + OMX_IndexParamAudioMp3, /**< reference: OMX_AUDIO_PARAM_MP3TYPE */ + OMX_IndexParamAudioAdpcm, /**< reference: OMX_AUDIO_PARAM_ADPCMTYPE */ + OMX_IndexParamAudioG723, /**< reference: OMX_AUDIO_PARAM_G723TYPE */ + OMX_IndexParamAudioG729, /**< reference: OMX_AUDIO_PARAM_G729TYPE */ + OMX_IndexParamAudioAmr, /**< reference: OMX_AUDIO_PARAM_AMRTYPE */ + OMX_IndexParamAudioWma, /**< reference: OMX_AUDIO_PARAM_WMATYPE */ + OMX_IndexParamAudioSbc, /**< reference: OMX_AUDIO_PARAM_SBCTYPE */ + OMX_IndexParamAudioMidi, /**< reference: OMX_AUDIO_PARAM_MIDITYPE */ + OMX_IndexParamAudioGsm_FR, /**< reference: OMX_AUDIO_PARAM_GSMFRTYPE */ + OMX_IndexParamAudioMidiLoadUserSound, /**< reference: OMX_AUDIO_PARAM_MIDILOADUSERSOUNDTYPE */ + OMX_IndexParamAudioG726, /**< reference: OMX_AUDIO_PARAM_G726TYPE */ + OMX_IndexParamAudioGsm_EFR, /**< reference: OMX_AUDIO_PARAM_GSMEFRTYPE */ + OMX_IndexParamAudioGsm_HR, /**< reference: OMX_AUDIO_PARAM_GSMHRTYPE */ + OMX_IndexParamAudioPdc_FR, /**< reference: OMX_AUDIO_PARAM_PDCFRTYPE */ + OMX_IndexParamAudioPdc_EFR, /**< reference: OMX_AUDIO_PARAM_PDCEFRTYPE */ + OMX_IndexParamAudioPdc_HR, /**< reference: OMX_AUDIO_PARAM_PDCHRTYPE */ + OMX_IndexParamAudioTdma_FR, /**< reference: OMX_AUDIO_PARAM_TDMAFRTYPE */ + OMX_IndexParamAudioTdma_EFR, /**< reference: OMX_AUDIO_PARAM_TDMAEFRTYPE */ + OMX_IndexParamAudioQcelp8, /**< reference: OMX_AUDIO_PARAM_QCELP8TYPE */ + OMX_IndexParamAudioQcelp13, /**< reference: OMX_AUDIO_PARAM_QCELP13TYPE */ + OMX_IndexParamAudioEvrc, /**< reference: OMX_AUDIO_PARAM_EVRCTYPE */ + OMX_IndexParamAudioSmv, /**< reference: OMX_AUDIO_PARAM_SMVTYPE */ + OMX_IndexParamAudioVorbis, /**< reference: OMX_AUDIO_PARAM_VORBISTYPE */ + + OMX_IndexConfigAudioMidiImmediateEvent, /**< reference: OMX_AUDIO_CONFIG_MIDIIMMEDIATEEVENTTYPE */ + OMX_IndexConfigAudioMidiControl, /**< reference: OMX_AUDIO_CONFIG_MIDICONTROLTYPE */ + OMX_IndexConfigAudioMidiSoundBankProgram, /**< reference: OMX_AUDIO_CONFIG_MIDISOUNDBANKPROGRAMTYPE */ + OMX_IndexConfigAudioMidiStatus, /**< reference: OMX_AUDIO_CONFIG_MIDISTATUSTYPE */ + OMX_IndexConfigAudioMidiMetaEvent, /**< reference: OMX_AUDIO_CONFIG_MIDIMETAEVENTTYPE */ + OMX_IndexConfigAudioMidiMetaEventData, /**< reference: OMX_AUDIO_CONFIG_MIDIMETAEVENTDATATYPE */ + OMX_IndexConfigAudioVolume, /**< reference: OMX_AUDIO_CONFIG_VOLUMETYPE */ + OMX_IndexConfigAudioBalance, /**< reference: OMX_AUDIO_CONFIG_BALANCETYPE */ + OMX_IndexConfigAudioChannelMute, /**< reference: OMX_AUDIO_CONFIG_CHANNELMUTETYPE */ + OMX_IndexConfigAudioMute, /**< reference: OMX_AUDIO_CONFIG_MUTETYPE */ + OMX_IndexConfigAudioLoudness, /**< reference: OMX_AUDIO_CONFIG_LOUDNESSTYPE */ + OMX_IndexConfigAudioEchoCancelation, /**< reference: OMX_AUDIO_CONFIG_ECHOCANCELATIONTYPE */ + OMX_IndexConfigAudioNoiseReduction, /**< reference: OMX_AUDIO_CONFIG_NOISEREDUCTIONTYPE */ + OMX_IndexConfigAudioBass, /**< reference: OMX_AUDIO_CONFIG_BASSTYPE */ + OMX_IndexConfigAudioTreble, /**< reference: OMX_AUDIO_CONFIG_TREBLETYPE */ + OMX_IndexConfigAudioStereoWidening, /**< reference: OMX_AUDIO_CONFIG_STEREOWIDENINGTYPE */ + OMX_IndexConfigAudioChorus, /**< reference: OMX_AUDIO_CONFIG_CHORUSTYPE */ + OMX_IndexConfigAudioEqualizer, /**< reference: OMX_AUDIO_CONFIG_EQUALIZERTYPE */ + OMX_IndexConfigAudioReverberation, /**< reference: OMX_AUDIO_CONFIG_REVERBERATIONTYPE */ + OMX_IndexConfigAudioChannelVolume, /**< reference: OMX_AUDIO_CONFIG_CHANNELVOLUMETYPE */ + + /* Image specific parameters and configurations */ + OMX_IndexImageStartUnused = 0x05000000, + OMX_IndexParamImagePortFormat, /**< reference: OMX_IMAGE_PARAM_PORTFORMATTYPE */ + OMX_IndexParamFlashControl, /**< reference: OMX_IMAGE_PARAM_FLASHCONTROLTYPE */ + OMX_IndexConfigFocusControl, /**< reference: OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE */ + OMX_IndexParamQFactor, /**< reference: OMX_IMAGE_PARAM_QFACTORTYPE */ + OMX_IndexParamQuantizationTable, /**< reference: OMX_IMAGE_PARAM_QUANTIZATIONTABLETYPE */ + OMX_IndexParamHuffmanTable, /**< reference: OMX_IMAGE_PARAM_HUFFMANTTABLETYPE */ + OMX_IndexConfigFlashControl, /**< reference: OMX_IMAGE_PARAM_FLASHCONTROLTYPE */ + + /* Video specific parameters and configurations */ + OMX_IndexVideoStartUnused = 0x06000000, + OMX_IndexParamVideoPortFormat, /**< reference: OMX_VIDEO_PARAM_PORTFORMATTYPE */ + OMX_IndexParamVideoQuantization, /**< reference: OMX_VIDEO_PARAM_QUANTIZATIONTYPE */ + OMX_IndexParamVideoFastUpdate, /**< reference: OMX_VIDEO_PARAM_VIDEOFASTUPDATETYPE */ + OMX_IndexParamVideoBitrate, /**< reference: OMX_VIDEO_PARAM_BITRATETYPE */ + OMX_IndexParamVideoMotionVector, /**< reference: OMX_VIDEO_PARAM_MOTIONVECTORTYPE */ + OMX_IndexParamVideoIntraRefresh, /**< reference: OMX_VIDEO_PARAM_INTRAREFRESHTYPE */ + OMX_IndexParamVideoErrorCorrection, /**< reference: OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE */ + OMX_IndexParamVideoVBSMC, /**< reference: OMX_VIDEO_PARAM_VBSMCTYPE */ + OMX_IndexParamVideoMpeg2, /**< reference: OMX_VIDEO_PARAM_MPEG2TYPE */ + OMX_IndexParamVideoMpeg4, /**< reference: OMX_VIDEO_PARAM_MPEG4TYPE */ + OMX_IndexParamVideoWmv, /**< reference: OMX_VIDEO_PARAM_WMVTYPE */ + OMX_IndexParamVideoRv, /**< reference: OMX_VIDEO_PARAM_RVTYPE */ + OMX_IndexParamVideoAvc, /**< reference: OMX_VIDEO_PARAM_AVCTYPE */ + OMX_IndexParamVideoH263, /**< reference: OMX_VIDEO_PARAM_H263TYPE */ + OMX_IndexParamVideoProfileLevelQuerySupported, /**< reference: OMX_VIDEO_PARAM_PROFILELEVELTYPE */ + OMX_IndexParamVideoProfileLevelCurrent, /**< reference: OMX_VIDEO_PARAM_PROFILELEVELTYPE */ + OMX_IndexConfigVideoBitrate, /**< reference: OMX_VIDEO_CONFIG_BITRATETYPE */ + OMX_IndexConfigVideoFramerate, /**< reference: OMX_CONFIG_FRAMERATETYPE */ + OMX_IndexConfigVideoIntraVOPRefresh, /**< reference: OMX_CONFIG_INTRAREFRESHVOPTYPE */ + OMX_IndexConfigVideoIntraMBRefresh, /**< reference: OMX_CONFIG_MACROBLOCKERRORMAPTYPE */ + OMX_IndexConfigVideoMBErrorReporting, /**< reference: OMX_CONFIG_MBERRORREPORTINGTYPE */ + OMX_IndexParamVideoMacroblocksPerFrame, /**< reference: OMX_PARAM_MACROBLOCKSTYPE */ + OMX_IndexConfigVideoMacroBlockErrorMap, /**< reference: OMX_CONFIG_MACROBLOCKERRORMAPTYPE */ + OMX_IndexParamVideoSliceFMO, /**< reference: OMX_VIDEO_PARAM_AVCSLICEFMO */ + OMX_IndexConfigVideoAVCIntraPeriod, /**< reference: OMX_VIDEO_CONFIG_AVCINTRAPERIOD */ + OMX_IndexConfigVideoNalSize, /**< reference: OMX_VIDEO_CONFIG_NALSIZE */ + + /* Image & Video common Configurations */ + OMX_IndexCommonStartUnused = 0x07000000, + OMX_IndexParamCommonDeblocking, /**< reference: OMX_PARAM_DEBLOCKINGTYPE */ + OMX_IndexParamCommonSensorMode, /**< reference: OMX_PARAM_SENSORMODETYPE */ + OMX_IndexParamCommonInterleave, /**< reference: OMX_PARAM_INTERLEAVETYPE */ + OMX_IndexConfigCommonColorFormatConversion, /**< reference: OMX_CONFIG_COLORCONVERSIONTYPE */ + OMX_IndexConfigCommonScale, /**< reference: OMX_CONFIG_SCALEFACTORTYPE */ + OMX_IndexConfigCommonImageFilter, /**< reference: OMX_CONFIG_IMAGEFILTERTYPE */ + OMX_IndexConfigCommonColorEnhancement, /**< reference: OMX_CONFIG_COLORENHANCEMENTTYPE */ + OMX_IndexConfigCommonColorKey, /**< reference: OMX_CONFIG_COLORKEYTYPE */ + OMX_IndexConfigCommonColorBlend, /**< reference: OMX_CONFIG_COLORBLENDTYPE */ + OMX_IndexConfigCommonFrameStabilisation,/**< reference: OMX_CONFIG_FRAMESTABTYPE */ + OMX_IndexConfigCommonRotate, /**< reference: OMX_CONFIG_ROTATIONTYPE */ + OMX_IndexConfigCommonMirror, /**< reference: OMX_CONFIG_MIRRORTYPE */ + OMX_IndexConfigCommonOutputPosition, /**< reference: OMX_CONFIG_POINTTYPE */ + OMX_IndexConfigCommonInputCrop, /**< reference: OMX_CONFIG_RECTTYPE */ + OMX_IndexConfigCommonOutputCrop, /**< reference: OMX_CONFIG_RECTTYPE */ + OMX_IndexConfigCommonDigitalZoom, /**< reference: OMX_CONFIG_SCALEFACTORTYPE */ + OMX_IndexConfigCommonOpticalZoom, /**< reference: OMX_CONFIG_SCALEFACTORTYPE*/ + OMX_IndexConfigCommonWhiteBalance, /**< reference: OMX_CONFIG_WHITEBALCONTROLTYPE */ + OMX_IndexConfigCommonExposure, /**< reference: OMX_CONFIG_EXPOSURECONTROLTYPE */ + OMX_IndexConfigCommonContrast, /**< reference: OMX_CONFIG_CONTRASTTYPE */ + OMX_IndexConfigCommonBrightness, /**< reference: OMX_CONFIG_BRIGHTNESSTYPE */ + OMX_IndexConfigCommonBacklight, /**< reference: OMX_CONFIG_BACKLIGHTTYPE */ + OMX_IndexConfigCommonGamma, /**< reference: OMX_CONFIG_GAMMATYPE */ + OMX_IndexConfigCommonSaturation, /**< reference: OMX_CONFIG_SATURATIONTYPE */ + OMX_IndexConfigCommonLightness, /**< reference: OMX_CONFIG_LIGHTNESSTYPE */ + OMX_IndexConfigCommonExclusionRect, /**< reference: OMX_CONFIG_RECTTYPE */ + OMX_IndexConfigCommonDithering, /**< reference: OMX_CONFIG_DITHERTYPE */ + OMX_IndexConfigCommonPlaneBlend, /**< reference: OMX_CONFIG_PLANEBLENDTYPE */ + OMX_IndexConfigCommonExposureValue, /**< reference: OMX_CONFIG_EXPOSUREVALUETYPE */ + OMX_IndexConfigCommonOutputSize, /**< reference: OMX_FRAMESIZETYPE */ + OMX_IndexParamCommonExtraQuantData, /**< reference: OMX_OTHER_EXTRADATATYPE */ + OMX_IndexConfigCommonFocusRegion, /**< reference: OMX_CONFIG_FOCUSREGIONTYPE */ + OMX_IndexConfigCommonFocusStatus, /**< reference: OMX_PARAM_FOCUSSTATUSTYPE */ + OMX_IndexConfigCommonTransitionEffect, /**< reference: OMX_CONFIG_TRANSITIONEFFECTTYPE */ + + /* Reserved Configuration range */ + OMX_IndexOtherStartUnused = 0x08000000, + OMX_IndexParamOtherPortFormat, /**< reference: OMX_OTHER_PARAM_PORTFORMATTYPE */ + OMX_IndexConfigOtherPower, /**< reference: OMX_OTHER_CONFIG_POWERTYPE */ + OMX_IndexConfigOtherStats, /**< reference: OMX_OTHER_CONFIG_STATSTYPE */ + + + /* Reserved Time range */ + OMX_IndexTimeStartUnused = 0x09000000, + OMX_IndexConfigTimeScale, /**< reference: OMX_TIME_CONFIG_SCALETYPE */ + OMX_IndexConfigTimeClockState, /**< reference: OMX_TIME_CONFIG_CLOCKSTATETYPE */ + OMX_IndexConfigTimeActiveRefClock, /**< reference: OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE */ + OMX_IndexConfigTimeCurrentMediaTime, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (read only) */ + OMX_IndexConfigTimeCurrentWallTime, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (read only) */ + OMX_IndexConfigTimeCurrentAudioReference, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (write only) */ + OMX_IndexConfigTimeCurrentVideoReference, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (write only) */ + OMX_IndexConfigTimeMediaTimeRequest, /**< reference: OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE (write only) */ + OMX_IndexConfigTimeClientStartTime, /** + + +/** Khronos standard extension indices. + +This enum lists the current Khronos extension indices to OpenMAX IL. +*/ +typedef enum OMX_INDEXEXTTYPE { + + /* Component parameters and configurations */ + OMX_IndexExtComponentStartUnused = OMX_IndexKhronosExtensions + 0x00100000, + OMX_IndexConfigCallbackRequest, /**< reference: OMX_CONFIG_CALLBACKREQUESTTYPE */ + + /* Port parameters and configurations */ + OMX_IndexExtPortStartUnused = OMX_IndexKhronosExtensions + 0x00200000, + + /* Audio parameters and configurations */ + OMX_IndexExtAudioStartUnused = OMX_IndexKhronosExtensions + 0x00400000, + + /* Image parameters and configurations */ + OMX_IndexExtImageStartUnused = OMX_IndexKhronosExtensions + 0x00500000, + + /* Video parameters and configurations */ + OMX_IndexExtVideoStartUnused = OMX_IndexKhronosExtensions + 0x00600000, + OMX_IndexKhronosExtParamNALStreamFormatSupported, /**< reference: OMX_NALSTREAMFORMATTYPE */ + OMX_IndexKhronosExtParamNALStreamFormat, /**< reference: OMX_NALSTREAMFORMATTYPE */ + OMX_IndexKhronosExtParamNALStreamFormatSelect, /**< reference: OMX_NALSTREAMFORMATTYPE */ + + /* Image & Video common configurations */ + OMX_IndexExtCommonStartUnused = OMX_IndexKhronosExtensions + 0x00700000, + + /* Other configurations */ + OMX_IndexExtOtherStartUnused = OMX_IndexKhronosExtensions + 0x00800000, + + /* Time configurations */ + OMX_IndexExtTimeStartUnused = OMX_IndexKhronosExtensions + 0x00900000, + + OMX_IndexExtMax = 0x7FFFFFFF +} OMX_INDEXEXTTYPE; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OMX_IndexExt_h */ +/* File EOF */ diff --git a/mm-core/inc/OMX_Other.h b/mm-core/inc/OMX_Other.h new file mode 100755 index 0000000..caf7f38 --- /dev/null +++ b/mm-core/inc/OMX_Other.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** @file OMX_Other.h - OpenMax IL version 1.1.2 + * The structures needed by Other components to exchange + * parameters and configuration data with the components. + */ + +#ifndef OMX_Other_h +#define OMX_Other_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include + + +/** + * Enumeration of possible data types which match to multiple domains or no + * domain at all. For types which are vendor specific, a value above + * OMX_OTHER_VENDORTSTART should be used. + */ +typedef enum OMX_OTHER_FORMATTYPE { + OMX_OTHER_FormatTime = 0, /**< Transmission of various timestamps, elapsed time, + time deltas, etc */ + OMX_OTHER_FormatPower, /**< Perhaps used for enabling/disabling power + management, setting clocks? */ + OMX_OTHER_FormatStats, /**< Could be things such as frame rate, frames + dropped, etc */ + OMX_OTHER_FormatBinary, /**< Arbitrary binary data */ + OMX_OTHER_FormatVendorReserved = 1000, /**< Starting value for vendor specific + formats */ + + OMX_OTHER_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_OTHER_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_OTHER_FormatMax = 0x7FFFFFFF +} OMX_OTHER_FORMATTYPE; + +/** + * Enumeration of seek modes. + */ +typedef enum OMX_TIME_SEEKMODETYPE { + OMX_TIME_SeekModeFast = 0, /**< Prefer seeking to an approximation + * of the requested seek position over + * the actual seek position if it + * results in a faster seek. */ + OMX_TIME_SeekModeAccurate, /**< Prefer seeking to the actual seek + * position over an approximation + * of the requested seek position even + * if it results in a slower seek. */ + OMX_TIME_SeekModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_TIME_SeekModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_TIME_SeekModeMax = 0x7FFFFFFF +} OMX_TIME_SEEKMODETYPE; + +/* Structure representing the seekmode of the component */ +typedef struct OMX_TIME_CONFIG_SEEKMODETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_TIME_SEEKMODETYPE eType; /**< The seek mode */ +} OMX_TIME_CONFIG_SEEKMODETYPE; + +/** Structure representing a time stamp used with the following configs + * on the Clock Component (CC): + * + * OMX_IndexConfigTimeCurrentWallTime: query of the CC’s current wall + * time + * OMX_IndexConfigTimeCurrentMediaTime: query of the CC’s current media + * time + * OMX_IndexConfigTimeCurrentAudioReference and + * OMX_IndexConfigTimeCurrentVideoReference: audio/video reference + * clock sending SC its reference time + * OMX_IndexConfigTimeClientStartTime: a Clock Component client sends + * this structure to the Clock Component via a SetConfig on its + * client port when it receives a buffer with + * OMX_BUFFERFLAG_STARTTIME set. It must use the timestamp + * specified by that buffer for nStartTimestamp. + * + * It’s also used with the following config on components in general: + * + * OMX_IndexConfigTimePosition: IL client querying component position + * (GetConfig) or commanding a component to seek to the given location + * (SetConfig) + */ +typedef struct OMX_TIME_CONFIG_TIMESTAMPTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version + * information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_TICKS nTimestamp; /**< timestamp .*/ +} OMX_TIME_CONFIG_TIMESTAMPTYPE; + +/** Enumeration of possible reference clocks to the media time. */ +typedef enum OMX_TIME_UPDATETYPE { + OMX_TIME_UpdateRequestFulfillment, /**< Update is the fulfillment of a media time request. */ + OMX_TIME_UpdateScaleChanged, /**< Update was generated because the scale chagned. */ + OMX_TIME_UpdateClockStateChanged, /**< Update was generated because the clock state changed. */ + OMX_TIME_UpdateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_TIME_UpdateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_TIME_UpdateMax = 0x7FFFFFFF +} OMX_TIME_UPDATETYPE; + +/** Enumeration of possible reference clocks to the media time. */ +typedef enum OMX_TIME_REFCLOCKTYPE { + OMX_TIME_RefClockNone, /**< Use no references. */ + OMX_TIME_RefClockAudio, /**< Use references sent through OMX_IndexConfigTimeCurrentAudioReference */ + OMX_TIME_RefClockVideo, /**< Use references sent through OMX_IndexConfigTimeCurrentVideoReference */ + OMX_TIME_RefClockKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_TIME_RefClockVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_TIME_RefClockMax = 0x7FFFFFFF +} OMX_TIME_REFCLOCKTYPE; + +/** Enumeration of clock states. */ +typedef enum OMX_TIME_CLOCKSTATE { + OMX_TIME_ClockStateRunning, /**< Clock running. */ + OMX_TIME_ClockStateWaitingForStartTime, /**< Clock waiting until the + * prescribed clients emit their + * start time. */ + OMX_TIME_ClockStateStopped, /**< Clock stopped. */ + OMX_TIME_ClockStateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_TIME_ClockStateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_TIME_ClockStateMax = 0x7FFFFFFF +} OMX_TIME_CLOCKSTATE; + +/** Structure representing a media time request to the clock component. + * + * A client component sends this structure to the Clock Component via a SetConfig + * on its client port to specify a media timestamp the Clock Component + * should emit. The Clock Component should fulfill the request by sending a + * OMX_TIME_MEDIATIMETYPE when its media clock matches the requested + * timestamp. + * + * The client may require a media time request be fulfilled slightly + * earlier than the media time specified. In this case the client specifies + * an offset which is equal to the difference between wall time corresponding + * to the requested media time and the wall time when it will be + * fulfilled. + * + * A client component may uses these requests and the OMX_TIME_MEDIATIMETYPE to + * time events according to timestamps. If a client must perform an operation O at + * a time T (e.g. deliver a video frame at its corresponding timestamp), it makes a + * media time request at T (perhaps specifying an offset to ensure the request fulfillment + * is a little early). When the clock component passes the resulting OMX_TIME_MEDIATIMETYPE + * structure back to the client component, the client may perform operation O (perhaps having + * to wait a slight amount more time itself as specified by the return values). + */ + +typedef struct OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_PTR pClientPrivate; /**< Client private data to disabiguate this media time + * from others (e.g. the number of the frame to deliver). + * Duplicated in the media time structure that fulfills + * this request. A value of zero is reserved for time scale + * updates. */ + OMX_TICKS nMediaTimestamp; /**< Media timestamp requested.*/ + OMX_TICKS nOffset; /**< Amount of wall clock time by which this + * request should be fulfilled early */ +} OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE; + +/**< Structure sent from the clock component client either when fulfilling + * a media time request or when the time scale has changed. + * + * In the former case the Clock Component fills this structure and times its emission + * to a client component (via the client port) according to the corresponding media + * time request sent by the client. The Clock Component should time the emission to occur + * when the requested timestamp matches the Clock Component's media time but also the + * prescribed offset early. + * + * Upon scale changes the clock component clears the nClientPrivate data, sends the current + * media time and sets the nScale to the new scale via the client port. It emits a + * OMX_TIME_MEDIATIMETYPE to all clients independent of any requests. This allows clients to + * alter processing to accomodate scaling. For instance a video component might skip inter-frames + * in the case of extreme fastforward. Likewise an audio component might add or remove samples + * from an audio frame to scale audio data. + * + * It is expected that some clock components may not be able to fulfill requests + * at exactly the prescribed time. This is acceptable so long as the request is + * fulfilled at least as early as described and not later. This structure provides + * fields the client may use to wait for the remaining time. + * + * The client may use either the nOffset or nWallTimeAtMedia fields to determine the + * wall time until the nMediaTimestamp actually occurs. In the latter case the + * client can get a more accurate value for offset by getting the current wall + * from the cloc component and subtracting it from nWallTimeAtMedia. + */ + +typedef struct OMX_TIME_MEDIATIMETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nClientPrivate; /**< Client private data to disabiguate this media time + * from others. Copied from the media time request. + * A value of zero is reserved for time scale updates. */ + OMX_TIME_UPDATETYPE eUpdateType; /**< Reason for the update */ + OMX_TICKS nMediaTimestamp; /**< Media time requested. If no media time was + * requested then this is the current media time. */ + OMX_TICKS nOffset; /**< Amount of wall clock time by which this + * request was actually fulfilled early */ + + OMX_TICKS nWallTimeAtMediaTime; /**< Wall time corresponding to nMediaTimeStamp. + * A client may compare this value to current + * media time obtained from the Clock Component to determine + * the wall time until the media timestamp is really + * current. */ + OMX_S32 xScale; /**< Current media time scale in Q16 format. */ + OMX_TIME_CLOCKSTATE eState; /* Seeking Change. Added 7/12.*/ + /**< State of the media time. */ +} OMX_TIME_MEDIATIMETYPE; + +/** Structure representing the current media time scale factor. Applicable only to clock + * component, other components see scale changes via OMX_TIME_MEDIATIMETYPE buffers sent via + * the clock component client ports. Upon recieving this config the clock component changes + * the rate by which the media time increases or decreases effectively implementing trick modes. + */ +typedef struct OMX_TIME_CONFIG_SCALETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_S32 xScale; /**< This is a value in Q16 format which is used for + * scaling the media time */ +} OMX_TIME_CONFIG_SCALETYPE; + +/** Bits used to identify a clock port. Used in OMX_TIME_CONFIG_CLOCKSTATETYPE’s nWaitMask field */ +#define OMX_CLOCKPORT0 0x00000001 +#define OMX_CLOCKPORT1 0x00000002 +#define OMX_CLOCKPORT2 0x00000004 +#define OMX_CLOCKPORT3 0x00000008 +#define OMX_CLOCKPORT4 0x00000010 +#define OMX_CLOCKPORT5 0x00000020 +#define OMX_CLOCKPORT6 0x00000040 +#define OMX_CLOCKPORT7 0x00000080 + +/** Structure representing the current mode of the media clock. + * IL Client uses this config to change or query the mode of the + * media clock of the clock component. Applicable only to clock + * component. + * + * On a SetConfig if eState is OMX_TIME_ClockStateRunning media time + * starts immediately at the prescribed start time. If + * OMX_TIME_ClockStateWaitingForStartTime the Clock Component ignores + * the given nStartTime and waits for all clients specified in the + * nWaitMask to send starttimes (via + * OMX_IndexConfigTimeClientStartTime). The Clock Component then starts + * the media clock using the earliest start time supplied. */ +typedef struct OMX_TIME_CONFIG_CLOCKSTATETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version + * information */ + OMX_TIME_CLOCKSTATE eState; /**< State of the media time. */ + OMX_TICKS nStartTime; /**< Start time of the media time. */ + OMX_TICKS nOffset; /**< Time to offset the media time by + * (e.g. preroll). Media time will be + * reported to be nOffset ticks earlier. + */ + OMX_U32 nWaitMask; /**< Mask of OMX_CLOCKPORT values. */ +} OMX_TIME_CONFIG_CLOCKSTATETYPE; + +/** Structure representing the reference clock currently being used to + * compute media time. IL client uses this config to change or query the + * clock component's active reference clock */ +typedef struct OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_TIME_REFCLOCKTYPE eClock; /**< Reference clock used to compute media time */ +} OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE; + +/** Descriptor for setting specifics of power type. + * Note: this structure is listed for backwards compatibility. */ +typedef struct OMX_OTHER_CONFIG_POWERTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bEnablePM; /**< Flag to enable Power Management */ +} OMX_OTHER_CONFIG_POWERTYPE; + + +/** Descriptor for setting specifics of stats type. + * Note: this structure is listed for backwards compatibility. */ +typedef struct OMX_OTHER_CONFIG_STATSTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + /* what goes here */ +} OMX_OTHER_CONFIG_STATSTYPE; + + +/** + * The PortDefinition structure is used to define all of the parameters + * necessary for the compliant component to setup an input or an output other + * path. + */ +typedef struct OMX_OTHER_PORTDEFINITIONTYPE { + OMX_OTHER_FORMATTYPE eFormat; /**< Type of data expected for this channel */ +} OMX_OTHER_PORTDEFINITIONTYPE; + +/** Port format parameter. This structure is used to enumerate + * the various data input/output format supported by the port. + */ +typedef struct OMX_OTHER_PARAM_PORTFORMATTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Indicates which port to set */ + OMX_U32 nIndex; /**< Indicates the enumeration index for the format from 0x0 to N-1 */ + OMX_OTHER_FORMATTYPE eFormat; /**< Type of data expected for this channel */ +} OMX_OTHER_PARAM_PORTFORMATTYPE; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ diff --git a/mm-core/inc/OMX_QCOMExtns.h b/mm-core/inc/OMX_QCOMExtns.h new file mode 100644 index 0000000..134b82e --- /dev/null +++ b/mm-core/inc/OMX_QCOMExtns.h @@ -0,0 +1,881 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef __OMX_QCOM_EXTENSIONS_H__ +#define __OMX_QCOM_EXTENSIONS_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*============================================================================ +*//** @file OMX_QCOMExtns.h + This header contains constants and type definitions that specify the + extensions added to the OpenMAX Vendor specific APIs. + +*//*========================================================================*/ + + +/////////////////////////////////////////////////////////////////////////////// +// Include Files +/////////////////////////////////////////////////////////////////////////////// +#include "OMX_Core.h" +#include "OMX_Video.h" + +/** + * This extension is used to register mapping of a virtual + * address to a physical address. This extension is a parameter + * which can be set using the OMX_SetParameter macro. The data + * pointer corresponding to this extension is + * OMX_QCOM_MemMapEntry. This parameter is a 'write only' + * parameter (Current value cannot be queried using + * OMX_GetParameter macro). + */ +#define OMX_QCOM_EXTN_REGISTER_MMAP "OMX.QCOM.index.param.register_mmap" + +/** + * This structure describes the data pointer corresponding to + * the OMX_QCOM_MMAP_REGISTER_EXTN extension. This parameter + * must be set only 'after' populating a port with a buffer + * using OMX_UseBuffer, wherein the data pointer of the buffer + * corresponds to the virtual address as specified in this + * structure. + */ +struct OMX_QCOM_PARAM_MEMMAPENTRYTYPE +{ + OMX_U32 nSize; /** Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port number the structure applies to */ + + /** + * The virtual address of memory block + */ + OMX_U64 nVirtualAddress; + + /** + * The physical address corresponding to the virtual address. The physical + * address is contiguous for the entire valid range of the virtual + * address. + */ + OMX_U64 nPhysicalAddress; +}; + +#define QOMX_VIDEO_IntraRefreshRandom (OMX_VIDEO_IntraRefreshVendorStartUnused + 0) + +#define QOMX_VIDEO_BUFFERFLAG_BFRAME 0x00100000 + +#define QOMX_VIDEO_BUFFERFLAG_EOSEQ 0x00200000 + +#define OMX_QCOM_PORTDEFN_EXTN "OMX.QCOM.index.param.portdefn" +/* Allowed APIs on the above Index: OMX_GetParameter() and OMX_SetParameter() */ + +typedef enum OMX_QCOMMemoryRegion +{ + OMX_QCOM_MemRegionInvalid, + OMX_QCOM_MemRegionEBI1, + OMX_QCOM_MemRegionSMI, + OMX_QCOM_MemRegionMax = 0X7FFFFFFF +} OMX_QCOMMemoryRegion; + +typedef enum OMX_QCOMCacheAttr +{ + OMX_QCOM_CacheAttrNone, + OMX_QCOM_CacheAttrWriteBack, + OMX_QCOM_CacheAttrWriteThrough, + OMX_QCOM_CacheAttrMAX = 0X7FFFFFFF +} OMX_QCOMCacheAttr; + +typedef struct OMX_QCOMRectangle +{ + OMX_S32 x; + OMX_S32 y; + OMX_S32 dx; + OMX_S32 dy; +} OMX_QCOMRectangle; + +/** OMX_QCOMFramePackingFormat + * Input or output buffer format + */ +typedef enum OMX_QCOMFramePackingFormat +{ + /* 0 - unspecified + */ + OMX_QCOM_FramePacking_Unspecified, + + /* 1 - Partial frames may be present OMX IL 1.1.1 Figure 2-10: + * Case 1??Each Buffer Filled In Whole or In Part + */ + OMX_QCOM_FramePacking_Arbitrary, + + /* 2 - Multiple complete frames per buffer (integer number) + * OMX IL 1.1.1 Figure 2-11: Case 2—Each Buffer Filled with + * Only Complete Frames of Data + */ + OMX_QCOM_FramePacking_CompleteFrames, + + /* 3 - Only one complete frame per buffer, no partial frame + * OMX IL 1.1.1 Figure 2-12: Case 3—Each Buffer Filled with + * Only One Frame of Compressed Data. Usually at least one + * complete unit of data will be delivered in a buffer for + * uncompressed data formats. + */ + OMX_QCOM_FramePacking_OnlyOneCompleteFrame, + + /* 4 - Only one complete subframe per buffer, no partial subframe + * Example: In H264, one complete NAL per buffer, where one frame + * can contatin multiple NAL + */ + OMX_QCOM_FramePacking_OnlyOneCompleteSubFrame, + + OMX_QCOM_FramePacking_MAX = 0X7FFFFFFF +} OMX_QCOMFramePackingFormat; + +typedef struct OMX_QCOM_PARAM_PORTDEFINITIONTYPE { + OMX_U32 nSize; /** Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion;/** OMX specification version information */ + OMX_U32 nPortIndex; /** Portindex which is extended by this structure */ + + /** Platform specific memory region EBI1, SMI, etc.,*/ + OMX_QCOMMemoryRegion nMemRegion; + + OMX_QCOMCacheAttr nCacheAttr; /** Cache attributes */ + + /** Input or output buffer format */ + OMX_U32 nFramePackingFormat; + +} OMX_QCOM_PARAM_PORTDEFINITIONTYPE; + +#define OMX_QCOM_PLATFORMPVT_EXTN "OMX.QCOM.index.param.platformprivate" +/** Allowed APIs on the above Index: OMX_SetParameter() */ + +typedef enum OMX_QCOM_PLATFORM_PRIVATE_ENTRY_TYPE +{ + /** Enum for PMEM information */ + OMX_QCOM_PLATFORM_PRIVATE_PMEM = 0x1 +} OMX_QCOM_PLATFORM_PRIVATE_ENTRY_TYPE; + +/** IL client will set the following structure. A failure + * code will be returned if component does not support the + * value provided for 'type'. + */ +struct OMX_QCOM_PLATFORMPRIVATE_EXTN +{ + OMX_U32 nSize; /** Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /** OMX spec version information */ + OMX_U32 nPortIndex; /** Port number on which usebuffer extn is applied */ + + /** Type of extensions should match an entry from + OMX_QCOM_PLATFORM_PRIVATE_ENTRY_TYPE + */ + OMX_QCOM_PLATFORM_PRIVATE_ENTRY_TYPE type; +}; + +typedef struct OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO +{ + /** pmem file descriptor */ + OMX_U32 pmem_fd; + /** Offset from pmem device base address */ + OMX_U32 offset; +}OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO; + +typedef struct OMX_QCOM_PLATFORM_PRIVATE_ENTRY +{ + /** Entry type */ + OMX_QCOM_PLATFORM_PRIVATE_ENTRY_TYPE type; + + /** Pointer to platform specific entry */ + void* entry; +}OMX_QCOM_PLATFORM_PRIVATE_ENTRY; + +typedef struct OMX_QCOM_PLATFORM_PRIVATE_LIST +{ + /** Number of entries */ + OMX_U32 nEntries; + + /** Pointer to array of platform specific entries * + * Contiguous block of OMX_QCOM_PLATFORM_PRIVATE_ENTRY element + */ + OMX_QCOM_PLATFORM_PRIVATE_ENTRY* entryList; +}OMX_QCOM_PLATFORM_PRIVATE_LIST; + +#define OMX_QCOM_FRAME_PACKING_FORMAT "OMX.QCOM.index.param.framepackfmt" +/* Allowed API call: OMX_GetParameter() */ +/* IL client can use this index to rerieve the list of frame formats * + * supported by the component */ + +typedef struct OMX_QCOM_FRAME_PACKINGFORMAT_TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nIndex; + OMX_QCOMFramePackingFormat eframePackingFormat; +} OMX_QCOM_FRAME_PACKINGFORMAT_TYPE; + + +/** + * Following is the enum for color formats supported on Qualcomm + * MSMs YVU420SemiPlanar color format is not defined in OpenMAX + * 1.1.1 and prior versions of OpenMAX specification. + */ + +enum OMX_QCOM_COLOR_FORMATTYPE +{ + +/** YVU420SemiPlanar: YVU planar format, organized with a first + * plane containing Y pixels, and a second plane containing + * interleaved V and U pixels. V and U pixels are sub-sampled + * by a factor of two both horizontally and vertically. + */ + QOMX_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00, + QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka, + QOMX_COLOR_FormatYUV420PackedSemiPlanar16m2ka, + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka, + QOMX_COLOR_FormatAndroidOpaque = (OMX_COLOR_FORMATTYPE) OMX_COLOR_FormatVendorStartUnused + 0x789, +}; + +enum OMX_QCOM_VIDEO_CODINGTYPE +{ +/** Codecs support by qualcomm which are not listed in OMX 1.1.x + * spec + * */ + OMX_QCOM_VIDEO_CodingVC1 = 0x7FA30C00 , + OMX_QCOM_VIDEO_CodingWMV9 = 0x7FA30C01, + QOMX_VIDEO_CodingDivx = 0x7FA30C02, /**< Value when coding is Divx */ + QOMX_VIDEO_CodingSpark = 0x7FA30C03, /**< Value when coding is Sorenson Spark */ + QOMX_VIDEO_CodingVp = 0x7FA30C04, + QOMX_VIDEO_CodingVp8 = 0x7FA30C05, + QOMX_VIDEO_CodingHevc = 0x7FA30C06 +}; + +enum OMX_QCOM_EXTN_INDEXTYPE +{ + /** Qcom proprietary extension index list */ + + /* "OMX.QCOM.index.param.register_mmap" */ + OMX_QcomIndexRegmmap = 0x7F000000, + + /* "OMX.QCOM.index.param.platformprivate" */ + OMX_QcomIndexPlatformPvt = 0x7F000001, + + /* "OMX.QCOM.index.param.portdefn" */ + OMX_QcomIndexPortDefn = 0x7F000002, + + /* "OMX.QCOM.index.param.framepackingformat" */ + OMX_QcomIndexPortFramePackFmt = 0x7F000003, + + /*"OMX.QCOM.index.param.Interlaced */ + OMX_QcomIndexParamInterlaced = 0x7F000004, + + /*"OMX.QCOM.index.config.interlaceformat */ + OMX_QcomIndexConfigInterlaced = 0x7F000005, + + /*"OMX.QCOM.index.param.syntaxhdr" */ + QOMX_IndexParamVideoSyntaxHdr = 0x7F000006, + + /*"OMX.QCOM.index.config.intraperiod" */ + QOMX_IndexConfigVideoIntraperiod = 0x7F000007, + + /*"OMX.QCOM.index.config.randomIntrarefresh" */ + QOMX_IndexConfigVideoIntraRefresh = 0x7F000008, + + /*"OMX.QCOM.index.config.video.TemporalSpatialTradeOff" */ + QOMX_IndexConfigVideoTemporalSpatialTradeOff = 0x7F000009, + + /*"OMX.QCOM.index.param.video.EncoderMode" */ + QOMX_IndexParamVideoEncoderMode = 0x7F00000A, + + /*"OMX.QCOM.index.param.Divxtype */ + OMX_QcomIndexParamVideoDivx = 0x7F00000B, + + /*"OMX.QCOM.index.param.Sparktype */ + OMX_QcomIndexParamVideoSpark = 0x7F00000C, + + /*"OMX.QCOM.index.param.Vptype */ + OMX_QcomIndexParamVideoVp = 0x7F00000D, + + OMX_QcomIndexQueryNumberOfVideoDecInstance = 0x7F00000E, + + OMX_QcomIndexParamVideoSyncFrameDecodingMode = 0x7F00000F, + + OMX_QcomIndexParamVideoDecoderPictureOrder = 0x7F000010, + + OMX_QcomIndexConfigVideoFramePackingArrangement = 0x7F000011, + + OMX_QcomIndexParamConcealMBMapExtraData = 0x7F000012, + + OMX_QcomIndexParamFrameInfoExtraData = 0x7F000013, + + OMX_QcomIndexParamInterlaceExtraData = 0x7F000014, + + OMX_QcomIndexParamH264TimeInfo = 0x7F000015, + + OMX_QcomIndexParamIndexExtraDataType = 0x7F000016, + + OMX_GoogleAndroidIndexEnableAndroidNativeBuffers = 0x7F000017, + + OMX_GoogleAndroidIndexUseAndroidNativeBuffer = 0x7F000018, + + OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage = 0x7F000019, + + /*"OMX.QCOM.index.config.video.QPRange" */ + OMX_QcomIndexConfigVideoQPRange = 0x7F00001A, + + /*"OMX.QCOM.index.param.EnableTimeStampReoder"*/ + OMX_QcomIndexParamEnableTimeStampReorder = 0x7F00001B, + + /*"OMX.google.android.index.storeMetaDataInBuffers"*/ + OMX_QcomIndexParamVideoEncodeMetaBufferMode = 0x7F00001C, + + /*"OMX.google.android.index.useAndroidNativeBuffer2"*/ + OMX_GoogleAndroidIndexUseAndroidNativeBuffer2 = 0x7F00001D, + + /*"OMX.QCOM.index.param.VideoMaxAllowedBitrateCheck"*/ + OMX_QcomIndexParamVideoMaxAllowedBitrateCheck = 0x7F00001E, + + OMX_QcomIndexEnableSliceDeliveryMode = 0x7F00001F, + + OMX_QcomIndexEnableExtnUserData = 0x7F000020, + + /*"OMX.QCOM.index.param.video.EnableSmoothStreaming"*/ + OMX_QcomIndexParamEnableSmoothStreaming = 0x7F000021, +}; + +/** + * Extension index parameter. This structure is used to enable + * vendor specific extension on input/output port and + * to pass the required flags and data, if any. + * The format of flags and data being passed is known to + * the client and component apriori. + * + * STRUCT MEMBERS: + * nSize : Size of Structure plus pData size + * nVersion : OMX specification version information + * nPortIndex : Indicates which port to set + * bEnable : Extension index enable (1) or disable (0) + * nFlags : Extension index flags, if any + * nDataSize : Size of the extension index data to follow + * pData : Extension index data, if present. + */ +typedef struct QOMX_EXTNINDEX_PARAMTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnable; + OMX_U32 nFlags; + OMX_U32 nDataSize; + OMX_PTR pData; +} QOMX_EXTNINDEX_PARAMTYPE; + +/** + * Enumeration used to define the video encoder modes + * + * ENUMS: + * EncoderModeDefault : Default video recording mode. + * All encoder settings made through + * OMX_SetParameter/OMX_SetConfig are applied. No + * parameter is overridden. + * EncoderModeMMS : Video recording mode for MMS (Multimedia Messaging + * Service). This mode is similar to EncoderModeDefault + * except that here the Rate control mode is overridden + * internally and set as a variant of variable bitrate with + * variable frame rate. After this mode is set if the IL + * client tries to set OMX_VIDEO_CONTROLRATETYPE via + * OMX_IndexParamVideoBitrate that would be rejected. For + * this, client should set mode back to EncoderModeDefault + * first and then change OMX_VIDEO_CONTROLRATETYPE. + */ +typedef enum QOMX_VIDEO_ENCODERMODETYPE +{ + QOMX_VIDEO_EncoderModeDefault = 0x00, + QOMX_VIDEO_EncoderModeMMS = 0x01, + QOMX_VIDEO_EncoderModeMax = 0x7FFFFFFF +} QOMX_VIDEO_ENCODERMODETYPE; + +/** + * This structure is used to set the video encoder mode. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * nMode : defines the video encoder mode + */ +typedef struct QOMX_VIDEO_PARAM_ENCODERMODETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_VIDEO_ENCODERMODETYPE nMode; +} QOMX_VIDEO_PARAM_ENCODERMODETYPE; + +/** + * This structure describes the parameters corresponding to the + * QOMX_VIDEO_SYNTAXHDRTYPE extension. This parameter can be queried + * during the loaded state. + */ + +typedef struct QOMX_VIDEO_SYNTAXHDRTYPE +{ + OMX_U32 nSize; /** Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion;/** OMX specification version information */ + OMX_U32 nPortIndex; /** Portindex which is extended by this structure */ + OMX_U32 nBytes; /** The number of bytes filled in to the buffer */ + OMX_U8 data[1]; /** Buffer to store the header information */ +} QOMX_VIDEO_SYNTAXHDRTYPE; + +/** + * This structure describes the parameters corresponding to the + * QOMX_VIDEO_TEMPORALSPATIALTYPE extension. This parameter can be set + * dynamically during any state except the state invalid. This is primarily + * used for setting MaxQP from the application. This is set on the out port. + */ + +typedef struct QOMX_VIDEO_TEMPORALSPATIALTYPE +{ + OMX_U32 nSize; /** Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion;/** OMX specification version information */ + OMX_U32 nPortIndex; /** Portindex which is extended by this structure */ + OMX_U32 nTSFactor; /** Temoral spatial tradeoff factor value in 0-100 */ +} QOMX_VIDEO_TEMPORALSPATIALTYPE; + +/** + * This structure describes the parameters corresponding to the + * OMX_QCOM_VIDEO_CONFIG_INTRAPERIODTYPE extension. This parameter can be set + * dynamically during any state except the state invalid. This is set on the out port. + */ + +typedef struct QOMX_VIDEO_INTRAPERIODTYPE +{ + OMX_U32 nSize; /** Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion;/** OMX specification version information */ + OMX_U32 nPortIndex; /** Portindex which is extended by this structure */ + OMX_U32 nIDRPeriod; /** This specifies coding a frame as IDR after every nPFrames + of intra frames. If this parameter is set to 0, only the + first frame of the encode session is an IDR frame. This + field is ignored for non-AVC codecs and is used only for + codecs that support IDR Period */ + OMX_U32 nPFrames; /** The number of "P" frames between two "I" frames */ + OMX_U32 nBFrames; /** The number of "B" frames between two "I" frames */ +} QOMX_VIDEO_INTRAPERIODTYPE; + +/** + * This structure describes the parameters corresponding to the + * OMX_QCOM_VIDEO_CONFIG_ULBUFFEROCCUPANCYTYPE extension. This parameter can be set + * dynamically during any state except the state invalid. This is used for the buffer negotiation + * with other clients. This is set on the out port. + */ +typedef struct OMX_QCOM_VIDEO_CONFIG_ULBUFFEROCCUPANCYTYPE +{ + OMX_U32 nSize; /** Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /** OMX specification version information */ + OMX_U32 nPortIndex; /** Portindex which is extended by this structure */ + OMX_U32 nBufferOccupancy; /** The number of bytes to be set for the buffer occupancy */ +} OMX_QCOM_VIDEO_CONFIG_ULBUFFEROCCUPANCYTYPE; + +/** + * This structure describes the parameters corresponding to the + * OMX_QCOM_VIDEO_CONFIG_RANDOMINTRAREFRESHTYPE extension. This parameter can be set + * dynamically during any state except the state invalid. This is primarily used for the dynamic/random + * intrarefresh. This is set on the out port. + */ +typedef struct OMX_QCOM_VIDEO_CONFIG_RANDOMINTRAREFRESHTYPE +{ + OMX_U32 nSize; /** Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion;/** OMX specification version information */ + OMX_U32 nPortIndex; /** Portindex which is extended by this structure */ + OMX_U32 nRirMBs; /** The number of MBs to be set for intrarefresh */ +} OMX_QCOM_VIDEO_CONFIG_RANDOMINTRAREFRESHTYPE; + + +/** + * This structure describes the parameters corresponding to the + * OMX_QCOM_VIDEO_CONFIG_QPRANGE extension. This parameter can be set + * dynamically during any state except the state invalid. This is primarily + * used for the min/max QP to be set from the application. This + * is set on the out port. + */ +typedef struct OMX_QCOM_VIDEO_CONFIG_QPRANGE +{ + OMX_U32 nSize; /** Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion;/** OMX specification version information */ + OMX_U32 nPortIndex; /** Portindex which is extended by this structure */ + OMX_U32 nMinQP; /** The number for minimum quantization parameter */ + OMX_U32 nMaxQP; /** The number for maximum quantization parameter */ +} OMX_QCOM_VIDEO_CONFIG_QPRANGE; + + +typedef struct OMX_VENDOR_EXTRADATATYPE { + OMX_U32 nPortIndex; + OMX_U32 nDataSize; + OMX_U8 *pData; // cdata (codec_data/extradata) +} OMX_VENDOR_EXTRADATATYPE; + +typedef enum OMX_INDEXVENDORTYPE { + OMX_IndexVendorFileReadInputFilename = 0xFF000001, + OMX_IndexVendorParser3gpInputFilename = 0xFF000002, + OMX_IndexVendorVideoExtraData = 0xFF000003, + OMX_IndexVendorAudioExtraData = 0xFF000004 +} OMX_INDEXVENDORTYPE; + +typedef enum OMX_QCOM_VC1RESOLUTIONTYPE +{ + OMX_QCOM_VC1_PICTURE_RES_1x1, + OMX_QCOM_VC1_PICTURE_RES_2x1, + OMX_QCOM_VC1_PICTURE_RES_1x2, + OMX_QCOM_VC1_PICTURE_RES_2x2 +} OMX_QCOM_VC1RESOLUTIONTYPE; + +typedef enum OMX_QCOM_INTERLACETYPE +{ + OMX_QCOM_InterlaceFrameProgressive, + OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst, + OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst, + OMX_QCOM_InterlaceFrameTopFieldFirst, + OMX_QCOM_InterlaceFrameBottomFieldFirst, + OMX_QCOM_InterlaceFieldTop, + OMX_QCOM_InterlaceFieldBottom +}OMX_QCOM_INTERLACETYPE; + +typedef struct OMX_QCOM_PARAM_VIDEO_INTERLACETYPE +{ + OMX_U32 nSize; /** Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion;/** OMX specification version information */ + OMX_U32 nPortIndex; /** Portindex which is extended by this structure */ + OMX_BOOL bInterlace; /** Interlace content **/ +}OMX_QCOM_PARAM_VIDEO_INTERLACETYPE; + +typedef struct OMX_QCOM_CONFIG_INTERLACETYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nIndex; + OMX_QCOM_INTERLACETYPE eInterlaceType; +}OMX_QCOM_CONFIG_INTERLACETYPE; + +#define MAX_PAN_SCAN_WINDOWS 4 + +typedef struct OMX_QCOM_PANSCAN +{ + OMX_U32 numWindows; + OMX_QCOMRectangle window[MAX_PAN_SCAN_WINDOWS]; +} OMX_QCOM_PANSCAN; + +typedef struct OMX_QCOM_ASPECT_RATIO +{ + OMX_U32 aspectRatioX; + OMX_U32 aspectRatioY; +} OMX_QCOM_ASPECT_RATIO; + +typedef struct OMX_QCOM_FRAME_PACK_ARRANGEMENT +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 id; + OMX_U32 cancel_flag; + OMX_U32 type; + OMX_U32 quincunx_sampling_flag; + OMX_U32 content_interpretation_type; + OMX_U32 spatial_flipping_flag; + OMX_U32 frame0_flipped_flag; + OMX_U32 field_views_flag; + OMX_U32 current_frame_is_frame0_flag; + OMX_U32 frame0_self_contained_flag; + OMX_U32 frame1_self_contained_flag; + OMX_U32 frame0_grid_position_x; + OMX_U32 frame0_grid_position_y; + OMX_U32 frame1_grid_position_x; + OMX_U32 frame1_grid_position_y; + OMX_U32 reserved_byte; + OMX_U32 repetition_period; + OMX_U32 extension_flag; +} OMX_QCOM_FRAME_PACK_ARRANGEMENT; + +typedef struct OMX_QCOM_EXTRADATA_FRAMEINFO +{ + // common frame meta data. interlace related info removed + OMX_VIDEO_PICTURETYPE ePicType; + OMX_QCOM_INTERLACETYPE interlaceType; + OMX_QCOM_PANSCAN panScan; + OMX_QCOM_ASPECT_RATIO aspectRatio; + OMX_U32 nConcealedMacroblocks; + OMX_U32 nFrameRate; +} OMX_QCOM_EXTRADATA_FRAMEINFO; + +typedef struct OMX_QCOM_EXTRADATA_FRAMEDIMENSION +{ + /** Frame Dimensions added to each YUV buffer */ + OMX_U32 nDecWidth; /** Width rounded to multiple of 16 */ + OMX_U32 nDecHeight; /** Height rounded to multiple of 16 */ + OMX_U32 nActualWidth; /** Actual Frame Width */ + OMX_U32 nActualHeight; /** Actual Frame Height */ + +}OMX_QCOM_EXTRADATA_FRAMEDIMENSION; + +typedef struct OMX_QCOM_H264EXTRADATA +{ + OMX_U64 seiTimeStamp; +} OMX_QCOM_H264EXTRADATA; + +typedef struct OMX_QCOM_VC1EXTRADATA +{ + OMX_U32 nVC1RangeY; + OMX_U32 nVC1RangeUV; + OMX_QCOM_VC1RESOLUTIONTYPE eVC1PicResolution; +} OMX_QCOM_VC1EXTRADATA; + +typedef union OMX_QCOM_EXTRADATA_CODEC_DATA +{ + OMX_QCOM_H264EXTRADATA h264ExtraData; + OMX_QCOM_VC1EXTRADATA vc1ExtraData; +} OMX_QCOM_EXTRADATA_CODEC_DATA; + +typedef enum OMX_QCOM_EXTRADATATYPE +{ + OMX_ExtraDataFrameInfo = 0x7F000001, + OMX_ExtraDataH264 = 0x7F000002, + OMX_ExtraDataVC1 = 0x7F000003, + OMX_ExtraDataFrameDimension = 0x7F000004, + OMX_ExtraDataVideoEncoderSliceInfo = 0x7F000005, + OMX_ExtraDataConcealMB = 0x7F000006, + OMX_ExtraDataInterlaceFormat = 0x7F000007, + OMX_ExtraDataPortDef = 0x7F000008, + OMX_ExtraDataMP2ExtnData = 0x7F000009, + OMX_ExtraDataMP2UserData = 0x7F00000a +} OMX_QCOM_EXTRADATATYPE; + +typedef struct OMX_STREAMINTERLACEFORMATTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bInterlaceFormat; + OMX_U32 nInterlaceFormats; +} OMX_STREAMINTERLACEFORMAT; + +typedef enum OMX_INTERLACETYPE +{ + OMX_InterlaceFrameProgressive, + OMX_InterlaceInterleaveFrameTopFieldFirst, + OMX_InterlaceInterleaveFrameBottomFieldFirst, + OMX_InterlaceFrameTopFieldFirst, + OMX_InterlaceFrameBottomFieldFirst +}OMX_INTERLACEs; + + +#define OMX_EXTRADATA_HEADER_SIZE 20 + +/** + * DivX Versions + */ +typedef enum QOMX_VIDEO_DIVXFORMATTYPE { + QOMX_VIDEO_DIVXFormatUnused = 0x01, /**< Format unused or unknown */ + QOMX_VIDEO_DIVXFormat311 = 0x02, /**< DivX 3.11 */ + QOMX_VIDEO_DIVXFormat4 = 0x04, /**< DivX 4 */ + QOMX_VIDEO_DIVXFormat5 = 0x08, /**< DivX 5 */ + QOMX_VIDEO_DIVXFormat6 = 0x10, /**< DivX 6 */ + QOMX_VIDEO_DIVXFormatKhronosExtensions = 0x6F000000, + QOMX_VIDEO_DIVXFormatVendorStartUnused = 0x7F000000, + QOMX_VIDEO_DIVXFormatMax = 0x7FFFFFFF +} QOMX_VIDEO_DIVXFORMATTYPE; + +/** + * DivX profile types, each profile indicates support for + * various performance bounds. + */ +typedef enum QOMX_VIDEO_DIVXPROFILETYPE { + QOMX_VIDEO_DivXProfileqMobile = 0x01, /**< qMobile Profile */ + QOMX_VIDEO_DivXProfileMobile = 0x02, /**< Mobile Profile */ + QOMX_VIDEO_DivXProfileMT = 0x04, /**< Mobile Theatre Profile */ + QOMX_VIDEO_DivXProfileHT = 0x08, /**< Home Theatre Profile */ + QOMX_VIDEO_DivXProfileHD = 0x10, /**< High Definition Profile */ + QOMX_VIDEO_DIVXProfileKhronosExtensions = 0x6F000000, + QOMX_VIDEO_DIVXProfileVendorStartUnused = 0x7F000000, + QOMX_VIDEO_DIVXProfileMax = 0x7FFFFFFF +} QOMX_VIDEO_DIVXPROFILETYPE; + +/** + * DivX Video Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFormat : Version of DivX stream / data + * eProfile : Profile of DivX stream / data + */ +typedef struct QOMX_VIDEO_PARAM_DIVXTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_VIDEO_DIVXFORMATTYPE eFormat; + QOMX_VIDEO_DIVXPROFILETYPE eProfile; +} QOMX_VIDEO_PARAM_DIVXTYPE; + + + +/** + * VP Versions + */ +typedef enum QOMX_VIDEO_VPFORMATTYPE { + QOMX_VIDEO_VPFormatUnused = 0x01, /**< Format unused or unknown */ + QOMX_VIDEO_VPFormat6 = 0x02, /**< VP6 Video Format */ + QOMX_VIDEO_VPFormat7 = 0x04, /**< VP7 Video Format */ + QOMX_VIDEO_VPFormat8 = 0x08, /**< VP8 Video Format */ + QOMX_VIDEO_VPFormatKhronosExtensions = 0x6F000000, + QOMX_VIDEO_VPFormatVendorStartUnused = 0x7F000000, + QOMX_VIDEO_VPFormatMax = 0x7FFFFFFF +} QOMX_VIDEO_VPFORMATTYPE; + +/** + * VP profile types, each profile indicates support for various + * encoding tools. + */ +typedef enum QOMX_VIDEO_VPPROFILETYPE { + QOMX_VIDEO_VPProfileSimple = 0x01, /**< Simple Profile, applies to VP6 only */ + QOMX_VIDEO_VPProfileAdvanced = 0x02, /**< Advanced Profile, applies to VP6 only */ + QOMX_VIDEO_VPProfileVersion0 = 0x04, /**< Version 0, applies to VP7 and VP8 */ + QOMX_VIDEO_VPProfileVersion1 = 0x08, /**< Version 1, applies to VP7 and VP8 */ + QOMX_VIDEO_VPProfileVersion2 = 0x10, /**< Version 2, applies to VP8 only */ + QOMX_VIDEO_VPProfileVersion3 = 0x20, /**< Version 3, applies to VP8 only */ + QOMX_VIDEO_VPProfileKhronosExtensions = 0x6F000000, + QOMX_VIDEO_VPProfileVendorStartUnused = 0x7F000000, + QOMX_VIDEO_VPProfileMax = 0x7FFFFFFF +} QOMX_VIDEO_VPPROFILETYPE; + +/** + * VP Video Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFormat : Format of VP stream / data + * eProfile : Profile or Version of VP stream / data + */ +typedef struct QOMX_VIDEO_PARAM_VPTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_VIDEO_VPFORMATTYPE eFormat; + QOMX_VIDEO_VPPROFILETYPE eProfile; +} QOMX_VIDEO_PARAM_VPTYPE; + +/** + * Spark Versions + */ +typedef enum QOMX_VIDEO_SPARKFORMATTYPE { + QOMX_VIDEO_SparkFormatUnused = 0x01, /**< Format unused or unknown */ + QOMX_VIDEO_SparkFormat0 = 0x02, /**< Video Format Version 0 */ + QOMX_VIDEO_SparkFormat1 = 0x04, /**< Video Format Version 1 */ + QOMX_VIDEO_SparkFormatKhronosExtensions = 0x6F000000, + QOMX_VIDEO_SparkFormatVendorStartUnused = 0x7F000000, + QOMX_VIDEO_SparkFormatMax = 0x7FFFFFFF +} QOMX_VIDEO_SPARKFORMATTYPE; + +/** + * Spark Video Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFormat : Version of Spark stream / data + */ +typedef struct QOMX_VIDEO_PARAM_SPARKTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_VIDEO_SPARKFORMATTYPE eFormat; +} QOMX_VIDEO_PARAM_SPARKTYPE; + + +typedef struct QOMX_VIDEO_QUERY_DECODER_INSTANCES { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nNumOfInstances; +} QOMX_VIDEO_QUERY_DECODER_INSTANCES; + +typedef struct QOMX_ENABLETYPE { + OMX_BOOL bEnable; +} QOMX_ENABLETYPE; + +typedef enum QOMX_VIDEO_EVENTS { + OMX_EventIndexsettingChanged = OMX_EventVendorStartUnused +} QOMX_VIDEO_EVENTS; + +typedef enum QOMX_VIDEO_PICTURE_ORDER { + QOMX_VIDEO_DISPLAY_ORDER = 0x1, + QOMX_VIDEO_DECODE_ORDER = 0x2 +} QOMX_VIDEO_PICTURE_ORDER; + +typedef struct QOMX_VIDEO_DECODER_PICTURE_ORDER { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_VIDEO_PICTURE_ORDER eOutputPictureOrder; +} QOMX_VIDEO_DECODER_PICTURE_ORDER; + +typedef struct QOMX_INDEXEXTRADATATYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnabled; + OMX_INDEXTYPE nIndex; +} QOMX_INDEXEXTRADATATYPE; + +typedef struct QOMX_INDEXTIMESTAMPREORDER { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnable; +} QOMX_INDEXTIMESTAMPREORDER; + +#define OMX_QCOM_INDEX_PARAM_VIDEO_SYNCFRAMEDECODINGMODE "OMX.QCOM.index.param.video.SyncFrameDecodingMode" +#define OMX_QCOM_INDEX_PARAM_INDEXEXTRADATA "OMX.QCOM.index.param.IndexExtraData" +#define OMX_QCOM_INDEX_PARAM_VIDEO_SLICEDELIVERYMODE "OMX.QCOM.index.param.SliceDeliveryMode" + +typedef enum { + QOMX_VIDEO_FRAME_PACKING_CHECKERBOARD = 0, + QOMX_VIDEO_FRAME_PACKING_COLUMN_INTERLEAVE = 1, + QOMX_VIDEO_FRAME_PACKING_ROW_INTERLEAVE = 2, + QOMX_VIDEO_FRAME_PACKING_SIDE_BY_SIDE = 3, + QOMX_VIDEO_FRAME_PACKING_TOP_BOTTOM = 4, + QOMX_VIDEO_FRAME_PACKING_TEMPORAL = 5, +} QOMX_VIDEO_FRAME_PACKING_ARRANGEMENT; + +typedef enum { + QOMX_VIDEO_CONTENT_UNSPECIFIED = 0, + QOMX_VIDEO_CONTENT_LR_VIEW = 1, + QOMX_VIDEO_CONTENT_RL_VIEW = 2, +} QOMX_VIDEO_CONTENT_INTERPRETATION; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __OMX_QCOM_EXTENSIONS_H__ */ diff --git a/mm-core/inc/OMX_Types.h b/mm-core/inc/OMX_Types.h new file mode 100755 index 0000000..9b02a3e --- /dev/null +++ b/mm-core/inc/OMX_Types.h @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_Types.h - OpenMax IL version 1.1.2 + * The OMX_Types header file contains the primitive type definitions used by + * the core, the application and the component. This file may need to be + * modified to be used on systems that do not have "char" set to 8 bits, + * "short" set to 16 bits and "long" set to 32 bits. + */ + +#ifndef OMX_Types_h +#define OMX_Types_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** The OMX_API and OMX_APIENTRY are platform specific definitions used + * to declare OMX function prototypes. They are modified to meet the + * requirements for a particular platform */ +#ifdef __SYMBIAN32__ +# ifdef __OMX_EXPORTS +# define OMX_API __declspec(dllexport) +# else +# ifdef _WIN32 +# define OMX_API __declspec(dllexport) +# else +# define OMX_API __declspec(dllimport) +# endif +# endif +#else +# ifdef _WIN32 +# ifdef __OMX_EXPORTS +# define OMX_API __declspec(dllexport) +# else +# define OMX_API __declspec(dllimport) +# endif +# else +# ifdef __OMX_EXPORTS +# define OMX_API +# else +# define OMX_API extern +# endif +# endif +#endif + +#ifndef OMX_APIENTRY +#define OMX_APIENTRY +#endif + +/** OMX_IN is used to identify inputs to an OMX function. This designation + will also be used in the case of a pointer that points to a parameter + that is used as an output. */ +#ifndef OMX_IN +#define OMX_IN +#endif + +/** OMX_OUT is used to identify outputs from an OMX function. This + designation will also be used in the case of a pointer that points + to a parameter that is used as an input. */ +#ifndef OMX_OUT +#define OMX_OUT +#endif + + +/** OMX_INOUT is used to identify parameters that may be either inputs or + outputs from an OMX function at the same time. This designation will + also be used in the case of a pointer that points to a parameter that + is used both as an input and an output. */ +#ifndef OMX_INOUT +#define OMX_INOUT +#endif + +/** OMX_ALL is used to as a wildcard to select all entities of the same type + * when specifying the index, or referring to a object by an index. (i.e. + * use OMX_ALL to indicate all N channels). When used as a port index + * for a config or parameter this OMX_ALL denotes that the config or + * parameter applies to the entire component not just one port. */ +#define OMX_ALL 0xFFFFFFFF + +/** In the following we define groups that help building doxygen documentation */ + +/** @defgroup core OpenMAX IL core + * Functions and structure related to the OMX IL core + */ + + /** @defgroup comp OpenMAX IL component + * Functions and structure related to the OMX IL component + */ + +/** @defgroup rpm Resource and Policy Management + * Structures for resource and policy management of components + */ + +/** @defgroup buf Buffer Management + * Buffer handling functions and structures + */ + +/** @defgroup tun Tunneling + * @ingroup core comp + * Structures and functions to manage tunnels among component ports + */ + +/** @defgroup cp Content Pipes + * @ingroup core + */ + + /** @defgroup metadata Metadata handling + * + */ + +/** OMX_U8 is an 8 bit unsigned quantity that is byte aligned */ +typedef unsigned char OMX_U8; + +/** OMX_S8 is an 8 bit signed quantity that is byte aligned */ +typedef signed char OMX_S8; + +/** OMX_U16 is a 16 bit unsigned quantity that is 16 bit word aligned */ +typedef unsigned short OMX_U16; + +/** OMX_S16 is a 16 bit signed quantity that is 16 bit word aligned */ +typedef signed short OMX_S16; + +/** OMX_U32 is a 32 bit unsigned quantity that is 32 bit word aligned */ +typedef unsigned long OMX_U32; + +/** OMX_S32 is a 32 bit signed quantity that is 32 bit word aligned */ +typedef signed long OMX_S32; + + +/* Users with compilers that cannot accept the "long long" designation should + define the OMX_SKIP64BIT macro. It should be noted that this may cause + some components to fail to compile if the component was written to require + 64 bit integral types. However, these components would NOT compile anyway + since the compiler does not support the way the component was written. +*/ +#ifndef OMX_SKIP64BIT +#ifdef __SYMBIAN32__ +/** OMX_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ +typedef unsigned long long OMX_U64; + +/** OMX_S64 is a 64 bit signed quantity that is 64 bit word aligned */ +typedef signed long long OMX_S64; + +#elif defined(WIN32) + +/** OMX_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ +typedef unsigned __int64 OMX_U64; + +/** OMX_S64 is a 64 bit signed quantity that is 64 bit word aligned */ +typedef signed __int64 OMX_S64; + +#else /* WIN32 */ + +/** OMX_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ +typedef unsigned long long OMX_U64; + +/** OMX_S64 is a 64 bit signed quantity that is 64 bit word aligned */ +typedef signed long long OMX_S64; + +#endif /* WIN32 */ +#endif + + +/** The OMX_BOOL type is intended to be used to represent a true or a false + value when passing parameters to and from the OMX core and components. The + OMX_BOOL is a 32 bit quantity and is aligned on a 32 bit word boundary. + */ +typedef enum OMX_BOOL { + OMX_FALSE = 0, + OMX_TRUE = !OMX_FALSE, + OMX_BOOL_MAX = 0x7FFFFFFF +} OMX_BOOL; + +/** The OMX_PTR type is intended to be used to pass pointers between the OMX + applications and the OMX Core and components. This is a 32 bit pointer and + is aligned on a 32 bit boundary. + */ +typedef void* OMX_PTR; + +/** The OMX_STRING type is intended to be used to pass "C" type strings between + the application and the core and component. The OMX_STRING type is a 32 + bit pointer to a zero terminated string. The pointer is word aligned and + the string is byte aligned. + */ +typedef char* OMX_STRING; + +/** The OMX_BYTE type is intended to be used to pass arrays of bytes such as + buffers between the application and the component and core. The OMX_BYTE + type is a 32 bit pointer to a zero terminated string. The pointer is word + aligned and the string is byte aligned. + */ +typedef unsigned char* OMX_BYTE; + +/** OMX_UUIDTYPE is a very long unique identifier to uniquely identify + at runtime. This identifier should be generated by a component in a way + that guarantees that every instance of the identifier running on the system + is unique. */ +typedef unsigned char OMX_UUIDTYPE[128]; + +/** The OMX_DIRTYPE enumeration is used to indicate if a port is an input or + an output port. This enumeration is common across all component types. + */ +typedef enum OMX_DIRTYPE +{ + OMX_DirInput, /**< Port is an input port */ + OMX_DirOutput, /**< Port is an output port */ + OMX_DirMax = 0x7FFFFFFF +} OMX_DIRTYPE; + +/** The OMX_ENDIANTYPE enumeration is used to indicate the bit ordering + for numerical data (i.e. big endian, or little endian). + */ +typedef enum OMX_ENDIANTYPE +{ + OMX_EndianBig, /**< big endian */ + OMX_EndianLittle, /**< little endian */ + OMX_EndianMax = 0x7FFFFFFF +} OMX_ENDIANTYPE; + + +/** The OMX_NUMERICALDATATYPE enumeration is used to indicate if data + is signed or unsigned + */ +typedef enum OMX_NUMERICALDATATYPE +{ + OMX_NumericalDataSigned, /**< signed data */ + OMX_NumericalDataUnsigned, /**< unsigned data */ + OMX_NumercialDataMax = 0x7FFFFFFF +} OMX_NUMERICALDATATYPE; + + +/** Unsigned bounded value type */ +typedef struct OMX_BU32 { + OMX_U32 nValue; /**< actual value */ + OMX_U32 nMin; /**< minimum for value (i.e. nValue >= nMin) */ + OMX_U32 nMax; /**< maximum for value (i.e. nValue <= nMax) */ +} OMX_BU32; + + +/** Signed bounded value type */ +typedef struct OMX_BS32 { + OMX_S32 nValue; /**< actual value */ + OMX_S32 nMin; /**< minimum for value (i.e. nValue >= nMin) */ + OMX_S32 nMax; /**< maximum for value (i.e. nValue <= nMax) */ +} OMX_BS32; + + +/** Structure representing some time or duration in microseconds. This structure + * must be interpreted as a signed 64 bit value. The quantity is signed to accommodate + * negative deltas and preroll scenarios. The quantity is represented in microseconds + * to accomodate high resolution timestamps (e.g. DVD presentation timestamps based + * on a 90kHz clock) and to allow more accurate and synchronized delivery (e.g. + * individual audio samples delivered at 192 kHz). The quantity is 64 bit to + * accommodate a large dynamic range (signed 32 bit values would allow only for plus + * or minus 35 minutes). + * + * Implementations with limited precision may convert the signed 64 bit value to + * a signed 32 bit value internally but risk loss of precision. + */ +#ifndef OMX_SKIP64BIT +typedef OMX_S64 OMX_TICKS; +#else +typedef struct OMX_TICKS +{ + OMX_U32 nLowPart; /** low bits of the signed 64 bit tick value */ + OMX_U32 nHighPart; /** high bits of the signed 64 bit tick value */ +} OMX_TICKS; +#endif +#define OMX_TICKS_PER_SECOND 1000000 + +/** Define the public interface for the OMX Handle. The core will not use + this value internally, but the application should only use this value. + */ +typedef void* OMX_HANDLETYPE; + +typedef struct OMX_MARKTYPE +{ + OMX_HANDLETYPE hMarkTargetComponent; /**< The component that will + generate a mark event upon + processing the mark. */ + OMX_PTR pMarkData; /**< Application specific data associated with + the mark sent on a mark event to disambiguate + this mark from others. */ +} OMX_MARKTYPE; + + +/** OMX_NATIVE_DEVICETYPE is used to map a OMX video port to the + * platform & operating specific object used to reference the display + * or can be used by a audio port for native audio rendering */ +typedef void* OMX_NATIVE_DEVICETYPE; + +/** OMX_NATIVE_WINDOWTYPE is used to map a OMX video port to the + * platform & operating specific object used to reference the window */ +typedef void* OMX_NATIVE_WINDOWTYPE; + +/** The OMX_VERSIONTYPE union is used to specify the version for + a structure or component. For a component, the version is entirely + specified by the component vendor. Components doing the same function + from different vendors may or may not have the same version. For + structures, the version shall be set by the entity that allocates the + structure. For structures specified in the OMX 1.1 specification, the + value of the version shall be set to 1.1.0.0 in all cases. Access to the + OMX_VERSIONTYPE can be by a single 32 bit access (e.g. by nVersion) or + by accessing one of the structure elements to, for example, check only + the Major revision. + */ +typedef union OMX_VERSIONTYPE +{ + struct + { + OMX_U8 nVersionMajor; /**< Major version accessor element */ + OMX_U8 nVersionMinor; /**< Minor version accessor element */ + OMX_U8 nRevision; /**< Revision version accessor element */ + OMX_U8 nStep; /**< Step version accessor element */ + } s; + OMX_U32 nVersion; /**< 32 bit value to make accessing the + version easily done in a single word + size copy/compare operation */ +} OMX_VERSIONTYPE; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ diff --git a/mm-core/inc/OMX_Video.h b/mm-core/inc/OMX_Video.h new file mode 100755 index 0000000..1fc334b --- /dev/null +++ b/mm-core/inc/OMX_Video.h @@ -0,0 +1,1061 @@ +/** + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file OMX_Video.h - OpenMax IL version 1.1.2 + * The structures is needed by Video components to exchange parameters + * and configuration data with OMX components. + */ +#ifndef OMX_Video_h +#define OMX_Video_h + +/** @defgroup video OpenMAX IL Video Domain + * @ingroup iv + * Structures for OpenMAX IL Video domain + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/** + * Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include + + +/** + * Enumeration used to define the possible video compression codings. + * NOTE: This essentially refers to file extensions. If the coding is + * being used to specify the ENCODE type, then additional work + * must be done to configure the exact flavor of the compression + * to be used. For decode cases where the user application can + * not differentiate between MPEG-4 and H.264 bit streams, it is + * up to the codec to handle this. + */ +typedef enum OMX_VIDEO_CODINGTYPE { + OMX_VIDEO_CodingUnused, /**< Value when coding is N/A */ + OMX_VIDEO_CodingAutoDetect, /**< Autodetection of coding type */ + OMX_VIDEO_CodingMPEG2, /**< AKA: H.262 */ + OMX_VIDEO_CodingH263, /**< H.263 */ + OMX_VIDEO_CodingMPEG4, /**< MPEG-4 */ + OMX_VIDEO_CodingWMV, /**< all versions of Windows Media Video */ + OMX_VIDEO_CodingRV, /**< all versions of Real Video */ + OMX_VIDEO_CodingAVC, /**< H.264/AVC */ + OMX_VIDEO_CodingMJPEG, /**< Motion JPEG */ + OMX_VIDEO_CodingVPX, /**< Google VPX, formerly known as On2 VP8 */ + OMX_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_CodingMax = 0x7FFFFFFF +} OMX_VIDEO_CODINGTYPE; + + +/** + * Data structure used to define a video path. The number of Video paths for + * input and output will vary by type of the Video component. + * + * Input (aka Source) : zero Inputs, one Output, + * Splitter : one Input, 2 or more Outputs, + * Processing Element : one Input, one output, + * Mixer : 2 or more inputs, one output, + * Output (aka Sink) : one Input, zero outputs. + * + * The PortDefinition structure is used to define all of the parameters + * necessary for the compliant component to setup an input or an output video + * path. If additional vendor specific data is required, it should be + * transmitted to the component using the CustomCommand function. Compliant + * components will prepopulate this structure with optimal values during the + * GetDefaultInitParams command. + * + * STRUCT MEMBERS: + * cMIMEType : MIME type of data for the port + * pNativeRender : Platform specific reference for a display if a + * sync, otherwise this field is 0 + * nFrameWidth : Width of frame to be used on channel if + * uncompressed format is used. Use 0 for unknown, + * don't care or variable + * nFrameHeight : Height of frame to be used on channel if + * uncompressed format is used. Use 0 for unknown, + * don't care or variable + * nStride : Number of bytes per span of an image + * (i.e. indicates the number of bytes to get + * from span N to span N+1, where negative stride + * indicates the image is bottom up + * nSliceHeight : Height used when encoding in slices + * nBitrate : Bit rate of frame to be used on channel if + * compressed format is used. Use 0 for unknown, + * don't care or variable + * xFramerate : Frame rate to be used on channel if uncompressed + * format is used. Use 0 for unknown, don't care or + * variable. Units are Q16 frames per second. + * bFlagErrorConcealment : Turns on error concealment if it is supported by + * the OMX component + * eCompressionFormat : Compression format used in this instance of the + * component. When OMX_VIDEO_CodingUnused is + * specified, eColorFormat is used + * eColorFormat : Decompressed format used by this component + * pNativeWindow : Platform specific reference for a window object if a + * display sink , otherwise this field is 0x0. + */ +typedef struct OMX_VIDEO_PORTDEFINITIONTYPE { + OMX_STRING cMIMEType; + OMX_NATIVE_DEVICETYPE pNativeRender; + OMX_U32 nFrameWidth; + OMX_U32 nFrameHeight; + OMX_S32 nStride; + OMX_U32 nSliceHeight; + OMX_U32 nBitrate; + OMX_U32 xFramerate; + OMX_BOOL bFlagErrorConcealment; + OMX_VIDEO_CODINGTYPE eCompressionFormat; + OMX_COLOR_FORMATTYPE eColorFormat; + OMX_NATIVE_WINDOWTYPE pNativeWindow; +} OMX_VIDEO_PORTDEFINITIONTYPE; + +/** + * Port format parameter. This structure is used to enumerate the various + * data input/output format supported by the port. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Indicates which port to set + * nIndex : Indicates the enumeration index for the format from + * 0x0 to N-1 + * eCompressionFormat : Compression format used in this instance of the + * component. When OMX_VIDEO_CodingUnused is specified, + * eColorFormat is used + * eColorFormat : Decompressed format used by this component + * xFrameRate : Indicates the video frame rate in Q16 format + */ +typedef struct OMX_VIDEO_PARAM_PORTFORMATTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nIndex; + OMX_VIDEO_CODINGTYPE eCompressionFormat; + OMX_COLOR_FORMATTYPE eColorFormat; + OMX_U32 xFramerate; +} OMX_VIDEO_PARAM_PORTFORMATTYPE; + + +/** + * This is a structure for configuring video compression quantization + * parameter values. Codecs may support different QP values for different + * frame types. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * nQpI : QP value to use for index frames + * nQpP : QP value to use for P frames + * nQpB : QP values to use for bidirectional frames + */ +typedef struct OMX_VIDEO_PARAM_QUANTIZATIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nQpI; + OMX_U32 nQpP; + OMX_U32 nQpB; +} OMX_VIDEO_PARAM_QUANTIZATIONTYPE; + + +/** + * Structure for configuration of video fast update parameters. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * bEnableVFU : Enable/Disable video fast update + * nFirstGOB : Specifies the number of the first macroblock row + * nFirstMB : specifies the first MB relative to the specified first GOB + * nNumMBs : Specifies the number of MBs to be refreshed from nFirstGOB + * and nFirstMB + */ +typedef struct OMX_VIDEO_PARAM_VIDEOFASTUPDATETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnableVFU; + OMX_U32 nFirstGOB; + OMX_U32 nFirstMB; + OMX_U32 nNumMBs; +} OMX_VIDEO_PARAM_VIDEOFASTUPDATETYPE; + + +/** + * Enumeration of possible bitrate control types + */ +typedef enum OMX_VIDEO_CONTROLRATETYPE { + OMX_Video_ControlRateDisable, + OMX_Video_ControlRateVariable, + OMX_Video_ControlRateConstant, + OMX_Video_ControlRateVariableSkipFrames, + OMX_Video_ControlRateConstantSkipFrames, + OMX_Video_ControlRateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_Video_ControlRateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_Video_ControlRateMax = 0x7FFFFFFF +} OMX_VIDEO_CONTROLRATETYPE; + + +/** + * Structure for configuring bitrate mode of a codec. + * + * STRUCT MEMBERS: + * nSize : Size of the struct in bytes + * nVersion : OMX spec version info + * nPortIndex : Port that this struct applies to + * eControlRate : Control rate type enum + * nTargetBitrate : Target bitrate to encode with + */ +typedef struct OMX_VIDEO_PARAM_BITRATETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_CONTROLRATETYPE eControlRate; + OMX_U32 nTargetBitrate; +} OMX_VIDEO_PARAM_BITRATETYPE; + + +/** + * Enumeration of possible motion vector (MV) types + */ +typedef enum OMX_VIDEO_MOTIONVECTORTYPE { + OMX_Video_MotionVectorPixel, + OMX_Video_MotionVectorHalfPel, + OMX_Video_MotionVectorQuarterPel, + OMX_Video_MotionVectorEighthPel, + OMX_Video_MotionVectorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_Video_MotionVectorVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_Video_MotionVectorMax = 0x7FFFFFFF +} OMX_VIDEO_MOTIONVECTORTYPE; + + +/** + * Structure for configuring the number of motion vectors used as well + * as their accuracy. + * + * STRUCT MEMBERS: + * nSize : Size of the struct in bytes + * nVersion : OMX spec version info + * nPortIndex : port that this structure applies to + * eAccuracy : Enumerated MV accuracy + * bUnrestrictedMVs : Allow unrestricted MVs + * bFourMV : Allow use of 4 MVs + * sXSearchRange : Search range in horizontal direction for MVs + * sYSearchRange : Search range in vertical direction for MVs + */ +typedef struct OMX_VIDEO_PARAM_MOTIONVECTORTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_MOTIONVECTORTYPE eAccuracy; + OMX_BOOL bUnrestrictedMVs; + OMX_BOOL bFourMV; + OMX_S32 sXSearchRange; + OMX_S32 sYSearchRange; +} OMX_VIDEO_PARAM_MOTIONVECTORTYPE; + + +/** + * Enumeration of possible methods to use for Intra Refresh + */ +typedef enum OMX_VIDEO_INTRAREFRESHTYPE { + OMX_VIDEO_IntraRefreshCyclic, + OMX_VIDEO_IntraRefreshAdaptive, + OMX_VIDEO_IntraRefreshBoth, + OMX_VIDEO_IntraRefreshKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_IntraRefreshVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_IntraRefreshMax = 0x7FFFFFFF +} OMX_VIDEO_INTRAREFRESHTYPE; + + +/** + * Structure for configuring intra refresh mode + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eRefreshMode : Cyclic, Adaptive, or Both + * nAirMBs : Number of intra macroblocks to refresh in a frame when + * AIR is enabled + * nAirRef : Number of times a motion marked macroblock has to be + * intra coded + * nCirMBs : Number of consecutive macroblocks to be coded as "intra" + * when CIR is enabled + */ +typedef struct OMX_VIDEO_PARAM_INTRAREFRESHTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_INTRAREFRESHTYPE eRefreshMode; + OMX_U32 nAirMBs; + OMX_U32 nAirRef; + OMX_U32 nCirMBs; +} OMX_VIDEO_PARAM_INTRAREFRESHTYPE; + + +/** + * Structure for enabling various error correction methods for video + * compression. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bEnableHEC : Enable/disable header extension codes (HEC) + * bEnableResync : Enable/disable resynchronization markers + * nResynchMarkerSpacing : Resynch markers interval (in bits) to be + * applied in the stream + * bEnableDataPartitioning : Enable/disable data partitioning + * bEnableRVLC : Enable/disable reversible variable length + * coding + */ +typedef struct OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnableHEC; + OMX_BOOL bEnableResync; + OMX_U32 nResynchMarkerSpacing; + OMX_BOOL bEnableDataPartitioning; + OMX_BOOL bEnableRVLC; +} OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE; + + +/** + * Configuration of variable block-size motion compensation (VBSMC) + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * b16x16 : Enable inter block search 16x16 + * b16x8 : Enable inter block search 16x8 + * b8x16 : Enable inter block search 8x16 + * b8x8 : Enable inter block search 8x8 + * b8x4 : Enable inter block search 8x4 + * b4x8 : Enable inter block search 4x8 + * b4x4 : Enable inter block search 4x4 + */ +typedef struct OMX_VIDEO_PARAM_VBSMCTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL b16x16; + OMX_BOOL b16x8; + OMX_BOOL b8x16; + OMX_BOOL b8x8; + OMX_BOOL b8x4; + OMX_BOOL b4x8; + OMX_BOOL b4x4; +} OMX_VIDEO_PARAM_VBSMCTYPE; + + +/** + * H.263 profile types, each profile indicates support for various + * performance bounds and different annexes. + * + * ENUMS: + * Baseline : Baseline Profile: H.263 (V1), no optional modes + * H320 Coding : H.320 Coding Efficiency Backward Compatibility + * Profile: H.263+ (V2), includes annexes I, J, L.4 + * and T + * BackwardCompatible : Backward Compatibility Profile: H.263 (V1), + * includes annex F + * ISWV2 : Interactive Streaming Wireless Profile: H.263+ + * (V2), includes annexes I, J, K and T + * ISWV3 : Interactive Streaming Wireless Profile: H.263++ + * (V3), includes profile 3 and annexes V and W.6.3.8 + * HighCompression : Conversational High Compression Profile: H.263++ + * (V3), includes profiles 1 & 2 and annexes D and U + * Internet : Conversational Internet Profile: H.263++ (V3), + * includes profile 5 and annex K + * Interlace : Conversational Interlace Profile: H.263++ (V3), + * includes profile 5 and annex W.6.3.11 + * HighLatency : High Latency Profile: H.263++ (V3), includes + * profile 6 and annexes O.1 and P.5 + */ +typedef enum OMX_VIDEO_H263PROFILETYPE { + OMX_VIDEO_H263ProfileBaseline = 0x01, + OMX_VIDEO_H263ProfileH320Coding = 0x02, + OMX_VIDEO_H263ProfileBackwardCompatible = 0x04, + OMX_VIDEO_H263ProfileISWV2 = 0x08, + OMX_VIDEO_H263ProfileISWV3 = 0x10, + OMX_VIDEO_H263ProfileHighCompression = 0x20, + OMX_VIDEO_H263ProfileInternet = 0x40, + OMX_VIDEO_H263ProfileInterlace = 0x80, + OMX_VIDEO_H263ProfileHighLatency = 0x100, + OMX_VIDEO_H263ProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_H263ProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_H263ProfileMax = 0x7FFFFFFF +} OMX_VIDEO_H263PROFILETYPE; + + +/** + * H.263 level types, each level indicates support for various frame sizes, + * bit rates, decoder frame rates. + */ +typedef enum OMX_VIDEO_H263LEVELTYPE { + OMX_VIDEO_H263Level10 = 0x01, + OMX_VIDEO_H263Level20 = 0x02, + OMX_VIDEO_H263Level30 = 0x04, + OMX_VIDEO_H263Level40 = 0x08, + OMX_VIDEO_H263Level45 = 0x10, + OMX_VIDEO_H263Level50 = 0x20, + OMX_VIDEO_H263Level60 = 0x40, + OMX_VIDEO_H263Level70 = 0x80, + OMX_VIDEO_H263LevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_H263LevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_H263LevelMax = 0x7FFFFFFF +} OMX_VIDEO_H263LEVELTYPE; + + +/** + * Specifies the picture type. These values should be OR'd to signal all + * pictures types which are allowed. + * + * ENUMS: + * Generic Picture Types: I, P and B + * H.263 Specific Picture Types: SI and SP + * H.264 Specific Picture Types: EI and EP + * MPEG-4 Specific Picture Types: S + */ +typedef enum OMX_VIDEO_PICTURETYPE { + OMX_VIDEO_PictureTypeI = 0x01, + OMX_VIDEO_PictureTypeP = 0x02, + OMX_VIDEO_PictureTypeB = 0x04, + OMX_VIDEO_PictureTypeSI = 0x08, + OMX_VIDEO_PictureTypeSP = 0x10, + OMX_VIDEO_PictureTypeEI = 0x11, + OMX_VIDEO_PictureTypeEP = 0x12, + OMX_VIDEO_PictureTypeS = 0x14, + OMX_VIDEO_PictureTypeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_PictureTypeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_PictureTypeMax = 0x7FFFFFFF +} OMX_VIDEO_PICTURETYPE; + + +/** + * H.263 Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nPFrames : Number of P frames between each I frame + * nBFrames : Number of B frames between each I frame + * eProfile : H.263 profile(s) to use + * eLevel : H.263 level(s) to use + * bPLUSPTYPEAllowed : Indicating that it is allowed to use PLUSPTYPE + * (specified in the 1998 version of H.263) to + * indicate custom picture sizes or clock + * frequencies + * nAllowedPictureTypes : Specifies the picture types allowed in the + * bitstream + * bForceRoundingTypeToZero : value of the RTYPE bit (bit 6 of MPPTYPE) is + * not constrained. It is recommended to change + * the value of the RTYPE bit for each reference + * picture in error-free communication + * nPictureHeaderRepetition : Specifies the frequency of picture header + * repetition + * nGOBHeaderInterval : Specifies the interval of non-empty GOB + * headers in units of GOBs + */ +typedef struct OMX_VIDEO_PARAM_H263TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nPFrames; + OMX_U32 nBFrames; + OMX_VIDEO_H263PROFILETYPE eProfile; + OMX_VIDEO_H263LEVELTYPE eLevel; + OMX_BOOL bPLUSPTYPEAllowed; + OMX_U32 nAllowedPictureTypes; + OMX_BOOL bForceRoundingTypeToZero; + OMX_U32 nPictureHeaderRepetition; + OMX_U32 nGOBHeaderInterval; +} OMX_VIDEO_PARAM_H263TYPE; + + +/** + * MPEG-2 profile types, each profile indicates support for various + * performance bounds and different annexes. + */ +typedef enum OMX_VIDEO_MPEG2PROFILETYPE { + OMX_VIDEO_MPEG2ProfileSimple = 0, /**< Simple Profile */ + OMX_VIDEO_MPEG2ProfileMain, /**< Main Profile */ + OMX_VIDEO_MPEG2Profile422, /**< 4:2:2 Profile */ + OMX_VIDEO_MPEG2ProfileSNR, /**< SNR Profile */ + OMX_VIDEO_MPEG2ProfileSpatial, /**< Spatial Profile */ + OMX_VIDEO_MPEG2ProfileHigh, /**< High Profile */ + OMX_VIDEO_MPEG2ProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_MPEG2ProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_MPEG2ProfileMax = 0x7FFFFFFF +} OMX_VIDEO_MPEG2PROFILETYPE; + + +/** + * MPEG-2 level types, each level indicates support for various frame + * sizes, bit rates, decoder frame rates. No need + */ +typedef enum OMX_VIDEO_MPEG2LEVELTYPE { + OMX_VIDEO_MPEG2LevelLL = 0, /**< Low Level */ + OMX_VIDEO_MPEG2LevelML, /**< Main Level */ + OMX_VIDEO_MPEG2LevelH14, /**< High 1440 */ + OMX_VIDEO_MPEG2LevelHL, /**< High Level */ + OMX_VIDEO_MPEG2LevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_MPEG2LevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_MPEG2LevelMax = 0x7FFFFFFF +} OMX_VIDEO_MPEG2LEVELTYPE; + + +/** + * MPEG-2 params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nPFrames : Number of P frames between each I frame + * nBFrames : Number of B frames between each I frame + * eProfile : MPEG-2 profile(s) to use + * eLevel : MPEG-2 levels(s) to use + */ +typedef struct OMX_VIDEO_PARAM_MPEG2TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nPFrames; + OMX_U32 nBFrames; + OMX_VIDEO_MPEG2PROFILETYPE eProfile; + OMX_VIDEO_MPEG2LEVELTYPE eLevel; +} OMX_VIDEO_PARAM_MPEG2TYPE; + + +/** + * MPEG-4 profile types, each profile indicates support for various + * performance bounds and different annexes. + * + * ENUMS: + * - Simple Profile, Levels 1-3 + * - Simple Scalable Profile, Levels 1-2 + * - Core Profile, Levels 1-2 + * - Main Profile, Levels 2-4 + * - N-bit Profile, Level 2 + * - Scalable Texture Profile, Level 1 + * - Simple Face Animation Profile, Levels 1-2 + * - Simple Face and Body Animation (FBA) Profile, Levels 1-2 + * - Basic Animated Texture Profile, Levels 1-2 + * - Hybrid Profile, Levels 1-2 + * - Advanced Real Time Simple Profiles, Levels 1-4 + * - Core Scalable Profile, Levels 1-3 + * - Advanced Coding Efficiency Profile, Levels 1-4 + * - Advanced Core Profile, Levels 1-2 + * - Advanced Scalable Texture, Levels 2-3 + */ +typedef enum OMX_VIDEO_MPEG4PROFILETYPE { + OMX_VIDEO_MPEG4ProfileSimple = 0x01, + OMX_VIDEO_MPEG4ProfileSimpleScalable = 0x02, + OMX_VIDEO_MPEG4ProfileCore = 0x04, + OMX_VIDEO_MPEG4ProfileMain = 0x08, + OMX_VIDEO_MPEG4ProfileNbit = 0x10, + OMX_VIDEO_MPEG4ProfileScalableTexture = 0x20, + OMX_VIDEO_MPEG4ProfileSimpleFace = 0x40, + OMX_VIDEO_MPEG4ProfileSimpleFBA = 0x80, + OMX_VIDEO_MPEG4ProfileBasicAnimated = 0x100, + OMX_VIDEO_MPEG4ProfileHybrid = 0x200, + OMX_VIDEO_MPEG4ProfileAdvancedRealTime = 0x400, + OMX_VIDEO_MPEG4ProfileCoreScalable = 0x800, + OMX_VIDEO_MPEG4ProfileAdvancedCoding = 0x1000, + OMX_VIDEO_MPEG4ProfileAdvancedCore = 0x2000, + OMX_VIDEO_MPEG4ProfileAdvancedScalable = 0x4000, + OMX_VIDEO_MPEG4ProfileAdvancedSimple = 0x8000, + OMX_VIDEO_MPEG4ProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_MPEG4ProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_MPEG4ProfileMax = 0x7FFFFFFF +} OMX_VIDEO_MPEG4PROFILETYPE; + + +/** + * MPEG-4 level types, each level indicates support for various frame + * sizes, bit rates, decoder frame rates. No need + */ +typedef enum OMX_VIDEO_MPEG4LEVELTYPE { + OMX_VIDEO_MPEG4Level0 = 0x01, /**< Level 0 */ + OMX_VIDEO_MPEG4Level0b = 0x02, /**< Level 0b */ + OMX_VIDEO_MPEG4Level1 = 0x04, /**< Level 1 */ + OMX_VIDEO_MPEG4Level2 = 0x08, /**< Level 2 */ + OMX_VIDEO_MPEG4Level3 = 0x10, /**< Level 3 */ + OMX_VIDEO_MPEG4Level4 = 0x20, /**< Level 4 */ + OMX_VIDEO_MPEG4Level4a = 0x40, /**< Level 4a */ + OMX_VIDEO_MPEG4Level5 = 0x80, /**< Level 5 */ + OMX_VIDEO_MPEG4LevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_MPEG4LevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_MPEG4LevelMax = 0x7FFFFFFF +} OMX_VIDEO_MPEG4LEVELTYPE; + + +/** + * MPEG-4 configuration. This structure handles configuration options + * which are specific to MPEG4 algorithms + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nSliceHeaderSpacing : Number of macroblocks between slice header (H263+ + * Annex K). Put zero if not used + * bSVH : Enable Short Video Header mode + * bGov : Flag to enable GOV + * nPFrames : Number of P frames between each I frame (also called + * GOV period) + * nBFrames : Number of B frames between each I frame + * nIDCVLCThreshold : Value of intra DC VLC threshold + * bACPred : Flag to use ac prediction + * nMaxPacketSize : Maximum size of packet in bytes. + * nTimeIncRes : Used to pass VOP time increment resolution for MPEG4. + * Interpreted as described in MPEG4 standard. + * eProfile : MPEG-4 profile(s) to use. + * eLevel : MPEG-4 level(s) to use. + * nAllowedPictureTypes : Specifies the picture types allowed in the bitstream + * nHeaderExtension : Specifies the number of consecutive video packet + * headers within a VOP + * bReversibleVLC : Specifies whether reversible variable length coding + * is in use + */ +typedef struct OMX_VIDEO_PARAM_MPEG4TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nSliceHeaderSpacing; + OMX_BOOL bSVH; + OMX_BOOL bGov; + OMX_U32 nPFrames; + OMX_U32 nBFrames; + OMX_U32 nIDCVLCThreshold; + OMX_BOOL bACPred; + OMX_U32 nMaxPacketSize; + OMX_U32 nTimeIncRes; + OMX_VIDEO_MPEG4PROFILETYPE eProfile; + OMX_VIDEO_MPEG4LEVELTYPE eLevel; + OMX_U32 nAllowedPictureTypes; + OMX_U32 nHeaderExtension; + OMX_BOOL bReversibleVLC; +} OMX_VIDEO_PARAM_MPEG4TYPE; + + +/** + * WMV Versions + */ +typedef enum OMX_VIDEO_WMVFORMATTYPE { + OMX_VIDEO_WMVFormatUnused = 0x01, /**< Format unused or unknown */ + OMX_VIDEO_WMVFormat7 = 0x02, /**< Windows Media Video format 7 */ + OMX_VIDEO_WMVFormat8 = 0x04, /**< Windows Media Video format 8 */ + OMX_VIDEO_WMVFormat9 = 0x08, /**< Windows Media Video format 9 */ + OMX_VIDEO_WMFFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_WMFFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_WMVFormatMax = 0x7FFFFFFF +} OMX_VIDEO_WMVFORMATTYPE; + + +/** + * WMV Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFormat : Version of WMV stream / data + */ +typedef struct OMX_VIDEO_PARAM_WMVTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_WMVFORMATTYPE eFormat; +} OMX_VIDEO_PARAM_WMVTYPE; + + +/** + * Real Video Version + */ +typedef enum OMX_VIDEO_RVFORMATTYPE { + OMX_VIDEO_RVFormatUnused = 0, /**< Format unused or unknown */ + OMX_VIDEO_RVFormat8, /**< Real Video format 8 */ + OMX_VIDEO_RVFormat9, /**< Real Video format 9 */ + OMX_VIDEO_RVFormatG2, /**< Real Video Format G2 */ + OMX_VIDEO_RVFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_RVFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_RVFormatMax = 0x7FFFFFFF +} OMX_VIDEO_RVFORMATTYPE; + + +/** + * Real Video Params + * + * STUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFormat : Version of RV stream / data + * nBitsPerPixel : Bits per pixel coded in the frame + * nPaddedWidth : Padded width in pixel of a video frame + * nPaddedHeight : Padded Height in pixels of a video frame + * nFrameRate : Rate of video in frames per second + * nBitstreamFlags : Flags which internal information about the bitstream + * nBitstreamVersion : Bitstream version + * nMaxEncodeFrameSize: Max encoded frame size + * bEnablePostFilter : Turn on/off post filter + * bEnableTemporalInterpolation : Turn on/off temporal interpolation + * bEnableLatencyMode : When enabled, the decoder does not display a decoded + * frame until it has detected that no enhancement layer + * frames or dependent B frames will be coming. This + * detection usually occurs when a subsequent non-B + * frame is encountered + */ +typedef struct OMX_VIDEO_PARAM_RVTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_RVFORMATTYPE eFormat; + OMX_U16 nBitsPerPixel; + OMX_U16 nPaddedWidth; + OMX_U16 nPaddedHeight; + OMX_U32 nFrameRate; + OMX_U32 nBitstreamFlags; + OMX_U32 nBitstreamVersion; + OMX_U32 nMaxEncodeFrameSize; + OMX_BOOL bEnablePostFilter; + OMX_BOOL bEnableTemporalInterpolation; + OMX_BOOL bEnableLatencyMode; +} OMX_VIDEO_PARAM_RVTYPE; + + +/** + * AVC profile types, each profile indicates support for various + * performance bounds and different annexes. + */ +typedef enum OMX_VIDEO_AVCPROFILETYPE { + OMX_VIDEO_AVCProfileBaseline = 0x01, /**< Baseline profile */ + OMX_VIDEO_AVCProfileMain = 0x02, /**< Main profile */ + OMX_VIDEO_AVCProfileExtended = 0x04, /**< Extended profile */ + OMX_VIDEO_AVCProfileHigh = 0x08, /**< High profile */ + OMX_VIDEO_AVCProfileHigh10 = 0x10, /**< High 10 profile */ + OMX_VIDEO_AVCProfileHigh422 = 0x20, /**< High 4:2:2 profile */ + OMX_VIDEO_AVCProfileHigh444 = 0x40, /**< High 4:4:4 profile */ + OMX_VIDEO_AVCProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_AVCProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_AVCProfileMax = 0x7FFFFFFF +} OMX_VIDEO_AVCPROFILETYPE; + + +/** + * AVC level types, each level indicates support for various frame sizes, + * bit rates, decoder frame rates. No need + */ +typedef enum OMX_VIDEO_AVCLEVELTYPE { + OMX_VIDEO_AVCLevel1 = 0x01, /**< Level 1 */ + OMX_VIDEO_AVCLevel1b = 0x02, /**< Level 1b */ + OMX_VIDEO_AVCLevel11 = 0x04, /**< Level 1.1 */ + OMX_VIDEO_AVCLevel12 = 0x08, /**< Level 1.2 */ + OMX_VIDEO_AVCLevel13 = 0x10, /**< Level 1.3 */ + OMX_VIDEO_AVCLevel2 = 0x20, /**< Level 2 */ + OMX_VIDEO_AVCLevel21 = 0x40, /**< Level 2.1 */ + OMX_VIDEO_AVCLevel22 = 0x80, /**< Level 2.2 */ + OMX_VIDEO_AVCLevel3 = 0x100, /**< Level 3 */ + OMX_VIDEO_AVCLevel31 = 0x200, /**< Level 3.1 */ + OMX_VIDEO_AVCLevel32 = 0x400, /**< Level 3.2 */ + OMX_VIDEO_AVCLevel4 = 0x800, /**< Level 4 */ + OMX_VIDEO_AVCLevel41 = 0x1000, /**< Level 4.1 */ + OMX_VIDEO_AVCLevel42 = 0x2000, /**< Level 4.2 */ + OMX_VIDEO_AVCLevel5 = 0x4000, /**< Level 5 */ + OMX_VIDEO_AVCLevel51 = 0x8000, /**< Level 5.1 */ + OMX_VIDEO_AVCLevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_AVCLevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_AVCLevelMax = 0x7FFFFFFF +} OMX_VIDEO_AVCLEVELTYPE; + + +/** + * AVC loop filter modes + * + * OMX_VIDEO_AVCLoopFilterEnable : Enable + * OMX_VIDEO_AVCLoopFilterDisable : Disable + * OMX_VIDEO_AVCLoopFilterDisableSliceBoundary : Disabled on slice boundaries + */ +typedef enum OMX_VIDEO_AVCLOOPFILTERTYPE { + OMX_VIDEO_AVCLoopFilterEnable = 0, + OMX_VIDEO_AVCLoopFilterDisable, + OMX_VIDEO_AVCLoopFilterDisableSliceBoundary, + OMX_VIDEO_AVCLoopFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_AVCLoopFilterVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_AVCLoopFilterMax = 0x7FFFFFFF +} OMX_VIDEO_AVCLOOPFILTERTYPE; + + +/** + * AVC params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nSliceHeaderSpacing : Number of macroblocks between slice header, put + * zero if not used + * nPFrames : Number of P frames between each I frame + * nBFrames : Number of B frames between each I frame + * bUseHadamard : Enable/disable Hadamard transform + * nRefFrames : Max number of reference frames to use for inter + * motion search (1-16) + * nRefIdxTrailing : Pic param set ref frame index (index into ref + * frame buffer of trailing frames list), B frame + * support + * nRefIdxForward : Pic param set ref frame index (index into ref + * frame buffer of forward frames list), B frame + * support + * bEnableUEP : Enable/disable unequal error protection. This + * is only valid of data partitioning is enabled. + * bEnableFMO : Enable/disable flexible macroblock ordering + * bEnableASO : Enable/disable arbitrary slice ordering + * bEnableRS : Enable/disable sending of redundant slices + * eProfile : AVC profile(s) to use + * eLevel : AVC level(s) to use + * nAllowedPictureTypes : Specifies the picture types allowed in the + * bitstream + * bFrameMBsOnly : specifies that every coded picture of the + * coded video sequence is a coded frame + * containing only frame macroblocks + * bMBAFF : Enable/disable switching between frame and + * field macroblocks within a picture + * bEntropyCodingCABAC : Entropy decoding method to be applied for the + * syntax elements for which two descriptors appear + * in the syntax tables + * bWeightedPPrediction : Enable/disable weighted prediction shall not + * be applied to P and SP slices + * nWeightedBipredicitonMode : Default weighted prediction is applied to B + * slices + * bconstIpred : Enable/disable intra prediction + * bDirect8x8Inference : Specifies the method used in the derivation + * process for luma motion vectors for B_Skip, + * B_Direct_16x16 and B_Direct_8x8 as specified + * in subclause 8.4.1.2 of the AVC spec + * bDirectSpatialTemporal : Flag indicating spatial or temporal direct + * mode used in B slice coding (related to + * bDirect8x8Inference) . Spatial direct mode is + * more common and should be the default. + * nCabacInitIdx : Index used to init CABAC contexts + * eLoopFilterMode : Enable/disable loop filter + */ +typedef struct OMX_VIDEO_PARAM_AVCTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nSliceHeaderSpacing; + OMX_U32 nPFrames; + OMX_U32 nBFrames; + OMX_BOOL bUseHadamard; + OMX_U32 nRefFrames; + OMX_U32 nRefIdx10ActiveMinus1; + OMX_U32 nRefIdx11ActiveMinus1; + OMX_BOOL bEnableUEP; + OMX_BOOL bEnableFMO; + OMX_BOOL bEnableASO; + OMX_BOOL bEnableRS; + OMX_VIDEO_AVCPROFILETYPE eProfile; + OMX_VIDEO_AVCLEVELTYPE eLevel; + OMX_U32 nAllowedPictureTypes; + OMX_BOOL bFrameMBsOnly; + OMX_BOOL bMBAFF; + OMX_BOOL bEntropyCodingCABAC; + OMX_BOOL bWeightedPPrediction; + OMX_U32 nWeightedBipredicitonMode; + OMX_BOOL bconstIpred ; + OMX_BOOL bDirect8x8Inference; + OMX_BOOL bDirectSpatialTemporal; + OMX_U32 nCabacInitIdc; + OMX_VIDEO_AVCLOOPFILTERTYPE eLoopFilterMode; +} OMX_VIDEO_PARAM_AVCTYPE; + +typedef struct OMX_VIDEO_PARAM_PROFILELEVELTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 eProfile; /**< type is OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE, + or OMX_VIDEO_MPEG4PROFILETYPE depending on context */ + OMX_U32 eLevel; /**< type is OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE, + or OMX_VIDEO_MPEG4PROFILETYPE depending on context */ + OMX_U32 nProfileIndex; /**< Used to query for individual profile support information, + This parameter is valid only for + OMX_IndexParamVideoProfileLevelQuerySupported index, + For all other indices this parameter is to be ignored. */ +} OMX_VIDEO_PARAM_PROFILELEVELTYPE; + +/** + * Structure for dynamically configuring bitrate mode of a codec. + * + * STRUCT MEMBERS: + * nSize : Size of the struct in bytes + * nVersion : OMX spec version info + * nPortIndex : Port that this struct applies to + * nEncodeBitrate : Target average bitrate to be generated in bps + */ +typedef struct OMX_VIDEO_CONFIG_BITRATETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nEncodeBitrate; +} OMX_VIDEO_CONFIG_BITRATETYPE; + +/** + * Defines Encoder Frame Rate setting + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * xEncodeFramerate : Encoding framerate represented in Q16 format + */ +typedef struct OMX_CONFIG_FRAMERATETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 xEncodeFramerate; /* Q16 format */ +} OMX_CONFIG_FRAMERATETYPE; + +typedef struct OMX_CONFIG_INTRAREFRESHVOPTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL IntraRefreshVOP; +} OMX_CONFIG_INTRAREFRESHVOPTYPE; + +typedef struct OMX_CONFIG_MACROBLOCKERRORMAPTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nErrMapSize; /* Size of the Error Map in bytes */ + OMX_U8 ErrMap[1]; /* Error map hint */ +} OMX_CONFIG_MACROBLOCKERRORMAPTYPE; + +typedef struct OMX_CONFIG_MBERRORREPORTINGTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnabled; +} OMX_CONFIG_MBERRORREPORTINGTYPE; + +typedef struct OMX_PARAM_MACROBLOCKSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nMacroblocks; +} OMX_PARAM_MACROBLOCKSTYPE; + +/** + * AVC Slice Mode modes + * + * OMX_VIDEO_SLICEMODE_AVCDefault : Normal frame encoding, one slice per frame + * OMX_VIDEO_SLICEMODE_AVCMBSlice : NAL mode, number of MBs per frame + * OMX_VIDEO_SLICEMODE_AVCByteSlice : NAL mode, number of bytes per frame + */ +typedef enum OMX_VIDEO_AVCSLICEMODETYPE { + OMX_VIDEO_SLICEMODE_AVCDefault = 0, + OMX_VIDEO_SLICEMODE_AVCMBSlice, + OMX_VIDEO_SLICEMODE_AVCByteSlice, + OMX_VIDEO_SLICEMODE_AVCKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_SLICEMODE_AVCVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_SLICEMODE_AVCLevelMax = 0x7FFFFFFF +} OMX_VIDEO_AVCSLICEMODETYPE; + +/** + * AVC FMO Slice Mode Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nNumSliceGroups : Specifies the number of slice groups + * nSliceGroupMapType : Specifies the type of slice groups + * eSliceMode : Specifies the type of slice + */ +typedef struct OMX_VIDEO_PARAM_AVCSLICEFMO { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U8 nNumSliceGroups; + OMX_U8 nSliceGroupMapType; + OMX_VIDEO_AVCSLICEMODETYPE eSliceMode; +} OMX_VIDEO_PARAM_AVCSLICEFMO; + +/** + * AVC IDR Period Configs + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nIDRPeriod : Specifies periodicity of IDR frames + * nPFrames : Specifies internal of coding Intra frames + */ +typedef struct OMX_VIDEO_CONFIG_AVCINTRAPERIOD { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nIDRPeriod; + OMX_U32 nPFrames; +} OMX_VIDEO_CONFIG_AVCINTRAPERIOD; + +/** + * AVC NAL Size Configs + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nNaluBytes : Specifies the NAL unit size + */ +typedef struct OMX_VIDEO_CONFIG_NALSIZE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nNaluBytes; +} OMX_VIDEO_CONFIG_NALSIZE; + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ + diff --git a/mm-core/inc/QCMediaDefs.h b/mm-core/inc/QCMediaDefs.h new file mode 100644 index 0000000..62ab60a --- /dev/null +++ b/mm-core/inc/QCMediaDefs.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012 - 2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef QC_MEDIA_DEFS_H_ + +#define QC_MEDIA_DEFS_H_ + +namespace android { + +extern const char *MEDIA_MIMETYPE_AUDIO_EVRC; +extern const char *MEDIA_MIMETYPE_VIDEO_WMV; +extern const char *MEDIA_MIMETYPE_AUDIO_WMA; +extern const char *MEDIA_MIMETYPE_CONTAINER_ASF; +extern const char *MEDIA_MIMETYPE_VIDEO_DIVX; +extern const char *MEDIA_MIMETYPE_AUDIO_AC3; +extern const char *MEDIA_MIMETYPE_CONTAINER_AAC; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCP; +extern const char *MEDIA_MIMETYPE_VIDEO_DIVX311; +extern const char *MEDIA_MIMETYPE_VIDEO_DIVX4; +extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2; +extern const char *MEDIA_MIMETYPE_CONTAINER_3G2; +extern const char *MEDIA_MIMETYPE_AUDIO_DTS; +extern const char *MEDIA_MIMETYPE_AUDIO_DTS_LBR; +extern const char *MEDIA_MIMETYPE_AUDIO_EAC3; +extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG2TS; +extern const char *MEDIA_MIMETYPE_VIDEO_HEVC; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_NB; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_WB; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCWAV; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCFLV; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG2PS; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG4; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCMATROSKA; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCOGG; +extern const char *MEDIA_MIMETYPE_CONTAINER_QTIFLAC; +} // namespace android + +#endif //QC_MEDIA_DEFS_H_ diff --git a/mm-core/inc/QCMetaData.h b/mm-core/inc/QCMetaData.h new file mode 100644 index 0000000..fe0799b --- /dev/null +++ b/mm-core/inc/QCMetaData.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef QC_META_DATA_H_ + +#define QC_META_DATA_H_ + +namespace android { + +enum { + kKeyAacCodecSpecificData = 'nacc' , // for native aac files + +#if 0 + kKeyRawCodecSpecificData = 'rcsd', // raw data - added to support mmParser + kKeyDivXVersion = 'DivX', // int32_t + kKeyDivXDrm = 'QDrm', // void * + kKeyWMAEncodeOpt = 'eopt', // int32_t + kKeyWMABlockAlign = 'blka', // int32_t + kKeyWMAVersion = 'wmav', // int32_t + kKeyWMAAdvEncOpt1 = 'ade1', // int16_t + kKeyWMAAdvEncOpt2 = 'ade2', // int32_t + kKeyWMAFormatTag = 'fmtt', // int64_t + kKeyWMABitspersample = 'bsps', // int64_t + kKeyWMAVirPktSize = 'vpks', // int64_t +#endif + kKeyWMAChannelMask = 'chmk', // int32_t + + kKeyFileFormat = 'ffmt', // cstring + + kkeyAacFormatAdif = 'adif', // bool (int32_t) + kKeyInterlace = 'intL', // bool (int32_t) + kkeyAacFormatLtp = 'ltp', + + + //DTS subtype + kKeyDTSSubtype = 'dtss', //int32_t + + //Extractor sets this + kKeyUseArbitraryMode = 'ArbM', //bool (int32_t) + kKeySmoothStreaming = 'ESmS', //bool (int32_t) + kKeyHFR = 'hfr ', // int32_t + kKeyHSR = 'hsr ', // int32_t + + kKeyMinBlkSize = 'mibs', //int32_t + kKeyMaxBlkSize = 'mabs', //int32_t + kKeyMinFrmSize = 'mifs', //int32_t + kKeyMaxFrmSize = 'mafs', //int32_t + kKeyMd5Sum = 'md5s', //cstring +}; + +#if 0 +enum { + kTypeDivXVer_3_11, + kTypeDivXVer_4, + kTypeDivXVer_5, + kTypeDivXVer_6, +}; +enum { + kTypeWMA, + kTypeWMAPro, + kTypeWMALossLess, +}; +#endif + +} // namespace android + +#endif // QC_META_DATA_H_ diff --git a/mm-core/inc/QOMX_AudioExtensions.h b/mm-core/inc/QOMX_AudioExtensions.h new file mode 100755 index 0000000..68027b5 --- /dev/null +++ b/mm-core/inc/QOMX_AudioExtensions.h @@ -0,0 +1,511 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, 2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + +*//** @file QOMX_AudioExtensions.h + This module contains the extensions for Audio + +*//*========================================================================*/ + +#ifndef __H_QOMX_AUDIOEXTENSIONS_H__ +#define __H_QOMX_AUDIOEXTENSIONS_H__ + +/*======================================================================== + + INCLUDE FILES FOR MODULE + +========================================================================== */ +#include + +/*======================================================================== + + DEFINITIONS AND DECLARATIONS + +========================================================================== */ + +#if defined( __cplusplus ) +extern "C" +{ +#endif /* end of macro __cplusplus */ + +/* Audio extension strings */ +#define OMX_QCOM_INDEX_PARAM_AMRWBPLUS "OMX.Qualcomm.index.audio.amrwbplus" +#define OMX_QCOM_INDEX_PARAM_WMA10PRO "OMX.Qualcomm.index.audio.wma10pro" +#define OMX_QCOM_INDEX_PARAM_SESSIONID "OMX.Qualcomm.index.audio.sessionId" +#define OMX_QCOM_INDEX_PARAM_VOICERECORDTYPE "OMX.Qualcomm.index.audio.VoiceRecord" +#define OMX_QCOM_INDEX_PARAM_AC3TYPE "OMX.Qualcomm.index.audio.ac3" +#define OMX_QCOM_INDEX_PARAM_AC3PP "OMX.Qualcomm.index.audio.postproc.ac3" +#define OMX_QCOM_INDEX_PARAM_DAK_BUNDLE "OMX.Qualcomm.index.audio.dakbundle" +#define OMX_QCOM_INDEX_PARAM_DAK_M2S "OMX.Qualcomm.index.audio.dak_m2s" +#define OMX_QCOM_INDEX_PARAM_DAK_SSE "OMX.Qualcomm.index.audio.dak_sse" +#define OMX_QCOM_INDEX_PARAM_DAK_SLC "OMX.Qualcomm.index.audio.dak_slc" +#define OMX_QCOM_INDEX_PARAM_DAK_VOL "OMX.Qualcomm.index.audio.dak_vol" +#define OMX_QCOM_INDEX_PARAM_DAK_NB "OMX.Qualcomm.index.audio.dak_nb" +#define OMX_QCOM_INDEX_PARAM_DAK_GEQ "OMX.Qualcomm.index.audio.dak_geq" +#define OMX_QCOM_INDEX_PARAM_DAK_MSR "OMX.Qualcomm.index.audio.dak_msr" +#define OMX_QCOM_INDEX_PARAM_DAK_HFE "OMX.Qualcomm.index.audio.dak_hfe" +#define OMX_QCOM_INDEX_PARAM_DAK_FADE "OMX.Qualcomm.index.audio.dak_fade" +#define OMX_QCOM_INDEX_PARAM_DAK_SEQ "OMX.Qualcomm.index.audio.dak_seq" +#define OMX_QCOM_INDEX_CONFIG_DUALMONO "OMX.Qualcomm.index.audio.dualmono" + +typedef enum QOMX_AUDIO_AMRBANDMODETYPE { + QOMX_AUDIO_AMRBandModeWB9 = 0x7F000001,/**< AMRWB Mode 9 = SID*/ + QOMX_AUDIO_AMRBandModeWB10 = 0x7F000002,/**< AMRWB Mode 10 = 13600 bps */ + QOMX_AUDIO_AMRBandModeWB11 = 0x7F000003,/**< AMRWB Mode 11 = 18000 bps */ + QOMX_AUDIO_AMRBandModeWB12 = 0x7F000004,/**< AMRWB Mode 12 = 24000 bps */ + QOMX_AUDIO_AMRBandModeWB13 = 0x7F000005,/**< AMRWB Mode 13 = 24000 bps */ + QOMX_AUDIO_AMRBandModeWB14 = 0x7F000006,/**< AMRWB Mode 14 = FRAME_ERASE*/ + QOMX_AUDIO_AMRBandModeWB15 = 0x7F000007,/**< AMRWB Mode 15 = NO_DATA */ +}QOMX_AUDIO_AMRBANDMODETYPE; + +typedef enum QOMX_AUDIO_CODINGTYPE { + QOMX_AUDIO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + QOMX_AUDIO_CodingEVRCB = 0x7F000001, + QOMX_AUDIO_CodingEVRCWB = 0x7F000002, + QOMX_AUDIO_CodingFLAC = 0x7F000003, + QOMX_AUDIO_CodingMax = 0x7FFFFFFF +}QOMX_AUDIO_CODINGTYPE; + + +/** + * AMR WB PLUS type + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nChannels : Number of channels + * nBitRate : Bit rate read only field + * nSampleRate : Sampling frequency for the clip(16/24/32/48KHz) + * eAMRBandMode : AMR Band Mode enumeration + * eAMRDTXMode : AMR DTX Mode enumeration + * eAMRFrameFormat : AMR frame format enumeration + */ + +typedef struct QOMX_AUDIO_PARAM_AMRWBPLUSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nChannels; + OMX_U32 nBitRate; + OMX_U32 nSampleRate; + OMX_AUDIO_AMRBANDMODETYPE eAMRBandMode; + OMX_AUDIO_AMRDTXMODETYPE eAMRDTXMode; + OMX_AUDIO_AMRFRAMEFORMATTYPE eAMRFrameFormat; +} QOMX_AUDIO_PARAM_AMRWBPLUSTYPE; + +typedef enum QOMX_AUDIO_WMAFORMATTYPE { + QOMX_AUDIO_WMAFormat10Pro = 0x7F000001, /**< Windows Media Audio format 10*/ +} QOMX_AUDIO_WMAFORMATTYPE; + +/** + * WMA 10 PRO type + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nChannels : Number of channels + * nBitRate : Bit rate read only field + * eFormat : Version of WMA stream / data + * eProfile : Profile of WMA stream / data + * nSamplingRate : Sampling rate of the source data + * nBlockAlign : block alignment, or block size, in bytes of the audio codec + * nEncodeOptions : WMA Type-specific data + * nSuperBlockAlign : WMA Type-specific data + * validBitsPerSample : encoded stream (24-bit or 16-bit) + * formatTag : codec ID(0x162 or 0x166) + * advancedEncodeOpt : bit packed words indicating the features supported for LBR bitstream + * advancedEncodeOpt2 : bit packed words indicating the features supported for LBR bitstream + */ +typedef struct QOMX_AUDIO_PARAM_WMA10PROTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U16 nChannels; + OMX_U32 nBitRate; + QOMX_AUDIO_WMAFORMATTYPE eFormat; + OMX_AUDIO_WMAPROFILETYPE eProfile; + OMX_U32 nSamplingRate; + OMX_U16 nBlockAlign; + OMX_U16 nEncodeOptions; + OMX_U32 nSuperBlockAlign; + OMX_U32 validBitsPerSample; + OMX_U32 formatTag; + OMX_U32 advancedEncodeOpt; + OMX_U32 advancedEncodeOpt2; + OMX_U16 nVirtualPktSize; +} QOMX_AUDIO_PARAM_WMA10PROTYPE; + + +typedef enum OMX_AUDIO_AC3FORMATTYPE { + omx_audio_ac3 = 0x7f000001, /**< ac-3 */ + omx_audio_eac3 = 0x7f000002 /**< eac-3 */ +} OMX_AUDIO_AC3FORMATTYPE; + +typedef enum OMX_AUDIO_AC3_CHANNEL_CONFIG +{ + OMX_AUDIO_AC3_CHANNEL_CONFIG_RSVD = 0, + OMX_AUDIO_AC3_CHANNEL_CONFIG_1_0, + OMX_AUDIO_AC3_CHANNEL_CONFIG_2_0, + OMX_AUDIO_AC3_CHANNEL_CONFIG_3_0, + OMX_AUDIO_AC3_CHANNEL_CONFIG_2_1, + OMX_AUDIO_AC3_CHANNEL_CONFIG_3_1, + OMX_AUDIO_AC3_CHANNEL_CONFIG_2_2, + OMX_AUDIO_AC3_CHANNEL_CONFIG_3_2, + OMX_AUDIO_AC3_CHANNEL_CONFIG_3_0_1, + OMX_AUDIO_AC3_CHANNEL_CONFIG_2_2_1, + OMX_AUDIO_AC3_CHANNEL_CONFIG_3_2_1, + OMX_AUDIO_AC3_CHANNEL_CONFIG_3_0_2, + OMX_AUDIO_AC3_CHANNEL_CONFIG_2_2_2, + OMX_AUDIO_AC3_CHANNEL_CONFIG_3_2_2, + OMX_AUDIO_AC3_CHANNEL_CONFIG_DEFAULT = 0xFFFF +} OMX_AUDIO_AC3_CHANNEL_CONFIG; + +/** + * AC-3 type + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nChannels : Number of channels + * nBitRate : Bitrate + * nSamplingRate : Sampling rate, 32K, 44.1K, 48K only supported + * eFormat : AC-3 or EAC-3 + * eChannelConfig : Channel configuration + * nProgramID : Indication of ProgramID, 0-7 + * bCompressionOn : Flag to enable Compression + * bLfeOn : Flag for LFE on/off + * bDelaySurroundChannels : Flag to put delay on surround channels + * + */ +typedef struct QOMX_AUDIO_PARAM_AC3TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U16 nChannels; + OMX_U32 nBitRate; + OMX_U32 nSamplingRate; + OMX_AUDIO_AC3FORMATTYPE eFormat; + OMX_AUDIO_AC3_CHANNEL_CONFIG eChannelConfig; + OMX_U8 nProgramID; + OMX_BOOL bCompressionOn; + OMX_BOOL bLfeOn; + OMX_BOOL bDelaySurroundChannels; +} QOMX_AUDIO_PARAM_AC3TYPE; + +typedef enum OMX_AUDIO_AC3_CHANNEL_ROUTING +{ + OMX_AUDIO_AC3_CHANNEL_LEFT, + OMX_AUDIO_AC3_CHANNEL_CENTER, + OMX_AUDIO_AC3_CHANNEL_RIGHT, + OMX_AUDIO_AC3_CHANNEL_LEFT_SURROUND, + OMX_AUDIO_AC3_CHANNEL_RIGHT_SURROUND, + OMX_AUDIO_AC3_CHANNEL_SURROUND, + OMX_AUDIO_AC3_CHANNEL_EXTENSION_1, + OMX_AUDIO_AC3_CHANNEL_EXTENSION_2, + OMX_AUDIO_AC3_CHANNEL_DEFAULT = 0xFFFF +} OMX_AUDIO_AC3_CHANNEL_ROUTING; + +typedef enum OMX_AUDIO_AC3_COMPRESSION_MODE +{ + OMX_AUDIO_AC3_COMPRESSION_MODE_ANALOG_DIALNORM, + OMX_AUDIO_AC3_COMPRESSION_MODE_DIGITAL_DIALNORM, + OMX_AUDIO_AC3_COMPRESSION_MODE_LINE_OUT, + OMX_AUDIO_AC3_COMPRESSION_MODE_RF_REMOD +} OMX_AUDIO_AC3_COMPRESSION_MODE; + +typedef enum OMX_AUDIO_AC3_STEREO_MODE +{ + OMX_AUDIO_AC3_STEREO_MODE_AUTO_DETECT, + OMX_AUDIO_AC3_STEREO_MODE_LT_RT, + OMX_AUDIO_AC3_STEREO_MODE_LO_RO, + OMX_AUDIO_AC3_STEREO_MODE_DEFAULT = 0xFFFF +} OMX_AUDIO_AC3_STEREO_MODE; + +typedef enum OMX_AUDIO_AC3_DUAL_MONO_MODE +{ + OMX_AUDIO_AC3_DUAL_MONO_MODE_STEREO, + OMX_AUDIO_AC3_DUAL_MONO_MODE_LEFT_MONO, + OMX_AUDIO_AC3_DUAL_MONO_MODE_RIGHT_MONO, + OMX_AUDIO_AC3_DUAL_MONO_MODE_MIXED_MONO, + OMX_AUDIO_AC3_DUAL_MONO_MODE_DEFAULT = 0xFFFF +} OMX_AUDIO_AC3_DUAL_MONO_MODE; + +typedef enum OMX_AUDIO_AC3_KARAOKE_MODE +{ + OMX_AUDIO_AC3_KARAOKE_MODE_NO_VOCAL, + OMX_AUDIO_AC3_KARAOKE_MODE_LEFT_VOCAL, + OMX_AUDIO_AC3_KARAOKE_MODE_RIGHT_VOCAL, + OMX_AUDIO_AC3_KARAOKE_MODE_BOTH_VOCAL, + OMX_AUDIO_AC3_KARAOKE_MODE_DEFAULT = 0xFFFF +} OMX_AUDIO_AC3_KARAOKE_MODE; + + +typedef struct QOMX_AUDIO_PARAM_AC3PP +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_AUDIO_AC3_CHANNEL_ROUTING eChannelRouting[8]; + OMX_AUDIO_AC3_COMPRESSION_MODE eCompressionMode; + OMX_AUDIO_AC3_STEREO_MODE eStereoMode; + OMX_AUDIO_AC3_DUAL_MONO_MODE eDualMonoMode; + OMX_U32 usPcmScale; + OMX_U32 usDynamicScaleBoost; + OMX_U32 usDynamicScaleCut; + OMX_AUDIO_AC3_KARAOKE_MODE eKaraokeMode; +} QOMX_AUDIO_PARAM_AC3PP; + + +/** + * Stream info data + * + * STRUCT MEMBERS: + * sessionId : session Id for alsa to route data + */ +typedef struct QOMX_AUDIO_STREAM_INFO_DATA { + OMX_U8 sessionId; +} QOMX_AUDIO_STREAM_INFO_DATA; + + +/** + * Record Path + * + * STRUCT MEMBERS: + * recPath : Record Path for encoding + */ +typedef enum{ + +QOMX_AUDIO_VOICE_TX, +QOMX_AUDIO_VOICE_RX, +QOMX_AUDIO_VOICE_MIXED, + +} QOMX_AUDIO_VOICERECORDMODETYPE; +typedef struct QOMX_AUDIO_CONFIG_VOICERECORDTYPE { + +OMX_U32 nSize; +OMX_VERSIONTYPE nVersion; +QOMX_AUDIO_VOICERECORDMODETYPE eVoiceRecordMode; +} QOMX_AUDIO_CONFIG_VOICERECORDTYPE; + +/* Enum for mapping dual-mono contents to left and right channels */ +typedef enum OMX_AUDIO_DUAL_MONO_CHANNEL_CONFIG { + OMX_AUDIO_DUAL_MONO_MODE_FL_FR,/* 1st SCE to left & right */ + OMX_AUDIO_DUAL_MONO_MODE_SL_SR,/* 2nd SCE to left & right */ + OMX_AUDIO_DUAL_MONO_MODE_SL_FR,/* 2nd SCE to left, 1st SCE to right */ + OMX_AUDIO_DUAL_MONO_MODE_FL_SR,/* 1st SCE to left, 2nd SCE to right default */ + OMX_AUDIO_DUAL_MONO_MODE_DEFAULT = OMX_AUDIO_DUAL_MONO_MODE_FL_SR, + OMX_AUDIO_DUAL_MONO_MODE_INVALID = -1 +} OMX_AUDIO_DUAL_MONO_CHANNEL_CONFIG; + +/************************************/ +/* DAK */ +/*************************************/ + +/** this is the list of custom vendor index */ +typedef enum OMX_INDEX_DAK_TYPE { + OMX_IndexConfigDAK_BUNDLE = OMX_IndexVendorStartUnused /*0x7F000000*/, /**< reference: OMX_DAK_CONFIG_BUNDLETYPE */ + OMX_IndexConfigDAK_M2S, /**< reference: OMX_DAK_CONFIG_M2STYPE */ + OMX_IndexConfigDAK_SSE, /**< reference: OMX_DAK_CONFIG_SSETYPE */ + OMX_IndexConfigDAK_SLC, /**< reference: OMX_DAK_CONFIG_SLCTYPE */ + OMX_IndexConfigDAK_VOL, /**< reference: OMX_DAK_CONFIG_VOLTYPE */ + OMX_IndexConfigDAK_NB, /**< reference: OMX_DAK_CONFIG_NBTYPE */ + OMX_IndexConfigDAK_GEQ, /**< reference: OMX_DAK_CONFIG_GEQTYPE */ + OMX_IndexConfigDAK_MSR, /**< reference: OMX_DAK_CONFIG_MSRTYPE */ + OMX_IndexConfigDAK_HFE, /**< reference: OMX_DAK_CONFIG_HFETYPE */ + OMX_IndexConfigDAK_FADE,/**< reference: OMX_DAK_CONFIG_FADETYPE */ + OMX_IndexConfigDAK_SEQ, /**< reference: OMX_DAK_CONFIG_SEQTYPE */ + +} OMX_INDEX_DAK_TYPE; + + +/** Dolby Audio Kernel TDAS bundle */ +typedef struct OMX_DAK_CONFIG_BUNDLETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nDAK_Version; /**< Dolby Audio Kernel version information */ + OMX_U32 nDAK_Revision; /**< Dolby Audio Kernel revision information */ + OMX_U8 nLfeMixLevel; /**< level at which the LFE channel is mixed into the output audio */ + OMX_U8 nSampleRateIndex; /**< Output sample rate */ + OMX_U8 nInChans; /**< Channel format of input audio */ + OMX_U8 nInMatrix; /**< L/R mixing specification for stereo audio input */ + OMX_U8 nBypass; /**< Audio Processing bypass */ + OMX_U8 nRateMultipier; /**< Sample-rate multiplier (output with respect to input) */ + OMX_U8 nInChanFormat; /**< Input/Output channel format */ + OMX_U8 nMsrMaxProfile; /**< Maximum number of virtual rendering channels in Mobile Surround */ + OMX_BOOL bPortablemodeEnable; /**< Enable or disable Pulse Portable Mode */ + OMX_S16 nPotablemodeGain; /**< Send the Portable Mode gain value from the Pulse decoder */ + OMX_U8 nORL; /**< Device specific target signal level (output reference level) */ + OMX_BOOL bPulsedownmixEnable; /**< Enable the Pulse Downmix compensation */ + OMX_S8 nPulsedownmixAtten; /**< Attenuation value that Pulse is currently applying */ + OMX_U8 nOutChans; /**< Channel format of output audio */ + +} OMX_DAK_CONFIG_BUNDLETYPE; + +/** Dolby Audio Kernel Mono-to-Stereo Creator */ +typedef struct OMX_DAK_CONFIG_M2STYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bEnable; /**< Mono-to-Stereo Creator enable */ + OMX_BOOL bDetector; /**< Stereo detector status */ +} OMX_DAK_CONFIG_M2STYPE; + +/** Dolby Audio Kernel Sound Space Expander */ +typedef struct OMX_DAK_CONFIG_SSETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bEnable; /**< Sound Space Expander enable */ + OMX_U8 nWidth; /**< Width of expansion effect */ + OMX_U8 nSpkMode; /**< Speaker Mode */ +} OMX_DAK_CONFIG_SSETYPE; + +/** Dolby Audio Kernel Sound Level Controller */ +typedef struct OMX_DAK_CONFIG_SLCTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bEnable; /**< Sound Level Controller enable */ + OMX_U8 nLevel; /**< Source audio RMS level */ + OMX_U8 nDepth; /**< Depth of effect */ +} OMX_DAK_CONFIG_SLCTYPE; + +/** Dolby Audio Kernel Volume */ +typedef struct OMX_DAK_CONFIG_VOLTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bEnable; /**< Volume enable */ + OMX_U8 nGainType; /**< Linear/Logarithmic audio scaling */ + OMX_U8 nInternalGain; /**< Audio volume scale */ + OMX_U8 nExternalGain; /**< Audio volume scale applied by external volume control */ + OMX_S8 nBalance; /**< L/R panning for output audio */ + OMX_BOOL bMute; /**< Audio Mute */ +} OMX_DAK_CONFIG_VOLTYPE; + +/** Dolby Audio Kernel Natural Bass */ +typedef struct OMX_DAK_CONFIG_NBTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bEnable; /**< Natural Bass enable */ + OMX_U8 nCutoff; /**< Speakers/headphones lower cutoff frequency */ + OMX_U8 nBoost; /**< Strength of effect */ + OMX_U8 nLevel; /**< Maximum output level capability of speakers/headphones */ +} OMX_DAK_CONFIG_NBTYPE; + +/** Dolby Audio Kernel Graphic EQ */ +typedef struct OMX_DAK_CONFIG_GEQTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bEnable; /**< Graphic EQ enable */ + OMX_U8 nNbands; /**< Number of frequency bands */ + OMX_S8 nPreamp; /**< Global attenuation to apply prior to band level adjustment */ + OMX_U8 nMaxboost; /**< Maximum absolute boost with respect to the source audio */ + OMX_S8 nBand1; /**< Boost/cut for 1st frequency band */ + OMX_S8 nBand2; /**< Boost/cut for 2nd frequency band */ + OMX_S8 nBand3; /**< Boost/cut for 3rd frequency band */ + OMX_S8 nBand4; /**< Boost/cut for 4th frequency band */ + OMX_S8 nBand5; /**< Boost/cut for 5th frequency band */ + OMX_S8 nBand6; /**< Boost/cut for 6th frequency band */ + OMX_S8 nBand7; /**< Boost/cut for 7th frequency band */ +} OMX_DAK_CONFIG_GEQTYPE; + +/** Dolby Audio Kernel, Mobile Surround and Surround Upmixer */ +typedef struct OMX_DAK_CONFIG_MSRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bMsrEnable; /**< Mobile Surround enable */ + OMX_U8 nMsrRoom; /**< Room Size control */ + OMX_U8 nMsrBright; /**< Brightness control */ + OMX_BOOL bMupEnable; /**< Mobile Surround Upmixer enable */ +} OMX_DAK_CONFIG_MSRTYPE; + +/** Dolby Audio Kernel High Frequency Enhancer */ +typedef struct OMX_DAK_CONFIG_HFETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bEnable; /**< High Frequency Enhancer enable */ + OMX_U8 nDepth; /**< Strength of effect */ +} OMX_DAK_CONFIG_HFETYPE; + +/** Dolby Audio Kernel Fade */ +typedef struct OMX_DAK_CONFIG_FADETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bEnable; /**< Fade enable */ + OMX_U8 nTarget; /**< Target fade level */ + OMX_U16 nTime; /**< Fade time interval */ +} OMX_DAK_CONFIG_FADETYPE; + +/** Dolby Audio Kernel Speaker EQ */ +typedef struct OMX_DAK_CONFIG_SEQTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bEnable; /**< Speaker EQ enable */ + OMX_S8 nLeftGainDB; /**< Additional gain for Left channel */ + OMX_S8 nRightGainDB; /**< Additional gain for Right channel */ + OMX_U8 nCoef48000Size; /**< Length of the block of coefficients for 48KHz Sampling Rate case */ + OMX_PTR pCoef48000; /**< Pointer to the block of coefficients for the 48KHz case */ + OMX_U8 nCoef44100Size; /**< Length of the block of coefficients for 44.1KHz Sampling Rate case */ + OMX_PTR pCoef44100; /**< Pointer to the block of coefficients for the 44.1KHz case */ + OMX_U8 nCoef32000Size; /**< Length of the block of coefficients for 32KHz Sampling Rate case */ + OMX_PTR pCoef32000; /**< Pointer to the block of coefficients for the 32KHz case */ + OMX_U8 nCoef24000Size; /**< Length of the block of coefficients for 24KHz Sampling Rate case */ + OMX_PTR pCoef24000; /**< Pointer to the block of coefficients for the 24KHz case */ + +} OMX_DAK_CONFIG_SEQTYPE; + + +typedef enum OMX_AUDIO_CHANNELTYPE_EXTENSION { + OMX_AUDIO_ChannelTS = OMX_AUDIO_ChannelVendorStartUnused, /**< Top Surround */ + OMX_AUDIO_ChannelCVH /**< Central Vertical Height */ +} OMX_AUDIO_CHANNELTYPE_EXTENSION; + +/** + * DUAL-MONO type + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eChannelConfig : Enum for channel config + * + */ +typedef struct QOMX_AUDIO_CONFIG_DUALMONOTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_AUDIO_DUAL_MONO_CHANNEL_CONFIG eChannelConfig; +} QOMX_AUDIO_CONFIG_DUALMONOTYPE; + +#if defined( __cplusplus ) +} +#endif /* end of macro __cplusplus */ + +#endif /* end of macro __H_QOMX_AUDIOEXTENSIONS_H__ */ diff --git a/mm-core/inc/QOMX_AudioIndexExtensions.h b/mm-core/inc/QOMX_AudioIndexExtensions.h new file mode 100755 index 0000000..4c07970 --- /dev/null +++ b/mm-core/inc/QOMX_AudioIndexExtensions.h @@ -0,0 +1,80 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + +*//** @file QOMX_AudioIndexExtensions.h + This module contains the index extensions for Audio + +*//*========================================================================*/ + + +#ifndef __H_QOMX_AUDIOINDEXEXTENSIONS_H__ +#define __H_QOMX_AUDIOINDEXEXTENSIONS_H__ + +/*======================================================================== + + INCLUDE FILES FOR MODULE + +========================================================================== */ +#include + +/*======================================================================== + + DEFINITIONS AND DECLARATIONS + +========================================================================== */ + +#if defined( __cplusplus ) +extern "C" +{ +#endif /* end of macro __cplusplus */ + +/** + * Enumeration used to define Qualcomm's vendor extensions for + * audio. The audio extensions occupy a range of + * 0x7F100000-0x7F1FFFFF, inclusive. + */ +typedef enum QOMX_AUDIO_EXTENSIONS_INDEXTYPE +{ + QOMX_IndexParamAudioAmrWbPlus = 0x7F200000, /**< "OMX.Qualcomm.index.audio.amrwbplus" */ + QOMX_IndexParamAudioWma10Pro = 0x7F200001, /**< "OMX.Qualcomm.index.audio.wma10pro" */ + QOMX_IndexParamAudioSessionId = 0x7F200002, /**< "OMX.Qualcomm.index.audio.sessionId" */ + QOMX_IndexParamAudioVoiceRecord = 0x7F200003, /**< "OMX.Qualcomm.index.audio.VoiceRecord" */ + QOMX_IndexConfigAudioDualMono = 0x7F200004, /**< "OMX.Qualcomm.index.audio.dualmono" */ + QOMX_IndexParamAudioAc3 = 0x7F200005, /**< "OMX.Qualcomm.index.audio.ac3" */ + QOMX_IndexParamAudioAc3PostProc = 0x7F200006, /**< "OMX.Qualcomm.index.audio.postproc.ac3" */ + QOMX_IndexParamAudioUnused = 0x7F2FFFFF +} QOMX_AUDIO_EXTENSIONS_INDEXTYPE; + +#if defined( __cplusplus ) +} +#endif /* end of macro __cplusplus */ + +#endif /* end of macro __H_QOMX_AUDIOINDEXEXTENSIONS_H__ */ diff --git a/mm-core/inc/QOMX_CoreExtensions.h b/mm-core/inc/QOMX_CoreExtensions.h new file mode 100755 index 0000000..772a5fd --- /dev/null +++ b/mm-core/inc/QOMX_CoreExtensions.h @@ -0,0 +1,164 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2011 Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#ifndef __H_QOMX_COREEXTENSIONS_H__ +#define __H_QOMX_COREEXTENSIONS_H__ + + + +/*======================================================================== + + INCLUDE FILES FOR MODULE + +========================================================================== */ +#include + +/*======================================================================== + + DEFINITIONS AND DECLARATIONS + +========================================================================== */ + +#if defined( __cplusplus ) +extern "C" +{ +#endif /* end of macro __cplusplus */ + +/** + * Qualcom vendor extensions. + */ +#define OMX_QCOM_INDEX_PARAM_INDEXEXTRADATA "OMX.QCOM.index.param.IndexExtraData" /**< reference: QOMX_INDEXEXTRADATATYPE */ +#define OMX_QCOM_INDEX_PARAM_HELDBUFFERCOUNT "OMX.QCOM.index.param.HeldBufferCount" /**< reference: QOMX_HELDBUFFERCOUNTTYPE */ + +/** + * Buffer header nFlags field extension. + * + * The source of a stream sets the TIMESTAMPINVALID flag to + * indicate that the buffer header nTimeStamp field does not + * hold valid timestamp information. The component that updates + * the nTimeStamp field to reflect a valid timestamp shall clear + * this flag. + */ +#define QOMX_BUFFERFLAG_TIMESTAMPINVALID 0x80000000 + +/** + * Buffer header nFlags field extension. + * + * The READONLY flag is set when the component emitting the + * buffer on an output port identifies the buffer's contents to + * be read-only. The IL client or input port that receives a + * filled read-only buffer cannot alter the contents of the + * buffer. This flag can be cleared by the component when the + * emptied buffer is returned to it. + */ +#define QOMX_BUFFERFLAG_READONLY 0x40000000 + +/** + * Buffer header nFlags field extension. + * + * The ENDOFSUBFRAME flag is an optional flag that is set by an + * output port when the last byte that a buffer payload contains + * is an end-of-subframe. Any component that implements setting + * the ENDOFSUBFRAME flag on an output port shall set this flag + * for every buffer sent from the output port containing an + * end-of-subframe. + * + * A subframe is defined by the next level of natural + * partitioning in a logical unit for a given format. For + * example, a subframe in an H.264 access unit is defined as the + * "network abstraction layer" unit, or NAL unit. + */ +#define QOMX_BUFFERFLAG_ENDOFSUBFRAME 0x20000000 + +/** + * A component sends this error to the IL client (via the EventHandler callback) + * in the event that application of a config or parameter has failed some time + * after the return of OMX_SetConfig or OMX_SetParameter. This may happen when a + * component transitions between states and discovers some incompatibility + * between multiple settings. Configuration indicies sent via extra data may also + * fail when set to a down stream component. The index that failed will be + * included as the nData2 parameter of the EventHandler callback. + */ +#define QOMX_ErrorAsyncIndexFailed (OMX_ErrorVendorStartUnused+1) + +/* In some scenarios there may be a possibilty to run out of the storage space + * and components may want to notify this error to IL client to take appropriate + * action by the IL client. + * + * For example, In recording scenario, MUX component can know the available + * space in the recording media and can compute peridically to accommodate the + * meta data before we reach to a stage where we end up no space to write even + * the meta data. When the space limit reached in recording media, MUX component + * would like to notify the IL client with QOMX_ErrorSpaceLimitReached. + * After this error all the buffers that are returned will have nFilledLen + * unchanges i.e not consumed. + */ +#define QOMX_ErrorStorageLimitReached (OMX_ErrorVendorStartUnused + 2) + +/** + * This structure is used to enable/disable the generation or + * consumption of the QOMX_ExtraDataOMXIndex extra data type for + * the specified OpenMax index. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * bEnabled : Enable/Disable the extra data processing + * nIndex : The index associated with the extra data + */ +typedef struct QOMX_INDEXEXTRADATATYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnabled; + OMX_INDEXTYPE nIndex; +} QOMX_INDEXEXTRADATATYPE; + +/** + * This structure is used to indicate the maximum number of buffers + * that a port will hold during data flow. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * nHeldBufferCount : Read-only, maximum number of buffers that will be held + */ +typedef struct QOMX_HELDBUFFERCOUNTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nHeldBufferCount; +} QOMX_HELDBUFFERCOUNTTYPE; + +#if defined( __cplusplus ) +} +#endif /* end of macro __cplusplus */ + +#endif /* end of macro __H_QOMX_COREEXTENSIONS_H__ */ diff --git a/mm-core/inc/QOMX_FileFormatExtensions.h b/mm-core/inc/QOMX_FileFormatExtensions.h new file mode 100755 index 0000000..3488943 --- /dev/null +++ b/mm-core/inc/QOMX_FileFormatExtensions.h @@ -0,0 +1,137 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2011 Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#ifndef __QOMX_FILE_FORMAT_EXTENSIONS_H__ +#define __QOMX_FILE_FORMAT_EXTENSIONS_H__ + +/*============================================================================ +*//** @file QOMX_FileFormatExtensions.h + This header contains constants and type definitions that specify the + extensions added to the OpenMAX Vendor specific APIs. +*//*========================================================================*/ + +/*============================================================================ + Edit History + +when who what, where, why +-------- --- ------------------------------------------------------- + +============================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// +#include "OMX_Core.h" + + +/* :OMX.QCOM.index.param.container.info*/ +#define QOMX_QcomIndexParamContainerInfo 0x7F000009 + +#define QOMX_INDEX_CONTAINER_INFO_STRING "QOMX.Qualcomm.index.param.containerinfo" +#define OMX_QCOM_INDEX_FILE_FORMAT "OMX.QCOM.index.config.FileFormat" + +/**----------------------------------------------------------------------------- + OMX.QCOM.index.param.container.info +-------------------------------------------------------------------------------- +*/ + +typedef enum QOMX_CONTAINER_FORMATTYPE { + QOMX_FORMAT_RAW, + QOMX_FORMAT_MP4, + QOMX_FORMAT_3GP, + QOMX_FORMAT_3G2, + QOMX_FORMAT_AMC, + QOMX_FORMAT_SKM, + QOMX_FORMAT_K3G, + QOMX_FORMAT_VOB, + QOMX_FORMAT_AVI, + QOMX_FORMAT_ASF, + QOMX_FORMAT_RM , + QOMX_FORMAT_MPEG_ES, + QOMX_FORMAT_DIVX, + QOMX_FORMATMPEG_TS, + QOMX_FORMAT_QT, + QOMX_FORMAT_M4A, + QOMX_FORMAT_MP3, + QOMX_FORMAT_WAVE, + QOMX_FORMAT_XMF, + QOMX_FORMAT_AMR, + QOMX_FORMAT_AAC, + QOMX_FORMAT_EVRC, + QOMX_FORMAT_QCP, + QOMX_FORMAT_SMF, + QOMX_FORMAT_OGG, + QOMX_FORMAT_BMP, + QOMX_FORMAT_JPG, + QOMX_FORMAT_JPG2000 +}QOMX_CONTAINER_FORMATTYPE; + +typedef struct QOMX_CONTAINER_INFOTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + QOMX_CONTAINER_FORMATTYPE eFmtType; +} QOMX_CONTAINER_INFOTYPE; + +typedef enum QOMX_FILEFORMATTYPE { + QOMX_FileFormatNone, /**< no file format naming convention is followed. */ + QOMX_FileFormatDCF, /**< DCF file naming convention. */ + QOMX_FileFormatMax = 0x7FFFFFFF +} QOMX_FILEFORMATTYPE; + +/** QOMX_CONFIG_FILEFORMATTYPE is used to determine how the file writer will interpret +the provided content URI and whether it will increment the index of the file name. */ +typedef struct QOMX_CONFIG_FILEFORMATTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + QOMX_FILEFORMATTYPE eFileFormat; /** file format type */ +} QOMX_CONFIG_FILEFORMATTYPE; + +/**The QOMX_RECORDINGSTATISTICSINTERVALTYPE structure is used to enable +IL client to indicate the interval of the statistics notification to file mux +component. Time interval will indicate the frequency(in ms) when client needs +the statistics data*/ +typedef struct QOMX_RECORDINGSTATISTICSINTERVALTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion;/**< OMX specification version information */ + OMX_TICKS interval;/**< specifies the time(milliseconds) between updates */ + }QOMX_RECORDINGSTATISTICSINTERVALTYPE; + +/**QOMX_RECORDINGSTATISTICSTYPE indicates the current recording +time and space statistics of this session, which can be used by client to +identify current status of recorded data in milliseconds and bytes */ +typedef struct QOMX_RECORDINGSTATISTICSTYPE { + OMX_U32 nSize;/**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion;/**< OMX specification version information */ + OMX_TICKS nRecordedTime; /** duration that we already recorded*/ + OMX_TICKS nTimeCanRecord;/** the time we can record at the same bitrate*/ + OMX_U64 nSpaceConsumed;/** space that consumed in bytes*/ + OMX_U64 nSpaceLeft;/** space left in bytes*/ +} QOMX_RECORDINGSTATISTICSTYPE; + +#endif /*__QOMX_FILE_FORMAT_EXTENSIONS_H__*/ diff --git a/mm-core/inc/QOMX_IVCommonExtensions.h b/mm-core/inc/QOMX_IVCommonExtensions.h new file mode 100755 index 0000000..210820f --- /dev/null +++ b/mm-core/inc/QOMX_IVCommonExtensions.h @@ -0,0 +1,399 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2011 Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#ifndef __H_QOMX_IVCOMMONEXTENSIONS_H__ +#define __H_QOMX_IVCOMMONEXTENSIONS_H__ + +/*======================================================================== + +*//** @file QOMX_CommonExtensions.h + +@par FILE SERVICES: + common extensions API for OpenMax IL. + + This file contains the description of the Qualcomm OpenMax IL + common extention interface, through which the IL client and OpenMax + components can access additional capabilities. + +*//*====================================================================== */ + + +/*======================================================================== + + INCLUDE FILES FOR MODULE + +========================================================================== */ +#include + +/*======================================================================== + + DEFINITIONS AND DECLARATIONS + +========================================================================== */ + +#if defined( __cplusplus ) +extern "C" +{ +#endif /* end of macro __cplusplus */ + +/* IV common extension strings */ +#define OMX_QCOM_INDEX_CONFIG_MEDIAINFO "OMX.QCOM.index.config.mediainfo" /**< reference: QOMX_MEDIAINFOTYPE */ +#define OMX_QCOM_INDEX_CONFIG_CONTENTURI "OMX.QCOM.index.config.contenturi" /**< reference: OMX_PARAM_CONTENTURITYPE */ +#define OMX_QCOM_INDEX_PARAM_IMAGESIZECONTROL "OMX.Qualcomm.index.param.ImageSizeControl" /**< reference: QOMX_IMAGE_IMAGESIZECONTROLTYPE */ +#define OMX_QCOM_INDEX_CONFIG_PAUSEPORT "OMX.QCOM.index.config.PausePort" /**< reference: QOMX_CONFIG_PAUSEPORTTYPE */ + +/** reference: QOMX_URANGETYPE + * nMin, nMax, nStepSize give width in pixels */ +#define OMX_QCOM_INDEX_PARAM_FRAMEWIDTHRANGESUPPORTED "OMX.QCOM.index.param.FrameWidthRangeSupported" + +/** reference: QOMX_URANGETYPE + * nMin, nMax, nStepSize give height in pixels */ +#define OMX_QCOM_INDEX_PARAM_FRAMEHEIGHTRANGESUPPORTED "OMX.QCOM.index.param.FrameHeightRangeSupported" + +/** reference: QOMX_URANGETYPE + * nMin, nMax, nStepSize give the number of macroblocks per + * frame. */ +#define OMX_QCOM_INDEX_PARAM_MACROBLOCKSPERFRAMERANGESUPPORTED "OMX.QCOM.index.param.MacroblocksPerFrameRangeSupported" + +/** reference: QOMX_URANGETYPE + * nMin, nMax, nStepSize give the number of macroblocks per + * second. */ +#define OMX_QCOM_INDEX_PARAM_MACROBLOCKSPERSECONDRANGESUPPORTED "OMX.QCOM.index.param.MacroblocksPerSecondRangeSupported" + +/** reference: QOMX_URANGETYPE + * nMin, nMax, nStepSize give frame rate in frames per second + * in Q16 format. */ +#define OMX_QCOM_INDEX_PARAM_FRAMERATERANGESUPPORTED "OMX.QCOM.index.param.FrameRateRangeSupported" + +#define OMX_QCOM_INDEX_PARAM_PLANEDEFINITION "OMX.QCOM.index.param.PlaneDefinition" /** reference: QOMX_PLANEDEFINITIONTYPE */ + +/** reference: QOMX_URANGETYPE + * nMin, nMax, nStepSize give the crop width in pixels */ +#define OMX_QOMX_INDEX_PARAM_CROPWIDTHRANGESUPPORTED "OMX.QCOM.index.param.CropWidthRangeSupported" + +/** reference: QOMX_URANGETYPE + * nMin, nMax, nStepSize give the crop height in pixels */ +#define OMX_QOMX_INDEX_PARAM_CROPHEIGHTRANGESUPPORTED "OMX.QCOM.index.param.CropHeightRangeSupported" + +/** reference: QOMX_URANGETYPE + * nMin, nMax, nStepSize give the digital zoom factor on width + * in Q16 format. */ +#define OMX_QCOM_INDEX_PARAM_DIGITALZOOMWIDTHRANGESUPPORTED "OMX.QCOM.index.param.DigitalZoomWidthRangeSupported" + +/** reference: QOMX_URANGETYPE + * nMin, nMax, nStepSize give the digital zoom factor on height + * in Q16 format. */ +#define OMX_QCOM_INDEX_PARAM_DIGITALZOOMHEIGHTRANGESUPPORTED "OMX.QCOM.index.param.DigitalZoomHeightRangeSupported" + +/** + * Enumeration defining the extended uncompressed image/video + * formats. + * + * ENUMS: + * YVU420PackedSemiPlanar : Buffer containing all Y, and then V and U + * interleaved. + * YVU420PackedSemiPlanar32m4ka : YUV planar format, similar to the + * YVU420PackedSemiPlanar format, but with the + * following restrictions: + * + * 1. The width and height of both plane must + * be a multiple of 32 texels. + * + * 2. The base address of both planes must be + * aligned to a 4kB boundary. + * + * YUV420PackedSemiPlanar16m2ka : YUV planar format, similar to the + * YUV420PackedSemiPlanar format, but with the + * following restrictions: + * + * 1. The width of the luma plane must be a + * multiple of 16 pixels. + * + * 2. The address of both planes must be + * aligned to a 2kB boundary. + * + * YUV420PackedSemiPlanar64x32Tile2m8ka : YUV planar format, similar to the + * YUV420PackedSemiPlanar format, but with the + * following restrictions: + * + * 1. The data is laid out in a 4x2 MB tiling + * memory structure + * + * 2. The width of each plane is a multiple of + * 2 4x2 MB tiles. + * + * 3. The height of each plan is a multiple of + * a 4x2 MB tile. + * + * 4. The base address of both planes must be + * aligned to an 8kB boundary. + * + * 5. The tiles are scanned in the order + * defined in the MFCV5.1 User's Manual. + */ +typedef enum QOMX_COLOR_FORMATTYPE +{ + QOMX_COLOR_FormatYVU420PackedSemiPlanar = 0x7F000001, + QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka, + QOMX_COLOR_FormatYUV420PackedSemiPlanar16m2ka, + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka +} QOMX_COLOR_FORMATTYPE; + +typedef enum QOMX_MEDIAINFOTAGTYPE { + QOMX_MediaInfoTagVersion, /**< OMX_VERSIONTYPE. Version of the standard specifying the media information.*/ + QOMX_MediaInfoTagUID, /**< OMX_U8*. Unique ID of the media data, ie image unique ID.*/ + QOMX_MediaInfoTagDescription, /**< OMX_U8*. Comments about the media.*/ + QOMX_MediaInfoTagTitle, /**< OMX_U8*. Title of the media.*/ + QOMX_MediaInfoTagAuthor, /**< OMX_U8*. Author of the media.*/ + QOMX_MediaInfoTagCopyright, /**< OMX_U8*. Copyright information.*/ + QOMX_MediaInfoTagTrackNum, /**< OMX_U32. Track number.*/ + QOMX_MediaInfoTagGenre, /**< OMX_U8*. The genre of the media.*/ + QOMX_MediaInfoTagEquipmentMake, /**< OMX_U8*. Manufacturer of recording equipment.*/ + QOMX_MediaInfoTagEquipmentModel,/**< OMX_U8*. Model or name of the recording equipment.*/ + QOMX_MediaInfoTagSoftware, /**< OMX_U8*. Name and version of the software or firmware of the device generating the media.*/ + QOMX_MediaInfoTagAssociatedFile,/**< OMX_U8*. The name of the file related to the media. For example, an audio file related to an image file.*/ + QOMX_MediaInfoTagResolution, /**< QOMX_RESOLUTIONTYPE. Number of pixels per resolution unit.*/ + QOMX_MediaInfoTagDateCreated, /**< QOMX_DATESTAMPTYPE. Date when media was created.*/ + QOMX_MediaInfoTagTimeCreated, /**< QOMX_TIMESTAMPTYPE. Time when media was created.*/ + QOMX_MediaInfoTagDateModified, /**< QOMX_DATESTAMPETYPE. Date when file was last modified.*/ + QOMX_MediaInfoTagTimeModified, /**< QOMX_TIMESTAMPTYPE. Time when file was last modified.*/ + QOMX_MediaInfoTagGPSAreaName, /**< OMX_U8*. The name of the location.*/ + QOMX_MediaInfoTagGPSVersion, /**< OMX_VERSIONTYPE. GPS version.*/ + QOMX_MediaInfoTagGPSCoordinates,/**< QOMX_GEODETICTYPE. The longitude, latitude, and altitude.*/ + QOMX_MediaInfoTagGPSSatellites, /**< OMX_U8*. The GPS satellites used for measurements.*/ + QOMX_MediaInfoTagGPSPrecision, /**< OMX_U32. GPS degree of precision.*/ + QOMX_MediaInfoTagGPSDateStamp, /**< QOMX_DATESTAMPTYPE. Date of the GPS data.*/ + QOMX_MediaInfoTagGPSTimeStamp, /**< QOMX_TIMESTAMPTYPE. Time of the GPS data.*/ + QOMX_MediaInfoTagMediaStreamType,/**< QOMX_MEDIASTREAMTYPE. Type of the stream. */ + QOMX_MediaInfoDuration, /**< OMX_TICKS. Total duration of the media.*/ + QOMX_MediaInfoSize, /**< OMX_U32. Total size of the media in bytes.*/ + QOMX_MediaInfoTagAlbum, /**< OMX_U8*. Name of album/movie/show.*/ + QOMX_MediaInfoTagLocation, /**< OMX_U8*. Recording location information.*/ + QOMX_MediaInfoTagClassification, /**< OMX_U8*. Classification information of media.*/ + QOMX_MediaInfoTagRatings, /**< OMX_U8*. Media Ratings based on popularity & rating criteria.*/ + QOMX_MediaInfoTagKeyword, /**< OMX_U8*. Keyword associated with media which are intended to reflect mood of the A/V.*/ + QOMX_MediaInfoTagPerformance, /**< OMX_U8*. Media Performer information..*/ + QOMX_MediaInfoTagYear, /**< OMX_U8*. Production year information of media.*/ + QOMX_MediaInfoTagComposer, /**< OMX_U8*. Name of the composer of media i.e. audio.*/ + QOMX_MediaInfoTagEncoderName, /**< OMX_U8*. Name of the person or organisation who encoded media.*/ + QOMX_MediaInfoTagCopyProhibitFlag, /**< OMX_U8*. Flag to indicate if copy is allowed or not.*/ + QOMX_MediaInfoTagLyricist, /**< OMX_U8*. Name of the lyricist or text writer in recording. Specific to ID3 tag.*/ + QOMX_MediaInfoTagSubtitle, /**< OMX_U8*. Subtitle/Description used for informaton directly related to title of media.*/ + QOMX_MediaInfoTagOriginalFileName, /**< OMX_U8*. Original file name.*/ + QOMX_MediaInfoTagOriginalLyricist, /**< OMX_U8*. Name of the original lyricist/text writer of original recording.*/ + QOMX_MediaInfoTagOriginalArtist, /**< OMX_U8*. Name of the original artist.*/ + QOMX_MediaInfoTagOriginalReleaseYear, /**< OMX_U8*. Original release year of recorded media.*/ + QOMX_MediaInfoTagFileOwner, /**< OMX_U8*. Licensee or name of the file owner.*/ + QOMX_MediaInfoTagOrchestra, /**< OMX_U8*. Name of the orchestra or performers during recording.*/ + QOMX_MediaInfoTagConductor, /**< OMX_U8*. Name of the conductor.*/ + QOMX_MediaInfoTagRemixedBy, /**< OMX_U8*. Person or organization name who did the remix.*/ + QOMX_MediaInfoTagAlbumArtist, /**< OMX_U8*. Name of the album artist.*/ + QOMX_MediaInfoTagPublisher, /**< OMX_U8*. Name of the publisher or label.*/ + QOMX_MediaInfoTagRecordingDates, /**< OMX_U8*. Recording date of media.*/ + QOMX_MediaInfoTagInternetRadioStationName, /**< OMX_U8*. Name of the Internet radio station from which the audio is streamed.*/ + QOMX_MediaInfoTagInternetRadioStationOwner, /**< OMX_U8*. Name of the owner of the Internet radio station from which the audio is streamed.*/ + QOMX_MediaInfoTagInternationalRecordingCode,/**< OMX_U8*. International standard recording code.*/ + QOMX_MediaInfoTagEncoderSwHwSettings, /**< OMX_U8*. Software,hardware settings used by encoder.*/ + QOMX_MediaInfoTagInvolvedPeopleList, /**< OMX_U8*. List of people involved. Specific to ID3 tag.*/ + QOMX_MediaInfoTagComments, /**< OMX_U8*. Comments about the media. It can be any kind of full text informaton.*/ + QOMX_MediaInfoTagCommissioned, /**< OMX_U8*. Commissioned information of media.*/ + QOMX_MediaInfoTagSubject, /**< OMX_U8*. Subject associated with media.*/ + QOMX_MediaInfoTagContact, /**< OMX_U8*. Conatct information. URL information of the seller.*/ + QOMX_MediaInfoTagValidityPeriod, /**< OMX_U8*. Length or period of validity of media.*/ + QOMX_MediaInfoTagValidityEffectiveDate, /**< OMX_U8*. Validity effective date of media*/ + QOMX_MediaInfoTagNumberOfAllowedPlaybacks, /**< OMX_U8*. Number of allowed playbacks for this media*/ + QOMX_MediaInfoTagPlayCounter, /**< OMX_U8*. Current play counter of the media.Its number of times a file has been played.*/ + QOMX_MediaInfoTagMemo, /**< OMX_U8*. Memo associatd with media.*/ + QOMX_MediaInfoTagDeviceName, /**< OMX_U8*. Name of the devices used in creating media.*/ + QOMX_MediaInfoTagURL, /**< OMX_U8*. List artist /genre /movie sites URL.*/ + QOMX_MediaInfoTagFileType, /**< OMX_U8*. Indicates type of audio track.*/ + QOMX_MediaInfoTagContentGroupDesc, /**< OMX_U8*. Content group description if the sound belongs to a larger category of of music /sound.*/ + QOMX_MediaInfoTagInitialKeys, /**< OMX_U8*. Contains the musical key in which media starts.*/ + QOMX_MediaInfoTagLanguages, /**< OMX_U8*. Languages of the text or lyrics spoken or sung in the media.*/ + QOMX_MediaInfoTagMediaType, /**< OMX_U8*. Describes from which media the media sound originated.*/ + QOMX_MediaInfoTagPlaylistDelay, /**< OMX_U8*. Denotes number of milliseconds between each song of the playlist.*/ + QOMX_MediaInfoTagBeatsPerMinute, /**< OMX_U8*. Number of beats per minute in main part of audio.*/ + QOMX_MediaInfoTagPartOfSet, /**< OMX_U8*. Describes part of the set selected or played. */ + QOMX_MediaInfoTagInstrumentName, /**< OMX_U8*. Name of the instrument used in creating media.*/ + QOMX_MediaInfoTagLyrics, /**< OMX_U8*. Lyrics of the media/audio track.*/ + QOMX_MediaInfoTagTrackName, /**< OMX_U8*. Name of the media/audio track.*/ + QOMX_MediaInfoTagMarker, /**< OMX_U8*. Text string cotnents placed at a specific location to denote information about the music at that point.*/ + QOMX_MediaInfoTagCuePoint, /**< OMX_U8*. Subset of the content which can be optionally played.*/ + QOMX_MediaInfoTagGPSPositioningName, /**< OMX_U8*. GPS positioning name. */ + QOMX_MediaInfoTagGPSPositioningMethod, /**< OMX_U8*. GPS positioning method.*/ + QOMX_MediaInfoTagGPSSurveyData, /**< OMX_U8*. GPS survey data. */ + QOMX_MediaInfoTagGPSByteOrder, /**< OMX_U16.GPS byte order. */ + QOMX_MediaInfoTagGPSLatitudeRef, /**< OMX_U32.Reference GPS latitude. */ + QOMX_MediaInfoTagGPSLongitudeRef, /**< OMX_U32.Reference GPS longitude */ + QOMX_MediaInfoTagGPSAltitudeRef, /**< OMX_U32. Reference GPS altitude.*/ + QOMX_MediaInfoTagGPSExtensionMapScaleInfo, /**< OMX_U64. GPS extension map scale information.*/ + QOMX_MediaInfoTagUUIDAtomInfo, /**< OMX_U8*. The user defined data associated with UUID.*/ + QOMX_MediaInfoTagUUIDAtomCount, /**< OMX_U32 UUID atom count.*/ + QOMX_MediaInfoTagLocationRole, /**< OMX_32. Indicates the role of the place. i.e. ‘0’ indicate ‘shooting location'. ‘1’ ‘real location’.*/ + QOMX_MediaInfoTagAstronomicalBody, /**< OMX_U8*. Astronomical body on which the location exists.*/ + QOMX_MediaInfoTagUserInfoData /**< OMX_U8*. The user defined tag informaton.*/ +} QOMX_MEDIAINFOTAGTYPE; + +typedef struct QOMX_MEDIAINFOTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; /**< Read-only value containing the index of the output port. */ + QOMX_MEDIAINFOTAGTYPE eTag; /**< The type of media info being specified. */ + OMX_U32 nDataSize; /**< The size of the associated cData. Set nDataSize to 0 to retrieve the size required for cData. */ + OMX_U8 cData[1]; /**< The media data info */ +} QOMX_MEDIAINFOTYPE; + + +typedef enum QOMX_RESOLUTIONUNITTYPE { + QOMX_ResolutionUnitInch, + QOMX_ResolutionCentimeter +} QOMX_RESOLUTIONUNITTYPE; + +typedef struct QOMX_RESOLUTIONTYPE { + QOMX_RESOLUTIONUNITTYPE eUnit; /**< The unit of measurement. */ + OMX_U32 nX; /**< The number of pixels per unit in the width direction. */ + OMX_U32 nY; /**< The number of pixels per unit in the height direction. */ +} QOMX_RESOLUTIONTYPE; + +typedef struct QOMX_TIMESTAMPTYPE { + OMX_U32 nHour; /**< The hour portion of the time stamp, based on a 24-hour format. */ + OMX_U32 nMinute; /**< The minute portion of the time stamp. */ + OMX_U32 nSecond; /**< The second portion of the time stamp. */ + OMX_U32 nMillisecond; /**< the millisecond portion of the time stamp. */ +} QOMX_TIMESTAMPTYPE; + +typedef struct QOMX_DATESTAMPTYPE { + OMX_U32 nYear; /**< The year portion of the date stamp. */ + OMX_U32 nMonth; /**< The monthportion of the date stamp. Valid values are 1 to 12.*/ + OMX_U32 nDay; /**< The day portion of the date stamp. Valid values are 1 to 31 depending on the month specified.*/ +} QOMX_DATESTAMPTYPE; + +typedef enum QOMX_GEODETICREFTYPE { + QOMX_GeodeticRefNorth, /**< North latitude. */ + QOMX_GeodeticRefSouth, /**< South latitude. */ + QOMX_GeodeticRefEast, /**< East longitude. */ + QOMX_GeodeticRefWest /**< West longitude. */ +} QOMX_GEODETICREFTYPE; + +/** QOMX_GEODETICANGLETYPE is used to set geodetic angle coordinates on an ellipsoid (the Earth), +and is explicitly used to specify latitude and longitude. This structure is referenced by QOMX_GEODETICTYPE. */ +typedef struct QOMX_GEODETICANGLETYPE { + QOMX_GEODETICREFTYPE eReference; /**< Indicates whether the geodetic angle is a latitude or longitude. */ + OMX_U32 nDegree; /**< The degree of the latitude or longitude. */ + OMX_U32 nMinute; /**< The minute of the latitude or longitude. */ + OMX_U32 nSecond; /**< The second of the latitude or longitude. */ +} QOMX_GEODETICANGLETYPE; + +typedef enum QOMX_ALTITUDEREFTYPE { + QOMX_AltitudeRefSeaLevel, /**< At sea level. */ + QOMX_AltitudeRefBelowSeaLevel /**< Below sea level. */ +} QOMX_ALTITUDEREFTYPE; + +typedef struct QOMX_ALTITUDETYPE { + QOMX_ALTITUDEREFTYPE eReference; /**< The reference point for the altitude. */ + OMX_U32 nMeter; /**< The absolute value of the number of meters above or below sea level. */ + OMX_U32 nMillimeter; /**< The absolute value of the number of millimeters above or below sea level. */ +} QOMX_ALTITUDETYPE; + +/** QOMX_GEODETICTYPE is used to set geodetic coordinates such as longitude, latitude, and altitude. +This structure references QOMX_GEODETICANGLETYPE and QOMX_ALTITUDETYPE. */ +typedef struct QOMX_GEODETICTYPE { + QOMX_GEODETICANGLETYPE sLatitude; /**< Indicates the latitude.*/ + QOMX_GEODETICANGLETYPE sLongitude; /**< Indicates the longitude.*/ + QOMX_ALTITUDETYPE sAltitude; /**< Indicates the altitude.*/ +} QOMX_GEODETICTYPE; + + +typedef struct QOMX_IMAGE_IMAGESIZECONTROLTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; /**< port index on which size control needs to be applied */ + OMX_U32 nTargetImageSize; /**< expected max target size in Bytes */ +} QOMX_IMAGE_IMAGESIZECONTROLTYPE; + +typedef enum QOMX_URITYPE { + QOMX_URITYPE_RTSP, /**< RTSP URI Type. */ + QOMX_URITYPE_HTTP, /**< HTTP URI Type. */ + QOMX_URITYPE_LOCAL /**< Local URI Type.(i.e Non Network) */ +}QOMX_URITYPE; + + +typedef enum QOMX_STREAMTYPE { + QOMX_STREAMTYPE_VOD, /**< Video On demand Stream */ + QOMX_STREAMTYPE_LIVE,/**< Live Stream */ + QOMX_STREAMTYPE_FILE /**< File based Stream */ +}QOMX_STREAMTYPE; + + +typedef struct QOMX_MEDIASTREAMTYPE{ + QOMX_URITYPE eURIType; + QOMX_STREAMTYPE eStreamType; +}QOMX_MEDIASTREAMTYPE; + + +/** + * This structure specifies the parameters associated with each + * plane of the uncompressed image/video format. + */ +typedef struct QOMX_PLANEDEFINITIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; /**< Represents the port that this structure applies to */ + OMX_U32 nPlaneIndex; /**< Specifies the plane enumeration index that this structure applies to, starting with a base value of 1 */ + OMX_U32 nMinStride; /**< Read-only parameter that specifies the minimum buffer stride */ + OMX_U32 nMaxStride; /**< Read-only parameter that specifies the maximum buffer stride */ + OMX_U32 nStrideMultiples; /**< Read-only parameter that specifies the buffer stride multiple supported */ + OMX_S32 nActualStride; /**< Specifies the actual stride to be applied */ + OMX_U32 nMinPlaneBufferHeight; /**< Read-only parameter that specifies the minimum buffer height (number of stride lines) */ + OMX_U32 nActualPlaneBufferHeight; /**< Specifies the actual buffer height (number of stride lines) to be applied */ + OMX_U32 nBufferSize; /**< Read-only parameter that specifies the minimum size of the buffer, in bytes */ + OMX_U32 nBufferAlignment; /**< Read-only field that specifies the required alignment of the buffer, in bytes */ +} QOMX_PLANEDEFINITIONTYPE; + +/** + * Pause port parameters + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Index of port that this structure represent + * bPausePort : Boolean field which indicates if port is paused or resume. By default bPausePort = OMX_FALSE + * & port will be paused when bPausePort = OMX_TRUE + */ +typedef struct QOMX_CONFIG_PAUSEPORTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; /**< Represents the port that this structure applies to */ + OMX_BOOL bPausePort; /**< Specifies if port need to PAUSE or RESUME */ +} QOMX_CONFIG_PAUSEPORTTYPE; + +#if defined( __cplusplus ) +} +#endif /* end of macro __cplusplus */ + +#endif /* end of macro __H_QOMX_IVCOMMONEXTENSIONS_H__ */ diff --git a/mm-core/inc/QOMX_SourceExtensions.h b/mm-core/inc/QOMX_SourceExtensions.h new file mode 100755 index 0000000..69339db --- /dev/null +++ b/mm-core/inc/QOMX_SourceExtensions.h @@ -0,0 +1,157 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2011-2012 Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#ifndef __H_QOMX_SOURCEEXTENSIONS_H__ +#define __H_QOMX_SOURCEEXTENSIONS_H__ +/*======================================================================== +*//** @file QOMX_SourceExtensions.h + +@par FILE SERVICES: + Qualcomm extensions API for OpenMax IL demuxer component. + + This file contains the description of the Qualcomm OpenMax IL + demuxer component extention interface, through which the IL client and + OpenMax components can access additional capabilities of the demuxer. + +*//*====================================================================== */ + + +/*======================================================================== + INCLUDE FILES FOR MODULE +========================================================================== */ +#include +/*======================================================================== + DEFINITIONS AND DECLARATIONS +========================================================================== */ + +#if defined( __cplusplus ) +extern "C" +{ +#endif /* end of macro __cplusplus */ +/* Frame size query supported extension string */ +#define OMX_QCOM_INDEX_PARAM_FRAMESIZEQUERYSUPPORTED "OMX.QCOM.index.param.FrameSizeQuerySupported" /**< reference: QOMX_FRAMESIZETYPE */ + +/* Content interface extension strings */ +#define OMX_QCOM_INDEX_PARAM_CONTENTINTERFACE_IXSTREAM "OMX.QCOM.index.param.contentinterface.ixstream" /**< reference: QOMX_CONTENTINTERFACETYPE*/ +#define OMX_QCOM_INDEX_PARAM_CONTENTINTERFACE_ISTREAMPORT "OMX.QCOM.index.param.contentinterface.istreamport" /**< reference: QOMX_CONTENTINTERFACETYPE*/ + +/* Source seek access extension string */ +#define OMX_QCOM_INDEX_PARAM_SEEK_ACCESS "OMX.QCOM.index.param.SeekAccess" /**< reference: QOMX_PARAM_SEEKACCESSTYPE*/ + +/* Media duration extension string*/ +#define OMX_QCOM_INDEX_CONFIG_MEDIADURATION "OMX.QCOM.index.config.MediaDuration" /**< reference: OMX_TIME_CONFIG_MEDIADURATIONTYPE*/ + +/** + * Data interface Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nInterfaceSize : Size of the data pointed by pInterface + * pInterface : Interface pointer + */ +typedef struct QOMX_CONTENTINTERFACETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nInterfaceSize; + OMX_U8 pInterface[1]; +} QOMX_DATAINTERFACETYPE; + +/** + * Seek Access Parameters + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Index of port + * bSeekAllowed : Flag to indicate whether seek is supported or not + */ +typedef struct QOMX_PARAM_SEEKACCESSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bSeekAllowed; +} QOMX_PARAM_SEEKACCESSTYPE; + +/** + * Media Duration parameters + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Index of port + * nDuration : Total duration of the media +*/ +typedef struct OMX_TIME_CONFIG_MEDIADURATIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_TICKS nDuration; +} OMX_TIME_CONFIG_MEDIADURATIONTYPE; + +/** + * The parameters for QOMX_FRAMESIZETYPE are defined as + * follows: + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Represents the port that this structure + * applies to + * sFrameSize : Indicates the size of the frame + * nFrameSizeIndex : Enumerates the possible frame sizes for + * the given session/URL configuration. The + * caller specifies all fields and the + * OMX_GetParameter call returns the value of + * the frame size. The value of + * nFrameSizeIndex goes from 0 to N-1, where + * N is the number of frame sizes that may be + * emitted by the port. The port does not + * need to report N as the caller can + * determine N by enumerating all the frame + * sizes supported by the port. If the port + * does not have advance knowledge of the + * possible frame sizes, it may report no + * frame sizes. If there are no more frame + * sizes, OMX_GetParameter returns + * OMX_ErrorNoMore. + */ +typedef struct QOMX_FRAMESIZETYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_FRAMESIZETYPE sFrameSize; + OMX_U32 nFrameSizeIndex; +} QOMX_FRAMESIZETYPE; + +#if defined( __cplusplus ) +} +#endif /* end of macro __cplusplus */ + +#endif /* end of macro __H_QOMX_SOURCEEXTENSIONS_H__ */ diff --git a/mm-core/inc/QOMX_StreamingExtensions.h b/mm-core/inc/QOMX_StreamingExtensions.h new file mode 100755 index 0000000..2038acf --- /dev/null +++ b/mm-core/inc/QOMX_StreamingExtensions.h @@ -0,0 +1,486 @@ +#ifndef QOMX_STREAMINGEXTENSIONS_H_ +#define QOMX_STREAMINGEXTENSIONS_H_ +/*-------------------------------------------------------------------------- +Copyright (c) 2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*======================================================================== + +*//** @file QOMX_StreamingExtensions.h + +@par FILE SERVICES: + Qualcomm extensions API for OpenMax IL Streaming Components. + + This file contains the description of the Qualcomm OpenMax IL + streaming extention interface, through which the IL client and OpenMax + components can access additional streaming capabilities. + +*//*====================================================================== */ + +/*======================================================================== + Edit History + +$Header: //source/qcom/qct/multimedia2/api/OpenMax/QCOM/main/latest/QOMX_StreamingExtensions.h#7 $ +$DateTime: 2011/03/02 12:27:27 $ +$Change: 1638323 $ + +========================================================================== */ + +/* ======================================================================= +** Includes and Public Data Declarations +** ======================================================================= */ + +/* ======================================================================= + + INCLUDE FILES FOR MODULE + +========================================================================== */ + +#include +#include + +#if defined( __cplusplus ) +extern "C" +{ +#endif /* end of macro __cplusplus */ + +/* ======================================================================= + + DATA DECLARATIONS + +========================================================================== */ +/* ----------------------------------------------------------------------- +** Type Declarations +** ----------------------------------------------------------------------- */ +/** + * Qualcomm vendor streaming extension strings. + */ +#define OMX_QUALCOMM_INDEX_CONFIG_WATERMARK "OMX.Qualcomm.index.config.Watermark" +#define OMX_QUALCOMM_INDEX_CONFIG_WATERMARKSTATUS "OMX.Qualcomm.index.config.WatermarkStatus" +#define OMX_QUALCOMM_INDEX_CONFIG_BUFFERMARKING "OMX.Qualcomm.index.config.BufferMarking" +#define OMX_QUALCOMM_INDEX_PARAM_STREAMING_NETWORKINTERFACE "OMX.Qualcomm.index.param.streaming.NetworkInterface" +#define OMX_QUALCOMM_INDEX_PARAM_STREAMING_NETWORKPROFILE "OMX.Qualcomm.index.param.streaming.NetworkProfile" +#define OMX_QUALCOMM_INDEX_PARAM_STREAMING_PROXYSERVER "OMX.Qualcomm.index.param.streaming.ProxyServer" +#define OMX_QUALCOMM_INDEX_PARAM_STREAMING_SOURCEPORTS "OMX.Qualcomm.index.param.streaming.SourcePorts" +#define OMX_QUALCOMM_INDEX_CONFIG_STREAMING_PROTOCOLHEADER "OMX.Qualcomm.index.param.streaming.ProtocolHeader" +#define OMX_QUALCOMM_INDEX_CONFIG_STREAMING_PROTOCOLEVENT "OMX.Qualcomm.index.config.streaming.ProtocolEvent" +#define OMX_QUALCOMM_INDEX_CONFIG_STREAMING_DYNAMIC_SWITCH_CAPABILITY "OMX.Qualcomm.index.config.streaming.DynamicSessionSwitchCapability" +#define OMX_QUALCOMM_INDEX_CONFIG_STREAMING_PROTOCOLHEADERSEVENT "OMX.QCOM.index.config.streaming.ProtocolHeadersEvent" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_USERPAUSETIMEOUT "OMX.QCOM.index.config.streaming.UserPauseTimeout" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_NOTIFYERRORONOPTIONSTIMEOUT "OMX.QCOM.index.config.streaming.NotifyErrorOnOptionsTimeout" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_USEINTERLEAVEDTCP "OMX.QCOM.index.config.streaming.UseInterleavedTCP" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_DATAINACTIVITYTIMEOUT "OMX.QCOM.index.config.streaming.DataInactivityTimeout" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_RTSPOPTIONSKEEPALIVEINTERVAL "OMX.QCOM.index.config.streaming.RTSPOptionsKeepaliveInterval" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_RTCPRRINTERVAL "OMX.QCOM.index.config.streaming.RTCPRRInterval" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_RECONFIGUREPORT "OMX.QCOM.index.config.streaming.ReconfigurePort" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_DEFAULTRTSPMESSAGETIMEOUT "OMX.QCOM.index.config.streaming.DefaultRTSPMessageTimeout" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_ENABLEFIREWALLPROBES "OMX.QCOM.index.config.streaming.EnableFirewallProbes" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_RTSPOPTIONSBEFORESETUP "OMX.QCOM.index.config.streaming.RTSPOptionsBeforeSetup" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_RTSPPIPELINEDFASTSTARTUP "OMX.QCOM.index.config.streaming.RTSPPipelinedFastStartup" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_WMFASTSTARTSPEED "OMX.QCOM.index.config.streaming.WMFastStartSpeed" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_ENABLEFASTRECONNECT "OMX.QCOM.index.config.streaming.EnableFastReconnect" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_FASTRECONNECTMAXATTEMPTS "OMX.QCOM.index.config.streaming.FastReconnectMaxAttempts" +#define OMX_QCOM_INDEX_CONFIG_STREAMING_DOWNLOADPROGRESSUNITSTYPE "OMX.QCOM.index.config.streaming.DownloadProgressUnitsType" +#define OMX_QOMX_INDEX_CONFIG_STREAMING_DOWNLOADPROGRESS "OMX.QCOM.index.config.streaming.DownloadProgress" +/** + * Enumeration of the buffering watermark types + */ +typedef enum QOMX_WATERMARKTYPE +{ + QOMX_WATERMARK_UNDERRUN, /**< buffer has reached or is operating in an underrun condition */ + QOMX_WATERMARK_NORMAL /**< has reached or is operating in a normal (optimal) condition */ +}QOMX_WATERMARKTYPE; + +/** + * Enumeration of type of buffering level tracking + */ +typedef enum QOMX_WATERMARKUNITSTYPE +{ + QOMX_WATERMARKUNITSTYPE_Time, /**< use a media time based reference */ + QOMX_WATERMARKUNITSTYPE_Data /**< use a data fullness based reference */ +}QOMX_WATERMARKUNITSTYPE; + +/** + * Buffering watermark levels. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eWaterMark : eWaterMark specifies the type of buffering watermark being + * configured + * QOMX_WATERMARK_UNDERRUN Indicates the condition when the + * buffer has reached or is operating in an underrun condition + * - not enough data + * QOMX_WATERMARK_NORMAL Indicates the condition when the buffer + * has reached or is operating in a normal (optimal) condition + * - sufficient data within the buffer. + * + * nLevel : specifies the buffering level associated with the watermark. + * The units associated with the watermark level is dependent + * on the eUnitsType being selected. + * QOMX_WATERMARKUNITSTYPE_Time nLevel in units of microseconds. + * QOMX_WATERMARKUNITSTYPE_Data nLevel in units of bytes. + * + * nUnitsType : specifies the type of buffering level tracking to be used. + * QOMX_WATERMARKUNITSTYPE_Time the buffer watermark level + * shall use a media time based reference. + * QOMX_WATERMARKUNITSTYPE_Data the buffer watermark level + * shall use a data fullness based reference. + * bEnable : specifies if the watermark type is being enabled or disabled + */ +typedef struct QOMX_BUFFERINGWATERMARKTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_WATERMARKTYPE eWaterMark; + OMX_U32 nLevel; + QOMX_WATERMARKUNITSTYPE eUnitsType; + OMX_BOOL bEnable; +} QOMX_BUFFERINGWATERMARKTYPE; + +/** + * Current buffering status of the streaming source component, for a given + * media port + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eCurrentWaterMark : specifies the current buffer watermark level condition + * QOMX_WATERMARK_UNDERRUN Indicates the condition when the + * buffer has reached or is operating in an underrun + * condition - not enough data + * QOMX_WATERMARK_NORMAL Indicates the condition when the + * buffer has reached or is operating in a normal + * (optimal) condition - sufficient data within the buffer. + * eUnitsType : specifies the type of buffering level tracking to be used. + * QOMX_WATERMARKUNITSTYPE_Time the buffer watermark level + * shall use a media time based reference. + * QOMX_WATERMARKUNITSTYPE_Data the buffer watermark level + * shall use a data fullness based reference. + * nCurrentLevel : specifies the current buffer watermark level condition + * The units associated with the watermark level is dependent + * on the eUnitsType being selected. + * QOMX_WATERMARKUNITSTYPE_Time nLevel in units of microseconds. + * QOMX_WATERMARKUNITSTYPE_Data nLevel in units of bytes. + */ +typedef struct QOMX_BUFFERINGSTATUSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_WATERMARKTYPE eCurrentWaterMark; + QOMX_WATERMARKUNITSTYPE eUnitsType; + OMX_U32 nCurrentLevel; +} QOMX_BUFFERINGSTATUSTYPE; + +/** + * marked buffer shall be emitted when the buffering level has reach an + * underrun condition (QOMX_WATERMARK_UNDERRUN). + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * markInfo : identifies the target component handle that shall emit + * the mark buffer event and associated + * bEnable : enables or disables the buffer marking insertion. + * + */ +typedef struct QOMX_BUFFERMARKINGTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_MARKTYPE markInfo; + OMX_BOOL bEnable; +} QOMX_BUFFERMARKINGTYPE; + +/** + * Source ports. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nMinimumPortNumber : Minimum port number the component may use + * nMaximumPortNumber : Maximum port number the component may use + */ +typedef struct QOMX_PARAM_STREAMING_SOURCE_PORTS +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U16 nMinimumPortNumber; + OMX_U16 nMaximumPortNumber; +} QOMX_PARAM_STREAMING_SOURCE_PORTS; + +/** + * Enumeration used to define to the protocol message type. + */ +typedef enum QOMX_STREAMING_PROTOCOLMESSAGETYPE +{ + QOMX_STREAMING_PROTOCOLMESSAGE_REQUEST, + QOMX_STREAMING_PROTOCOLMESSAGE_RESPONSE, + QOMX_STREAMING_PROTOCOLMESSAGE_ALL +} QOMX_STREAMING_PROTOCOLMESSAGETYPE; + +/** + * Enumeration used to define the protocol header action type. + */ +typedef enum QOMX_STREAMING_PROTOCOLHEADERACTIONTYPE +{ + QOMX_STREAMING_PROTOCOLHEADERACTION_NONE, + QOMX_STREAMING_PROTOCOLHEADERACTION_ADD, + QOMX_STREAMING_PROTOCOLHEADERACTION_REMOVE +} QOMX_STREAMING_PROTOCOLHEADERACTIONTYPE; + +/** + * Protocol message header. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes (including size of + messageHeader parameter) + * nVersion : OMX specification version information + * eMessageType : enumeration to distinguish protocol message type + * eActionType : enumeration indicating protocol header action type + * nMessageClassSize : size of the message class string (excluding any + * terminating characters) + * nHeaderNameSize : size of the header name string (excluding any + * terminating characters) + * nHeaderValueSize : size of the header value string (excluding any + * terminating characters) + * messageHeader : the NULL-terminated message header string formed by + * concatenating message class, header name and value + * strings, i.e. the first nMessageClassSize bytes of the + * messageHeader parameter correspond to the message class + * (without any terminating characters), followed by the + * header name of size nHeaderNameSize bytes and then the + * header value of size nHeaderValueSize bytes. The value + * of message class is interpreted by what is mentioned in + * eMessageType, + * 1) For request message + * (QOMX_STREAMING_PROTOCOLMESSAGE_REQUEST) it is the + * Method token (as specified in the RFC 2616 and RFC + * 2326). + * 2) For response message + * (QOMX_STREAMING_PROTOCOLMESSAGE_RESPONSE) it is + * either or both the Method token and a three digit + * Status-Code (as specified in the RFC 2616 and + * RFC 2326) or a class of the response Status-Codes + * (1xx, 2xx, 3xx, 4xx, and 5xx). When both present, + * the method token and status code are separated by + * 1 empty space. + * 3) For all messages + * (QOMX_STREAMING_PROTOCOLMESSAGE_ALL) it will be + * absent (nMessageClassSize will be zero). + */ +typedef struct QOMX_CONFIG_STREAMING_PROTOCOLHEADERTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + QOMX_STREAMING_PROTOCOLMESSAGETYPE eMessageType; + QOMX_STREAMING_PROTOCOLHEADERACTIONTYPE eActionType; + OMX_U32 nMessageClassSize; + OMX_U32 nHeaderNameSize; + OMX_U32 nHeaderValueSize; + OMX_U8 messageHeader[1]; +} QOMX_CONFIG_STREAMING_PROTOCOLHEADERTYPE; + +/** + * Protocol Event. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes (including size of + protocolEventText parameter) + * nVersion : OMX specification version information + * nProtocolEvent : 1xx, 2xx, 3xx, 4xx or 5xx codes for HTTP/RTSP protocol + * nReasonPhraseSize : size of the reason phrase string (excluding any + * terminating characters) + * nEntityBodySize : size of the entity body string (excluding any + * terminating characters) + * nContentUriSize : size of the url (exclusing any terminating characters) + * url is used a key to identify for which operation this + * event belongs to + * protocolEventText : NULL-terminated protocol event text string formed by + * concatenating reason phrase and entity body + * and uri, i.e. the first nReasonPhraseSize bytes of the + * protocolEventText parameter correspond to the reason + * phrase (without any terminating characters), followed + * by the entity body of size nEntityBodySize bytes, + * followed by nContentUriSize bytes of URI + */ +typedef struct QOMX_CONFIG_STREAMING_PROTOCOLEVENTTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nProtocolEvent; + OMX_U32 nReasonPhraseSize; + OMX_U32 nEntityBodySize; + OMX_U32 nContentUriSize; + OMX_U8 protocolEventText[1]; +} QOMX_CONFIG_STREAMING_PROTOCOLEVENTTYPE; + +/** + * Protocol Headers Event + * + * STRUCT MEMBERS: + * nSize: Size of the structure in bytes including + * messageHeaders. + * nVersion: OMX specification version information + * eMessageType: enumeration to distinguish protocol message + * type + * nMessageClassSize: Size of the message class string. + * nMessageAttributesSize: Size of the message attributes + * string. + * + * This structure can be populated in 2 modes: + * (i) Query for required sizes of message class and message + * attributes. In this mode, nMessageClassSize and + * nMessageAtributesSize both need to be set to zero. + * (ii) Request to populate messageHeaders. In this mode, at + * least one of nMessageClassSize or nMessageAttributesSize + * need to be non-zero. On output, messageHeaders will be + * populated with the message class and message attributes. + * nMessageClassSize and/or nMessageAtributesSize may be + * overwritten to reflect the actual start and end of + * message class and message attributes. The max sizes of + * message class and message attributes will not exceed the + * values input by the client. The strings are not null + * terminated. + */ +typedef struct QOMX_STREAMING_PROTOCOLHEADERSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + QOMX_STREAMING_PROTOCOLMESSAGETYPE eMessageType; + OMX_U32 nMessageClassSize; + OMX_U32 nMessageAtributesSize; + OMX_U8 messageHeaders[1]; +} QOMX_STREAMING_PROTOCOLHEADERSTYPE; + +/** + * Enumeration of possible streaming network interfaces. + */ +typedef enum QOMX_STREAMING_NETWORKINTERFACETYPE +{ + QOMX_STREAMING_NETWORKINTERFACE_ANY_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_CDMA_SN_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_CDMA_AN_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_UMTS_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_SIO_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_CDMA_BCAST_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_WLAN_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_DUN_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_FLO_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_DVBH_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_STA_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_IPSEC_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_LO_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_MBMS_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_IWLAN_3GPP_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_IWLAN_3GPP2_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_MIP6_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_UW_FMC_IFACE, + QOMX_STREAMING_NETWORKINTERFACE_CMMB_IFACE +} QOMX_STREAMING_NETWORKINTERFACETYPE; + +/* + * Network interface. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes (including size of + protocolErrorText parameter) + * nVersion : OMX specification version information + * eNetworkInterface : Network interface the component may use + */ +typedef struct QOMX_PARAM_STREAMING_NETWORKINTERFACE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + QOMX_STREAMING_NETWORKINTERFACETYPE eNetworkInterface; +} QOMX_PARAM_STREAMING_NETWORKINTERFACE; + +/** + * Enumeration of UnitType for DownloadProgress + */ +typedef enum QOMX_DOWNLOADPROGRESSUNITSTYPE +{ + QOMX_DOWNLOADPROGRESSUNITSTYPE_TIME, + QOMX_DOWNLOADPROGRESSUNITSTYPE_DATA +} QOMX_DOWNLOADPROGRESSUNITSTYPE; + + +/** + * DownloadProgress units + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes (including size of + protocolEventText parameter) + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eUnitsType : Specifies the type of units type in + * which download prgoress should be + * reported + */ +typedef struct QOMX_CONFIG_STREAMING_DOWNLOADPROGRESSUNITS +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_DOWNLOADPROGRESSUNITSTYPE eUnitsType; +} QOMX_CONFIG_STREAMING_DOWNLOADPROGRESSUNITS; + + +/** + * Download Progress + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes (including size of + protocolEventText parameter) + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nDataDownloaded : specifies the amount of data downloaded + * in time or data scale (based on + * eUnitsType) from the media position + * specified by nStartOffset below. It + * starts at zero and progressively + * increases as more data is downloaded + * nCurrentStartOffset: specifies is the current download start + * position in time or data scale (based + * on eUnitsType) + */ +typedef struct QOMX_CONFIG_STREAMING_DOWNLOADPROGRESSTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nDataDownloaded; + OMX_U32 nCurrentStartOffset; +} QOMX_CONFIG_STREAMING_DOWNLOADPROGRESSTYPE; + +#if defined( __cplusplus ) +} +#endif /* end of macro __cplusplus */ + +#endif /* QOMX_STREAMINGEXTENSIONS_H_ */ + diff --git a/mm-core/inc/QOMX_VideoExtensions.h b/mm-core/inc/QOMX_VideoExtensions.h new file mode 100755 index 0000000..f261c07 --- /dev/null +++ b/mm-core/inc/QOMX_VideoExtensions.h @@ -0,0 +1,580 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2011 Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#ifndef __H_QOMX_VIDEOEXTENSIONS_H__ +#define __H_QOMX_VIDEOEXTENSIONS_H__ + +/*======================================================================== + +*//** @file QOMX_VideoExtensions.h + +@par FILE SERVICES: + Qualcomm extensions API for OpenMax IL Video. + + This file contains the description of the Qualcomm OpenMax IL + video extention interface, through which the IL client and OpenMax + components can access additional video capabilities. + +*//*====================================================================== */ + + +/*========================================================================== */ + +/*======================================================================== + + INCLUDE FILES FOR MODULE + +========================================================================== */ +#include +#include + +/*======================================================================== + + DEFINITIONS AND DECLARATIONS + +========================================================================== */ + +#if defined( __cplusplus ) +extern "C" +{ +#endif /* end of macro __cplusplus */ + +/* Video extension strings */ +#define OMX_QCOM_INDEX_PARAM_VIDEO_SYNTAXHDR "OMX.QCOM.index.param.video.SyntaxHdr" +#define OMX_QCOM_INDEX_PARAM_VIDEO_ENCODERMODE "OMX.QCOM.index.param.video.EncoderMode" +#define OMX_QCOM_INDEX_CONFIG_VIDEO_INTRAREFRESH "OMX.QCOM.index.config.video.IntraRefresh" +#define OMX_QCOM_INDEX_CONFIG_VIDEO_INTRAPERIOD "OMX.QCOM.index.config.video.IntraPeriod" +#define OMX_QCOM_INDEX_CONFIG_VIDEO_TEMPORALSPATIALTRADEOFF "OMX.QCOM.index.config.video.TemporalSpatialTradeOff" +#define OMX_QCOM_INDEX_CONFIG_VIDEO_MBCONCEALMENTREPORTING "OMX.QCOM.index.config.video.MBConcealmentReporting" +#define OMX_QCOM_INDEX_PARAM_VIDEO_EXTRADATAMULTISLICEINFO "OMX.QCOM.index.param.video.ExtraDataMultiSliceInfo" /**< reference: QOMX_ENABLETYPE */ +#define OMX_QCOM_INDEX_CONFIG_VIDEO_FLOWSTATUS "OMX.QCOM.index.config.video.FlowStatus" /**< reference: QOMX_FLOWSTATUSTYPE */ +#define OMX_QCOM_INDEX_PARAM_VIDEO_PICTURETYPEDECODE "OMX.QCOM.index.param.video.PictureTypeDecode" /**< reference: QOMX_VIDEO_DECODEPICTURETYPE */ +#define OMX_QCOM_INDEX_PARAM_VIDEO_SAMPLEASPECTRATIO "OMX.QCOM.index.param.video.SampleAspectRatio" /**< reference: QOMX_VIDEO_SAMPLEASPECTRATIO */ + +/* Video coding types */ +#define OMX_QCOM_INDEX_PARAM_VIDEO_DIVX "OMX.QCOM.index.param.video.DivX" +#define OMX_QCOM_INDEX_PARAM_VIDEO_VP "OMX.QCOM.index.param.video.VP" +#define OMX_QCOM_INDEX_PARAM_VIDEO_SPARK "OMX.QCOM.index.param.video.Spark" +#define OMX_QCOM_INDEX_PARAM_VIDEO_VC1 "OMX.QCOM.index.param.video.VC1" + +/** + * Enumeration used to define the extended video compression + * codings, not present in the OpenMax IL 1.1.2 specification. + * NOTE: This essentially refers to file extensions. If the + * coding is being used to specify the ENCODE type, then + * additional work must be done to configure the exact + * flavor of the compression to be used. + */ +typedef enum QOMX_VIDEO_CODINGTYPE +{ + QOMX_VIDEO_CodingDivX = 0x7F000001, /**< all versions of DivX */ + QOMX_VIDEO_CodingVP = 0x7F000002, /**< all versions of On2 VP codec */ + QOMX_VIDEO_CodingSpark = 0x7F000003, /**< Sorenson Spark */ + QOMX_VIDEO_CodingVC1 = 0x7F000004, /**< VC-1 */ + QOMX_VIDEO_MPEG1 = 0x7F000005 /**< MPEG-1 */ +} QOMX_VIDEO_CODINGTYPE; + +/** + * DivX Versions + */ +typedef enum QOMX_VIDEO_DIVXFORMATTYPE { + QOMX_VIDEO_DIVXFormatUnused = 0x01, /**< Format unused or unknown */ + QOMX_VIDEO_DIVXFormat311 = 0x02, /**< DivX 3.11 */ + QOMX_VIDEO_DIVXFormat4 = 0x04, /**< DivX 4 */ + QOMX_VIDEO_DIVXFormat5 = 0x08, /**< DivX 5 */ + QOMX_VIDEO_DIVXFormat6 = 0x10, /**< DivX 6 */ + QOMX_VIDEO_DIVXFormatKhronosExtensions = 0x6F000000, + QOMX_VIDEO_DIVXFormatVendorStartUnused = 0x7F000000, + QOMX_VIDEO_DIVXFormatMax = 0x7FFFFFFF +} QOMX_VIDEO_DIVXFORMATTYPE; + +/** + * DivX profile types, each profile indicates support for + * various performance bounds. + */ +typedef enum QOMX_VIDEO_DIVXPROFILETYPE { + QOMX_VIDEO_DivXProfileqMobile = 0x01, /**< qMobile Profile */ + QOMX_VIDEO_DivXProfileMobile = 0x02, /**< Mobile Profile */ + QOMX_VIDEO_DivXProfileMT = 0x04, /**< Mobile Theatre Profile */ + QOMX_VIDEO_DivXProfileHT = 0x08, /**< Home Theatre Profile */ + QOMX_VIDEO_DivXProfileHD = 0x10, /**< High Definition Profile */ + QOMX_VIDEO_DIVXProfileKhronosExtensions = 0x6F000000, + QOMX_VIDEO_DIVXProfileVendorStartUnused = 0x7F000000, + QOMX_VIDEO_DIVXProfileMax = 0x7FFFFFFF +} QOMX_VIDEO_DIVXPROFILETYPE; + +/** + * DivX Video Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFormat : Version of DivX stream / data + * eProfile : Profile of DivX stream / data + */ +typedef struct QOMX_VIDEO_PARAM_DIVXTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_VIDEO_DIVXFORMATTYPE eFormat; + QOMX_VIDEO_DIVXPROFILETYPE eProfile; +} QOMX_VIDEO_PARAM_DIVXTYPE; + +/** + * VP Versions + */ +typedef enum QOMX_VIDEO_VPFORMATTYPE { + QOMX_VIDEO_VPFormatUnused = 0x01, /**< Format unused or unknown */ + QOMX_VIDEO_VPFormat6 = 0x02, /**< VP6 Video Format */ + QOMX_VIDEO_VPFormat7 = 0x04, /**< VP7 Video Format */ + QOMX_VIDEO_VPFormat8 = 0x08, /**< VP8 Video Format */ + QOMX_VIDEO_VPFormatKhronosExtensions = 0x6F000000, + QOMX_VIDEO_VPFormatVendorStartUnused = 0x7F000000, + QOMX_VIDEO_VPFormatMax = 0x7FFFFFFF +} QOMX_VIDEO_VPFORMATTYPE; + +/** + * VP profile types, each profile indicates support for various + * encoding tools. + */ +typedef enum QOMX_VIDEO_VPPROFILETYPE { + QOMX_VIDEO_VPProfileSimple = 0x01, /**< Simple Profile, applies to VP6 only */ + QOMX_VIDEO_VPProfileAdvanced = 0x02, /**< Advanced Profile, applies to VP6 only */ + QOMX_VIDEO_VPProfileVersion0 = 0x04, /**< Version 0, applies to VP7 and VP8 */ + QOMX_VIDEO_VPProfileVersion1 = 0x08, /**< Version 1, applies to VP7 and VP8 */ + QOMX_VIDEO_VPProfileVersion2 = 0x10, /**< Version 2, applies to VP8 only */ + QOMX_VIDEO_VPProfileVersion3 = 0x20, /**< Version 3, applies to VP8 only */ + QOMX_VIDEO_VPProfileKhronosExtensions = 0x6F000000, + QOMX_VIDEO_VPProfileVendorStartUnused = 0x7F000000, + QOMX_VIDEO_VPProfileMax = 0x7FFFFFFF +} QOMX_VIDEO_VPPROFILETYPE; + +/** + * VP Video Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFormat : Format of VP stream / data + * eProfile : Profile or Version of VP stream / data + */ +typedef struct QOMX_VIDEO_PARAM_VPTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_VIDEO_VPFORMATTYPE eFormat; + QOMX_VIDEO_VPPROFILETYPE eProfile; +} QOMX_VIDEO_PARAM_VPTYPE; + +/** + * Spark Versions + */ +typedef enum QOMX_VIDEO_SPARKFORMATTYPE { + QOMX_VIDEO_SparkFormatUnused = 0x01, /**< Format unused or unknown */ + QOMX_VIDEO_SparkFormat0 = 0x02, /**< Video Format Version 0 */ + QOMX_VIDEO_SparkFormat1 = 0x04, /**< Video Format Version 1 */ + QOMX_VIDEO_SparkFormatKhronosExtensions = 0x6F000000, + QOMX_VIDEO_SparkFormatVendorStartUnused = 0x7F000000, + QOMX_VIDEO_SparkFormatMax = 0x7FFFFFFF +} QOMX_VIDEO_SPARKFORMATTYPE; + +/** + * Spark Video Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFormat : Version of Spark stream / data + */ +typedef struct QOMX_VIDEO_PARAM_SPARKTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_VIDEO_SPARKFORMATTYPE eFormat; +} QOMX_VIDEO_PARAM_SPARKTYPE; + +/** + * VC-1 profile types, each profile indicates support for + * various encoding tools. + */ +typedef enum QOMX_VIDEO_VC1PROFILETYPE { + QOMX_VIDEO_VC1ProfileSimple = 0x01, /**< Simple Profile */ + QOMX_VIDEO_VC1ProfileMain = 0x02, /**< Main Profile */ + QOMX_VIDEO_VC1ProfileAdvanced = 0x04, /**< Advanced Profile */ + QOMX_VIDEO_VC1ProfileKhronosExtensions = 0x6F000000, + QOMX_VIDEO_VC1ProfileVendorStartUnused = 0x7F000000, + QOMX_VIDEO_VC1ProfileMax = 0x7FFFFFFF +} QOMX_VIDEO_VC1PROFILETYPE; + +/** + * VC-1 level types, each level indicates support for various + * performance bounds. + */ +typedef enum QOMX_VIDEO_VC1LEVELTYPE { + QOMX_VIDEO_VC1LevelLow = 0x01, /**< Low Level, applies to simple and main profiles*/ + QOMX_VIDEO_VC1LevelMedium = 0x02, /**< Medium Level, applies to simple and main profiles */ + QOMX_VIDEO_VC1LevelHigh = 0x04, /**< High Level, applies to main profile only */ + QOMX_VIDEO_VC1Level0 = 0x08, /**< Level 0, applies to advanced profile only */ + QOMX_VIDEO_VC1Level1 = 0x10, /**< Level 1, applies to advanced profile only */ + QOMX_VIDEO_VC1Level2 = 0x20, /**< Level 2, applies to advanced profile only */ + QOMX_VIDEO_VC1Level3 = 0x40, /**< Level 3, applies to advanced profile only */ + QOMX_VIDEO_VC1Level4 = 0x80, /**< Level 4, applies to advanced profile only */ + QOMX_VIDEO_VC1LevelKhronosExtensions = 0x6F000000, + QOMX_VIDEO_VC1LevelVendorStartUnused = 0x7F000000, + QOMX_VIDEO_VC1LevelMax = 0x7FFFFFFF +} QOMX_VIDEO_VC1LEVELTYPE; + +/** + * VC-1 Video Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eProfile : Profile of VC-1 stream / data + * eLevel : Level of VC-1 stream / data + */ +typedef struct QOMX_VIDEO_PARAM_VC1TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_VIDEO_VC1PROFILETYPE eProfile; + QOMX_VIDEO_VC1LEVELTYPE eLevel; +} QOMX_VIDEO_PARAM_VC1TYPE; + +/** + * Extended MPEG-4 level types not defined in the OpenMax IL + * 1.1.2 specification, each level indicates support for various + * frame sizes, bit rates, decoder frame rates. + */ +typedef enum QOMX_VIDEO_MPEG4LEVELTYPE { + QOMX_VIDEO_MPEG4Level6 = 0x7F000001, /**< Level 6 */ + QOMX_VIDEO_MPEG4Level7 = 0x7F000002, /**< Level 7 */ + QOMX_VIDEO_MPEG4Level8 = 0x7F000003, /**< Level 8 */ + QOMX_VIDEO_MPEG4Level9 = 0x7F000004, /**< Level 9 */ + QOMX_VIDEO_MPEG4LevelMax = 0x7FFFFFFF +} QOMX_VIDEO_MPEG4LEVELTYPE; + +/** + * This structure is used in retrieving the syntax header from a + * video encoder component, or setting the out of band syntax + * header configuration data on a video decoder component. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * nBytes : When used with OMX_GetParameter for the encoder + * component, it is a read-write field. When + * QOMX_VIDEO_SYNTAXHDRTYPE is passed in + * OMX_GetParameter this is the size of the buffer + * array pointed by data field. When the + * OMX_GetParameter call returns this is the + * amount of data within the buffer array. + * + * The IL client needs to allocate the buffer + * array and then request for the syntax header. + * If the size of buffer array to allocate is + * unknown to the IL client, then it can call + * OMX_GetParamter with nBytes set to 0. In this + * case, when OMX_GetParameter returns, the nBytes + * field will be set to the size of the syntax + * header. IL Client can then allocate a buffer of + * this size and call OMX_GetParamter again. + * + * When used with OMX_SetParameter for the decoder + * component, it is a read-only field specifying + * the amount of data in the buffer array. + * data : The syntax header data. The format of the + * syntax header is specific to the video codec, + * and is described below. + * + * H.263 : N/A + * H.264 : The SPS and PPS parameter sets + * MPEG-4 : The VO, VOS, and VOL header + * WMV7 : The "Extra Data" info, in the ASF Stream + * Properties Object. + * WMV8 : The "Extra Data" info, in the ASF Stream + * Properties Object. + * WMV9 SP/MP : The STRUCT_C portion of the sequence layer + * meta data, defined in Table 263 of the VC-1 + * specification. + * VC-1 SP/MP : The STRUCT_C portion of the sequence layer + * meta data, defined in Table 263 of the VC-1 + * specification. + * VC-1 AP : The sequence and entry point header + * DivX 3 : N/A + * DivX 4.x : The VO, VOS, and VOL header + * DivX 5.x : The VO, VOS, and VOL header + * DivX 6.x : The VO, VOS, and VOL header + * VP6 : N/A + * Spark : N/A + */ +typedef struct QOMX_VIDEO_SYNTAXHDRTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nBytes; + OMX_U8 data[1]; +} QOMX_VIDEO_SYNTAXHDRTYPE; + + +/** + * Enumeration used to define the extended video intra refresh types, not + * present in the OpenMax IL 1.1.2 specification. + * + * ENUMS: + * IntraRefreshRandom : Random intra refresh mode. + */ +typedef enum QOMX_VIDEO_INTRAREFRESHTYPE +{ + QOMX_VIDEO_IntraRefreshRandom = 0x7F100000 +} QOMX_VIDEO_INTRAREFRESHTYPE; + + +/** + * This structure is used to configure the intra periodicity for encoder. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * nIDRPeriod : Defines the periodicity of IDR occurrence. This specifies + * coding a frame as IDR after a specific number of intra + * frames. The periodicity of intra frame coding is specified by + * the nPFrames. If nIDRPeriod is set to 0, only the first + * frame of the encode session is an IDR frame. This field is + * ignored for non-AVC codecs and is used only for codecs that + * support IDR Period. + * nPFrames : Specifies the number of P frames between each I Frame. + * nBFrames : Specifies the number of B frames between each I Frame. + */ +typedef struct QOMX_VIDEO_INTRAPERIODTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nIDRPeriod; + OMX_U32 nPFrames; + OMX_U32 nBFrames; +} QOMX_VIDEO_INTRAPERIODTYPE; + + +/** + * Enumeration used to define the extended video extra data payload types not + * present in the OpenMax IL 1.1.2 specification. + * + * ENUMS: + * VideoMultiSliceInfo : Multi slice layout information + * + * Slice information layout: + * First 4 bytes = Number of Slice Entries + * + * Then individual slice entries: 8 bytes per entry. + * Slice1 information: offset (4 bytes), Length (4 bytes) + * Slice2 information: offset (4 bytes), Length (4 bytes) + * Slice3 information: offset (4 bytes), Length (4 bytes) + * ................................... + * ................................... + * SliceN information: offset (4 bytes), Length (4 bytes) + * + * + * VideoNumConcealedMB : Number of concealed MBs + * + * The data array consists of an unsigned 32-bit size field + * indicating the number of concealed macroblocks in the + * uncompressed frame. + * + * + * QOMX_ExtraDataOMXIndex : Indicates that the data payload contains an + * OpenMax index and associated payload. + * + * The data of the extra data payload shall contain the value of the + * OMX_INDEXTYPE corresponding to the requested operation as an unsigned + * 32 bit number occupying the first four bytes of the payload. The index + * will be immediately followed by the associated structure. Padding bytes + * are appended to ensure 32 bit address alignment if needed. + */ +typedef enum QOMX_VIDEO_EXTRADATATYPE +{ + QOMX_ExtraDataVideoMultiSliceInfo = 0x7F100000, + QOMX_ExtraDataVideoNumConcealedMB, + QOMX_ExtraDataOMXIndex, + QOMX_ExtraDataHDCPEncryptionInfo +} QOMX_VIDEO_EXTRADATATYPE; + + +/** + * Enumeration used to define the video encoder modes + * + * ENUMS: + * EncoderModeDefault : Default video recording mode. + * All encoder settings made through + * OMX_SetParameter/OMX_SetConfig are applied. No + * parameter is overridden. + * EncoderModeMMS : Video recording mode for MMS (Multimedia Messaging + * Service). This mode is similar to EncoderModeDefault + * except that here the Rate control mode is overridden + * internally and set as a variant of variable bitrate with + * variable frame rate. After this mode is set if the IL + * client tries to set OMX_VIDEO_CONTROLRATETYPE via + * OMX_IndexParamVideoBitrate that would be rejected. For + * this, client should set mode back to EncoderModeDefault + * first and then change OMX_VIDEO_CONTROLRATETYPE. + */ +typedef enum QOMX_VIDEO_ENCODERMODETYPE +{ + QOMX_VIDEO_EncoderModeDefault = 0x01, + QOMX_VIDEO_EncoderModeMMS = 0x02, + QOMX_VIDEO_EncoderModeMax = 0x7FFFFFFF +} QOMX_VIDEO_ENCODERMODETYPE; + +/** + * This structure is used to set the video encoder mode. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * nMode : defines the video encoder mode + */ +typedef struct QOMX_VIDEO_PARAM_ENCODERMODETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + QOMX_VIDEO_ENCODERMODETYPE nMode; +} QOMX_VIDEO_PARAM_ENCODERMODETYPE; + + +/** + * This structure is used to set the temporal (picture rate) - spatial + * (picture quality) trade-off factor. + * This setting is only valid when rate control is enabled and set to a mode + * with variable frame rate. For all other rate control modes this setting is + * ignored. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * nTSFactor : temporal-spatial tradeoff factor value in the range of 0-100. + * A factor of 0 won't emphasizes picture rate in rate + * control decisions at all i.e only picture quality is emphasized. For + * increasing values from 1 to 99 the emphasis of picture rate in rate + * control decisions increases. A factor of 100 emphasizes only picture rate + * in rate control decisions. + */ +typedef struct QOMX_VIDEO_TEMPORALSPATIALTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nTSFactor; +} QOMX_VIDEO_TEMPORALSPATIALTYPE; + +/** + * This structure is used to enable or disable the MB concealmenet reporting + * for the uncompressed frames emitted from the port. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * bEnableMBConcealmentReporting : Flag indicating whether MB concealment + * reporting is enabled or disabled. + * OMX_TRUE: Enables MB concealment reporting + * OMX_FALSE: Disables MB concealment reporting + */ +typedef struct QOMX_VIDEO_MBCONCEALMENTREPORTINGTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnableMBConcealmentReporting; +} QOMX_VIDEO_MBCONCEALMENTREPORTINGTYPE; + +/** + * Specifies the extended picture types. These values should be + * OR'd along with the types defined in OMX_VIDEO_PICTURETYPE to + * signal all pictures types which are allowed. + * + * ENUMS: + * H.264 Specific Picture Types: IDR + */ +typedef enum QOMX_VIDEO_PICTURETYPE { + QOMX_VIDEO_PictureTypeIDR = OMX_VIDEO_PictureTypeVendorStartUnused + 0x1000 +} QOMX_VIDEO_PICTURETYPE; + +/** + * This structure is used to configure the processing of + * specific picture types. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * nPictureTypes : Specifies the picture type(s) + * that shall be processed. The value consists + * of the desired picture types, defined by the + * OMX_VIDEO_PICTURETYPE and + * QOMX_VIDEO_PICTURETYPE enumerations, OR'd to + * signal all the pictures types which are + * allowed. + */ +typedef struct QOMX_VIDEO_DECODEPICTURETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nPictureTypes; +} QOMX_VIDEO_DECODEPICTURETYPE; + +/** + * This structure describes the sample aspect ratio information. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * nWidth : Specifies the horizontal aspect size of + * the sample + * nHeight : Specifies the vertical aspect size of the + * sample + */ +typedef struct QOMX_VIDEO_SAMPLEASPECTRATIO { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U16 nWidth; + OMX_U16 nHeight; +} QOMX_VIDEO_SAMPLEASPECTRATIO; + +#if defined( __cplusplus ) +} +#endif /* end of macro __cplusplus */ + +#endif /* end of macro __H_QOMX_VIDEOEXTENSIONS_H__ */ diff --git a/mm-core/inc/drmplay_version.h b/mm-core/inc/drmplay_version.h new file mode 100755 index 0000000..e3562f3 --- /dev/null +++ b/mm-core/inc/drmplay_version.h @@ -0,0 +1,34 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#ifndef DRMPLAY_VERSION_H +#define DRMPLAY_VERSION_H + +#define DRMPLAY_API_VERSION ".101" + +#endif /* DRMPLAY_VERSION_H */ diff --git a/mm-core/inc/qc_omx_common.h b/mm-core/inc/qc_omx_common.h new file mode 100755 index 0000000..a673d3c --- /dev/null +++ b/mm-core/inc/qc_omx_common.h @@ -0,0 +1,65 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + +*//** @file qc_omx_common.h + This module contains the definitions of the OpenMAX core. + +*//*========================================================================*/ + +#ifndef QC_OMX_COMMON_H +#define QC_OMX_COMMON_H + + +#include // Standard IO +#include "OMX_Core.h" // OMX API +#include "OMX_QCOMExtns.h" // OMX API + +#define OMX_CORE_MAX_CMP 1 // MAX Components supported +#define OMX_CORE_MAX_CMP_ROLES 1 // MAX Roles per component +#define OMX_SPEC_VERSION 0x00000101 // OMX Version + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void * (*create_qc_omx_component)(void); + +#ifdef _ANDROID_ +#define LOG_TAG "QC_CORE" +#endif +#include "qc_omx_msg.h" + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/mm-core/inc/qc_omx_component.h b/mm-core/inc/qc_omx_component.h new file mode 100755 index 0000000..ad226d0 --- /dev/null +++ b/mm-core/inc/qc_omx_component.h @@ -0,0 +1,183 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o m p o n e n t I n t e r f a c e + +*//** @file qc_omx_component.h + This module contains the abstract interface for the OpenMAX components. + +*//*========================================================================*/ + +#ifndef QC_OMX_COMPONENT_H +#define QC_OMX_COMPONENT_H +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// +#include "OMX_Core.h" +#include "OMX_Component.h" + +class qc_omx_component +{ + +public: + /* single member to hold the vtable */ + OMX_COMPONENTTYPE m_cmp; + +public: + + // this is critical, otherwise, sub class destructor will not be called + virtual ~qc_omx_component(){} + + // Initialize the component after creation + virtual OMX_ERRORTYPE component_init(OMX_IN OMX_STRING componentName)=0; + + /*******************************************************************/ + /* Standard OpenMAX Methods */ + /*******************************************************************/ + + // Query the component for its information + virtual + OMX_ERRORTYPE get_component_version(OMX_HANDLETYPE cmp_handle, + OMX_STRING cmp_name, + OMX_VERSIONTYPE* cmp_version, + OMX_VERSIONTYPE* spec_version, + OMX_UUIDTYPE* cmp_UUID)=0; + + // Invoke a command on the component + virtual + OMX_ERRORTYPE send_command(OMX_HANDLETYPE cmp_handle, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmd_data)=0; + + // Get a Parameter setting from the component + virtual + OMX_ERRORTYPE get_parameter(OMX_HANDLETYPE cmp_handle, + OMX_INDEXTYPE param_index, + OMX_PTR param_data)=0; + + // Send a parameter structure to the component + virtual + OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE cmp_handle, + OMX_INDEXTYPE param_index, + OMX_PTR param_data)=0; + + // Get a configuration structure from the component + virtual + OMX_ERRORTYPE get_config(OMX_HANDLETYPE cmp_handle, + OMX_INDEXTYPE config_index, + OMX_PTR config_data)=0; + + // Set a component configuration value + virtual + OMX_ERRORTYPE set_config(OMX_HANDLETYPE cmp_handle, + OMX_INDEXTYPE config_index, + OMX_PTR config_data)=0; + + // Translate the vendor specific extension string to + // standardized index type + virtual + OMX_ERRORTYPE get_extension_index(OMX_HANDLETYPE cmp_handle, + OMX_STRING paramName, + OMX_INDEXTYPE* indexType)=0; + + // Get Current state information + virtual + OMX_ERRORTYPE get_state(OMX_HANDLETYPE cmp_handle, + OMX_STATETYPE* state)=0; + + // Component Tunnel Request + virtual + OMX_ERRORTYPE component_tunnel_request(OMX_HANDLETYPE cmp_handle, + OMX_U32 port, + OMX_HANDLETYPE peer_component, + OMX_U32 peer_port, + OMX_TUNNELSETUPTYPE* tunnel_setup)=0; + + // Use a buffer already allocated by the IL client + // or a buffer already supplied by a tunneled component + virtual + OMX_ERRORTYPE use_buffer(OMX_HANDLETYPE cmp_handle, + OMX_BUFFERHEADERTYPE** buffer_hdr, + OMX_U32 port, + OMX_PTR app_data, + OMX_U32 bytes, + OMX_U8* buffer)=0; + + + // Request that the component allocate new buffer and associated header + virtual + OMX_ERRORTYPE allocate_buffer(OMX_HANDLETYPE cmp_handle, + OMX_BUFFERHEADERTYPE** buffer_hdr, + OMX_U32 port, + OMX_PTR app_data, + OMX_U32 bytes)=0; + + // Release the buffer and associated header from the component + virtual + OMX_ERRORTYPE free_buffer(OMX_HANDLETYPE cmp_handle, + OMX_U32 port, + OMX_BUFFERHEADERTYPE* buffer)=0; + + // Send a filled buffer to an input port of a component + virtual + OMX_ERRORTYPE empty_this_buffer(OMX_HANDLETYPE cmp_handle, + OMX_BUFFERHEADERTYPE* buffer)=0; + + // Send an empty buffer to an output port of a component + virtual + OMX_ERRORTYPE fill_this_buffer(OMX_HANDLETYPE cmp_handle, + OMX_BUFFERHEADERTYPE* buffer)=0; + + // Set callbacks + virtual + OMX_ERRORTYPE set_callbacks( OMX_HANDLETYPE cmp_handle, + OMX_CALLBACKTYPE* callbacks, + OMX_PTR app_data)=0; + + // Component De-Initialize + virtual + OMX_ERRORTYPE component_deinit( OMX_HANDLETYPE cmp_handle)=0; + + // Use the Image already allocated via EGL + virtual + OMX_ERRORTYPE use_EGL_image(OMX_HANDLETYPE cmp_handle, + OMX_BUFFERHEADERTYPE** buffer_hdr, + OMX_U32 port, + OMX_PTR app_data, + void* egl_image)=0; + + // Component Role enum + virtual + OMX_ERRORTYPE component_role_enum( OMX_HANDLETYPE cmp_handle, + OMX_U8* role, + OMX_U32 index)=0; + +}; +#endif /* QC_OMX_COMPONENT_H */ diff --git a/mm-core/inc/qc_omx_msg.h b/mm-core/inc/qc_omx_msg.h new file mode 100644 index 0000000..bc7d034 --- /dev/null +++ b/mm-core/inc/qc_omx_msg.h @@ -0,0 +1,86 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*========================================================================== + O p e n M A X w r a p p e r s + O p e n M A X C o r e + +*//** @file qc_omx_msg.h + This module contains the definitions of the OpenMAX core. + +*//*========================================================================*/ + +#ifndef _QC_OMX_MSG_H_ +#define _QC_OMX_MSG_H_ + +#ifdef _ENABLE_QC_MSG_LOG_ + #ifdef _ANDROID_ + #include + + #ifdef __cplusplus + extern "C" { + #endif + + #ifndef LOGE + #define LOGE ALOGE + #endif + + #ifndef LOGW + #define LOGW ALOGW + #endif + + #ifndef LOGD + #define LOGD ALOGD + #endif + + #ifndef LOGV + #define LOGV ALOGV + #endif + + #ifndef LOGI + #define LOGI ALOGI + #endif + + #ifdef __cplusplus + } + #endif + + #define DEBUG_PRINT_ERROR LOGE + #define DEBUG_PRINT LOGI + #define DEBUG_DETAIL LOGV + #else + #define DEBUG_PRINT_ERROR printf + #define DEBUG_PRINT printf + #define DEBUG_DETAIL printf + #endif // _ANDROID_ +#else + #define DEBUG_PRINT_ERROR + #define DEBUG_PRINT + #define DEBUG_DETAIL +#endif // _ENABLE_QC_MSG_LOG_ + +#endif // _QC_OMX_MSG_H_ diff --git a/mm-core/src/7627A/qc_registry_table.c b/mm-core/src/7627A/qc_registry_table.c new file mode 100755 index 0000000..775cffd --- /dev/null +++ b/mm-core/src/7627A/qc_registry_table.c @@ -0,0 +1,812 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2011-2012 Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxH264Dec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.ittiam.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxIttiamVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.ittiam.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxIttiamVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMpeg4Dec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.ittiam.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxIttiamVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMpeg4Dec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMpeg4Dec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmvDec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.real", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxrv9Dec.so", + { + "video_decoder.real" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMpeg4Dec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVidEnc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.spark", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMpeg4Dec.so", + { + "video_decoder.spark" + } + }, + { + "OMX.qcom.video.decoder.vp", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxOn2Dec.so", + { + "video_decoder.vp" + } + }, + { + "OMX.qcom.video.decoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVp8Dec.so", + { + "video_decoder.vp8" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVidEnc.so", + { + "video_encoder.h263", + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVidEnc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.audio.decoder.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxMp3Dec.so", + #else + "libmm-adec-omxmp3.so.1", + #endif + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAacDec.so", + #else + "libmm-adec-omxaac.so.1", + #endif + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxMp3Dec.so", + #else + "libmm-adec-omxmp3.so.1", + #endif + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAacDec.so", + #else + "libmm-adec-omxaac.so.1", + #endif + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrDec.so", + #else + "libmm-adec-omxamr.so.1", + #endif + { + "audio_decoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrDec.so", + #else + "libmm-adec-omxamr.so.1", + #endif + { + "audio_decoder.amrnb" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAacEnc.so", + #else + "libmm-aenc-omxaac.so.1", + #endif + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13Hw", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxQcelpHwDec.so", + #else + "libmm-adec-omxQcelp13.so.1", + #endif + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.Qcelp13Hw", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxQcelpHwDec.so", + #else + "libmm-adec-omxQcelp13.so.1", + #endif + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrchw", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxEvrcHwDec.so", + #else + "libmm-adec-omxevrc.so.1", + #endif + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxEvrcHwDec.so", + #else + "libmm-adec-omxevrc.so.1", + #endif + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.amr", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrEnc.so", + #else + "libmm-aenc-omxamr.so.1", + #endif + { + "audio_encoder.amr" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxWmaDec.so", + #else + "libmm-adec-omxwma.so.1", + #endif + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxWmaDec.so", + #else + "libmm-adec-omxwma.so.1", + #endif + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxWmaDec.so", + #else + "libmm-adec-omxwma.so.1", + #endif + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxWmaDec.so", + #else + "libmm-adec-omxwma.so.1", + #endif + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.amrwb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrwbDec.so", + #else + "libmm-adec-omxamrwb.so.1", + #endif + { + "audio_decoder.amrwb" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrwb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrwbDec.so", + #else + "libmm-adec-omxamrwb.so.1", + #endif + { + "audio_decoder.amrwb" + } + }, + { + "OMX.qcom.audio.decoder.amrwbp", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrwbDec.so", + #else + "libmm-adec-omxamrwb.so.1", + #endif + { + "audio_decoder.amrwbp" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrwbp", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrwbDec.so", + #else + "libmm-adec-omxamrwb.so.1", + #endif + { + "audio_decoder.amrwbp" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxQcelp13Enc.so", + #else + "libmm-aenc-omxqcelp13.so.1", + #endif + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxQcelp13Enc.so", + #else + "libmm-aenc-omxqcelp13.so.1", + #endif + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxEvrcEnc.so", + #else + "libmm-aenc-omxevrc.so.1", + #endif + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxEvrcEnc.so", + #else + "libmm-aenc-omxevrc.so.1", + #endif + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.ac3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAc3HwDec.so", + { + "audio_decoder.ac3" + } + }, + { + "OMX.qcom.audio.decoder.eac3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAc3HwDec.so", + { + "audio_decoder.eac3" + } + }, +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/7627A/qc_registry_table_android.c b/mm-core/src/7627A/qc_registry_table_android.c new file mode 100755 index 0000000..4232fb1 --- /dev/null +++ b/mm-core/src/7627A/qc_registry_table_android.c @@ -0,0 +1,711 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxH264Dec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.ittiam.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxIttiamVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.ittiam.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxIttiamVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMpeg4Dec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.ittiam.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxIttiamVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + //Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMpeg4Dec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + //Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMpeg4Dec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmvDec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.real", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxrv9Dec.so", + { + "video_decoder.real" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMpeg4Dec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.decoder.spark", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMpeg4Dec.so", + { + "video_decoder.spark" + } + }, + { + "OMX.qcom.video.decoder.vp", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxOn2Dec.so", + { + "video_decoder.vp" + } + }, + { + "OMX.qcom.video.decoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVp8Dec.so", + { + "video_decoder.vp8" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVidEnc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVidEnc.so", + { + "video_encoder.h263" + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVidEnc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.audio.decoder.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMp3Dec.so", + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13Hw", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelpHwDec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrchw", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcHwDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.amrwbp", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrwbDec.so", + { + "audio_decoder.amrwbp" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxEvrcEnc.so", + #else + "libmm-aenc-omxevrc.so.1", + #endif + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxQcelp13Enc.so", + #else + "libmm-aenc-omxqcelp13.so.1", + #endif + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.ac3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAc3HwDec.so", + { + "audio_decoder.ac3" + } + }, + { + "OMX.qcom.audio.decoder.eac3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAc3HwDec.so", + { + "audio_decoder.eac3" + } + }, +#ifndef _ANDROID_ + { + "OMX.qcom.audio.decoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrDec.so", + { + "audio_decoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.amrwb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrwbDec.so", + { + "audio_decoder.amrwb" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMp3Dec.so", + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrDec.so", + { + "audio_decoder.amrnb" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.Qcelp13Hw", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelpHwDec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcHwDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.amr", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amr" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrwb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + } + NULL, // Shared object library handle + "libOmxAmrwbDec.so", + { + "audio_decoder.amrwb" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrwbp", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrwbDec.so", + { + "audio_decoder.amrwbp" + } + } +#endif +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/7630/qc_registry_table.c b/mm-core/src/7630/qc_registry_table.c new file mode 100644 index 0000000..169110f --- /dev/null +++ b/mm-core/src/7630/qc_registry_table.c @@ -0,0 +1,746 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009,2012 Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263", + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.audio.decoder.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxMp3Dec.so", + #else + "libmm-adec-omxmp3.so.1", + #endif + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAacDec.so", + #else + "libmm-adec-omxaac.so.1", + #endif + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxMp3Dec.so", + #else + "libmm-adec-omxmp3.so.1", + #endif + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAacDec.so", + #else + "libmm-adec-omxaac.so.1", + #endif + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrDec.so", + #else + "libmm-adec-omxamr.so.1", + #endif + { + "audio_decoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrDec.so", + #else + "libmm-adec-omxamr.so.1", + #endif + { + "audio_decoder.amrnb" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAacEnc.so", + #else + "libmm-aenc-omxaac.so.1", + #endif + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAacEnc.so", + #else + "libmm-aenc-omxaac.so.1", + #endif + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13Hw", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxQcelpHwDec.so", + #else + "libmm-adec-omxQcelp13.so.1", + #endif + { + "audio_decoder.Qcelp13" + } + }, +#ifdef _ANDROID_ + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, +#endif + { + "OMX.qcom.audio.decoder.tunneled.Qcelp13Hw", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxQcelpHwDec.so", + #else + "libmm-adec-omxQcelp13.so.1", + #endif + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxEvrcDec.so", + #else + "libmm-adec-omxevrc.so.1", + #endif + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxEvrcDec.so", + #else + "libmm-adec-omxevrc.so.1", + #endif + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.amr", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrEnc.so", + #else + "libmm-aenc-omxamr.so.1", + #endif + { + "audio_encoder.amr" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxWmaDec.so", + #else + "libmm-adec-omxwma.so.1", + #endif + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxWmaDec.so", + #else + "libmm-adec-omxwma.so.1", + #endif + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxWmaDec.so", + #else + "libmm-adec-omxwma.so.1", + #endif + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxWmaDec.so", + #else + "libmm-adec-omxwma.so.1", + #endif + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.amrwb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrwbDec.so", + #else + "libmm-adec-omxamrwb.so.1", + #endif + { + "audio_decoder.amrwb" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrwb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrwbDec.so", + #else + "libmm-adec-omxamrwb.so.1", + #endif + { + "audio_decoder.amrwb" + } + }, + { + "OMX.qcom.audio.decoder.amrwbp", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrwbDec.so", + #else + "libmm-adec-omxamrwb.so.1", + #endif + { + "audio_decoder.amrwbp" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrwbp", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAmrwbDec.so", + #else + "libmm-adec-omxamrwb.so.1", + #endif + { + "audio_decoder.amrwbp" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxQcelp13Enc.so", + #else + "libmm-aenc-omxqcelp13.so.1", + #endif + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxQcelp13Enc.so", + #else + "libmm-aenc-omxqcelp13.so.1", + #endif + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxEvrcEnc.so", + #else + "libmm-aenc-omxevrc.so.1", + #endif + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxEvrcEnc.so", + #else + "libmm-aenc-omxevrc.so.1", + #endif + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.adpcm", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAdpcmDec.so", + #else + "libmm-adec-omxadpcm.so.1", + #endif + { + "audio_decoder.adpcm" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.adpcm", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxAdpcmDec.so", + #else + "libmm-adec-omxadpcm.so.1", + #endif + { + "audio_decoder.adpcm" + } + } +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/7630/qc_registry_table_android.c b/mm-core/src/7630/qc_registry_table_android.c new file mode 100644 index 0000000..bc23fef --- /dev/null +++ b/mm-core/src/7630/qc_registry_table_android.c @@ -0,0 +1,568 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009,2011 Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + + +#include "qc_omx_core.h" +#include "drmplay_version.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263" + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.amrwbp", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrwbDec.so", + { + "audio_decoder.amrwbp" + } + }, + { + "drm.play" DRMPLAY_API_VERSION, + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libDrmPlay.so", + { + "drm.play" DRMPLAY_API_VERSION + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxEvrcEnc.so", + #else + "libmm-aenc-omxevrc.so.1", + #endif + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "libOmxQcelp13Enc.so", + #else + "libmm-aenc-omxqcelp13.so.1", + #endif + { + "audio_encoder.qcelp13" + } + }, +#ifndef _ANDROID_ + { + "OMX.qcom.audio.decoder.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMp3Dec.so", + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrDec.so", + { + "audio_decoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.amrwb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrwbDec.so", + { + "audio_decoder.amrwb" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMp3Dec.so", + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrDec.so", + { + "audio_decoder.amrnb" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.amr", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amr" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrwb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + } + NULL, // Shared object library handle + "libOmxAmrwbDec.so", + { + "audio_decoder.amrwb" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.amrwbp", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrwbDec.so", + { + "audio_decoder.amrwbp" + } + } +#endif +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/8250/qc_registry_table.c b/mm-core/src/8250/qc_registry_table.c new file mode 100644 index 0000000..5cc5e70 --- /dev/null +++ b/mm-core/src/8250/qc_registry_table.c @@ -0,0 +1,384 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-vdec-omx.so.1", +#else + "libOmxVdec.so", +#endif + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-vdec-omx.so.1", +#else + "libOmxVdec.so", +#endif + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-vdec-omx.so.1", +#else + "libOmxVdec.so", +#endif + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-vdec-omx.so.1", +#else + "libOmxVdec.so", +#endif + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-vdec-omx.so.1", +#else + "libOmxVdec.so", +#endif + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-venc-omx.so.1", +#else + "libOmxVidEnc.so", +#endif + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-venc-omx.so.1", +#else + "libOmxVidEnc.so", +#endif + { + "video_encoder.h263" + } + }, + { + "OMX.qcom.audio.decoder.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-adec-omxmp3.so.1", +#else + "libOmxMp3Dec.so", +#endif + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-adec-omxaac.so.1", +#else + "libOmxAacDec.so", +#endif + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-adec-omxmp3.so.1", +#else + "libOmxMp3Dec.so", +#endif + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-adec-omxaac.so.1", +#else + "libOmxAacDec.so", +#endif + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-aenc-omxaac.so.1", +#else + "libOmxAacEnc.so", +#endif + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-adec-omxQcelp13.so.1", +#else + "libOmxQcelp13Dec.so", +#endif + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-adec-omxevrc.so.1", +#else + "libOmxEvrcDec.so", +#endif + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-aenc-omxqcelp13.so.1", +#else + "libOmxQcelp13Enc.so", +#endif + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-aenc-omxevrc.so.1", +#else + "libOmxEvrcEnc.so", +#endif + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.amr", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle +#ifndef _ANDROID_ + "libmm-aenc-omxamr.so.1", +#else + "libOmxAmrEnc.so", +#endif + { + "audio_encoder.amr" + } + } +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/8250/qc_registry_table_android.c b/mm-core/src/8250/qc_registry_table_android.c new file mode 100644 index 0000000..0bd57b2 --- /dev/null +++ b/mm-core/src/8250/qc_registry_table_android.c @@ -0,0 +1,288 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVidEnc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVidEnc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVidEnc.so", + { + "video_encoder.h263" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + +#ifndef _ANDROID_ + { + "OMX.qcom.audio.decoder.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMp3Dec.so", + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMp3Dec.so", + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + } +#endif +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/8660/qc_registry_table.c b/mm-core/src/8660/qc_registry_table.c new file mode 100755 index 0000000..3253370 --- /dev/null +++ b/mm-core/src/8660/qc_registry_table.c @@ -0,0 +1,671 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Code Aurora Forum, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx311", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263", + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.audio.decoder.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMp3Dec.so", + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.multiaac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.mp3", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMp3Dec.so", + { + "audio_decoder.mp3" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.multiaac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wmaLossLess", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.wmaLossLess", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Enc.so", + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.tunneled.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcEnc.so", + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.adpcm", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAdpcmDec.so", + { + "audio_decoder.adpcm" + } + }, + { + "OMX.qcom.audio.decoder.tunneled.adpcm", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAdpcmDec.so", + { + "audio_decoder.adpcm" + } + }, + { + "OMX.qcom.file.muxer", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + + "libOmxMux.so", + { + "container_muxer.mp2" + } +}, + { + "OMX.qcom.audio.encoder.tunneled.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Enc.so", + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcEnc.so", + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amrnb" + } + }, +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/8660/qc_registry_table_android.c b/mm-core/src/8660/qc_registry_table_android.c new file mode 100755 index 0000000..2ab2cfc --- /dev/null +++ b/mm-core/src/8660/qc_registry_table_android.c @@ -0,0 +1,468 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Code Aurora Forum, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + + +#include "qc_omx_core.h" +#ifdef ENABLE_DRMPLAY +#include "drmplay_version.h" +#endif + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.avc.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx311", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.mpeg2", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg2" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263" + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wmaLossLess", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.encoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Enc.so", + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcEnc.so", + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.multiaac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, +#ifdef ENABLE_DRMPLAY + { + "drm.play" DRMPLAY_API_VERSION, + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libDrmPlay.so", + { + "drm.play" DRMPLAY_API_VERSION + } + }, + { + "OMX.qcom.file.muxer", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMux.so", + { + "container_muxer.mp2" + } + } +#endif +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/8960/qc_registry_table.c b/mm-core/src/8960/qc_registry_table.c new file mode 100755 index 0000000..ac47efc --- /dev/null +++ b/mm-core/src/8960/qc_registry_table.c @@ -0,0 +1,272 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Code Aurora Forum, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.file.muxer", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + + "libOmxMux.so", + { + "container_muxer.mp2" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx311", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263", + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.multiaac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/8960/qc_registry_table_android.c b/mm-core/src/8960/qc_registry_table_android.c new file mode 100755 index 0000000..72b178e --- /dev/null +++ b/mm-core/src/8960/qc_registry_table_android.c @@ -0,0 +1,463 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Code Aurora Forum, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.avc.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx311", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.mpeg2", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg2" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263" + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Enc.so", + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcEnc.so", + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.multiaac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "drm.play", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libDrmPlay.so", + { + "drm.play" + } + }, + { + "OMX.qcom.file.muxer", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMux.so", + { + "container_muxer.mp2" + } + } +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/8974/qc_registry_table.c b/mm-core/src/8974/qc_registry_table.c new file mode 100755 index 0000000..9d7c905 --- /dev/null +++ b/mm-core/src/8974/qc_registry_table.c @@ -0,0 +1,448 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Code Aurora Forum, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.file.muxer", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + + "libOmxMux.so", + { + "container_muxer.mp2" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx311", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, + { + "OMX.qcom.video.decoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vp8" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263", + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, +{ + "OMX.qcom.video.encoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.vp8", + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Enc.so", + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcEnc.so", + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.multiaac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/8974/qc_registry_table_android.c b/mm-core/src/8974/qc_registry_table_android.c new file mode 100755 index 0000000..9be7492 --- /dev/null +++ b/mm-core/src/8974/qc_registry_table_android.c @@ -0,0 +1,495 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Code Aurora Forum, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the registry table for the QCOM's OpenMAX core. + +*//*========================================================================*/ + + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.video.decoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.avc.secure", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.avc" + } + }, + { + "OMX.qcom.video.decoder.divx4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.divx311", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.divx" + } + }, + { + "OMX.qcom.video.decoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg4" + } + }, + { + "OMX.qcom.video.decoder.mpeg2", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.mpeg2" + } + }, + { + "OMX.qcom.video.decoder.vc1", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.wmv", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vc1" + } + }, + { + "OMX.qcom.video.decoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.h263" + } + }, +{ + "OMX.qcom.video.decoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVdec.so", + { + "video_decoder.vp8" + } + }, + { + "OMX.qcom.video.encoder.mpeg4", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.mpeg4" + } + }, + { + "OMX.qcom.video.encoder.h263", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.h263" + } + }, + { + "OMX.qcom.video.encoder.avc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.avc" + } + }, +{ + "OMX.qcom.video.encoder.vp8", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxVenc.so", + { + "video_encoder.vp8" + } + }, + { + "OMX.qcom.audio.decoder.Qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Dec.so", + { + "audio_decoder.Qcelp13" + } + }, + { + "OMX.qcom.audio.decoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcDec.so", + { + "audio_decoder.evrc" + } + }, + { + "OMX.qcom.audio.decoder.wma", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.wma10Pro", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxWmaDec.so", + { + "audio_decoder.wma" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacEnc.so", + { + "audio_encoder.aac" + } + }, + { + "OMX.qcom.audio.encoder.qcelp13", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxQcelp13Enc.so", + { + "audio_encoder.qcelp13" + } + }, + { + "OMX.qcom.audio.encoder.evrc", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxEvrcEnc.so", + { + "audio_encoder.evrc" + } + }, + { + "OMX.qcom.audio.encoder.amrnb", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAmrEnc.so", + { + "audio_encoder.amrnb" + } + }, + { + "OMX.qcom.audio.decoder.aac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "OMX.qcom.audio.decoder.multiaac", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxAacDec.so", + { + "audio_decoder.aac" + } + }, + { + "drm.play", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libDrmPlay.so", + { + "drm.play" + } + }, + { + "OMX.qcom.file.muxer", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "libOmxMux.so", + { + "container_muxer.mp2" + } + } +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/common/omx_core_cmp.cpp b/mm-core/src/common/omx_core_cmp.cpp new file mode 100755 index 0000000..dfe0466 --- /dev/null +++ b/mm-core/src/common/omx_core_cmp.cpp @@ -0,0 +1,406 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the implementation of the OpenMAX core Macros which + operate directly on the component. + +*//*========================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// +#include "qc_omx_common.h" +#include "omx_core_cmp.h" +#include "qc_omx_component.h" +#include + + +void * qc_omx_create_component_wrapper(OMX_PTR obj_ptr) +{ + qc_omx_component *pThis = (qc_omx_component *)obj_ptr; + OMX_COMPONENTTYPE* component = &(pThis->m_cmp); + memset(&pThis->m_cmp,0,sizeof(OMX_COMPONENTTYPE)); + + component->nSize = sizeof(OMX_COMPONENTTYPE); + component->nVersion.nVersion = OMX_SPEC_VERSION; + component->pApplicationPrivate = 0; + component->pComponentPrivate = obj_ptr; + + component->AllocateBuffer = &qc_omx_component_allocate_buffer; + component->FreeBuffer = &qc_omx_component_free_buffer; + component->GetParameter = &qc_omx_component_get_parameter; + component->SetParameter = &qc_omx_component_set_parameter; + component->SendCommand = &qc_omx_component_send_command; + component->FillThisBuffer = &qc_omx_component_fill_this_buffer; + component->EmptyThisBuffer = &qc_omx_component_empty_this_buffer; + component->GetState = &qc_omx_component_get_state; + component->GetComponentVersion = &qc_omx_component_get_version; + component->GetConfig = &qc_omx_component_get_config; + component->SetConfig = &qc_omx_component_set_config; + component->GetExtensionIndex = &qc_omx_component_get_extension_index; + component->ComponentTunnelRequest = &qc_omx_component_tunnel_request; + component->UseBuffer = &qc_omx_component_use_buffer; + component->SetCallbacks = &qc_omx_component_set_callbacks; + component->UseEGLImage = &qc_omx_component_use_EGL_image; + component->ComponentRoleEnum = &qc_omx_component_role_enum; + component->ComponentDeInit = &qc_omx_component_deinit; + return (void *)component; +} + + + +/************************************************************************/ +/* COMPONENT INTERFACE */ +/************************************************************************/ + +OMX_ERRORTYPE +qc_omx_component_init(OMX_IN OMX_HANDLETYPE hComp, OMX_IN OMX_STRING componentName) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_init %x\n",(unsigned)hComp); + + if(pThis) + { + // call the init fuction + eRet = pThis->component_init(componentName); + + if(eRet != OMX_ErrorNone) + { + // in case of error, please destruct the component created + delete pThis; + } + } + return eRet; +} + + +OMX_ERRORTYPE +qc_omx_component_get_version(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STRING componentName, + OMX_OUT OMX_VERSIONTYPE* componentVersion, + OMX_OUT OMX_VERSIONTYPE* specVersion, + OMX_OUT OMX_UUIDTYPE* componentUUID) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_get_version %x, %s , %x\n",(unsigned)hComp,componentName,(unsigned)componentVersion); + if(pThis) + { + eRet = pThis->get_component_version(hComp,componentName,componentVersion,specVersion,componentUUID); + } + return eRet; +} + +OMX_ERRORTYPE +qc_omx_component_send_command(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_send_command %x, %d , %d\n",(unsigned)hComp,(unsigned)cmd,(unsigned)param1); + + if(pThis) + { + eRet = pThis->send_command(hComp,cmd,param1,cmdData); + } + return eRet; +} + +OMX_ERRORTYPE +qc_omx_component_get_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_INOUT OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_get_parameter %x, %x , %d\n",(unsigned)hComp,(unsigned)paramData,paramIndex); + + if(pThis) + { + eRet = pThis->get_parameter(hComp,paramIndex,paramData); + } + return eRet; +} + +OMX_ERRORTYPE +qc_omx_component_set_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_IN OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_set_parameter %x, %x , %d\n",(unsigned)hComp,(unsigned)paramData,paramIndex); + + if(pThis) + { + eRet = pThis->set_parameter(hComp,paramIndex,paramData); + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_get_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_INOUT OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_get_config %x\n",(unsigned)hComp); + + if(pThis) + { + eRet = pThis->get_config(hComp, + configIndex, + configData); + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_set_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_IN OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_set_config %x\n",(unsigned)hComp); + + if(pThis) + { + eRet = pThis->set_config(hComp, + configIndex, + configData); + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_get_extension_index(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_STRING paramName, + OMX_OUT OMX_INDEXTYPE* indexType) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + if(pThis) + { + eRet = pThis->get_extension_index(hComp,paramName,indexType); + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_get_state(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STATETYPE* state) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_get_state %x\n",(unsigned)hComp); + + if(pThis) + { + eRet = pThis->get_state(hComp,state); + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_HANDLETYPE peerComponent, + OMX_IN OMX_U32 peerPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) +{ + DEBUG_PRINT("Error: qc_omx_component_tunnel_request Not Implemented\n"); + return OMX_ErrorNotImplemented; +} + + OMX_ERRORTYPE +qc_omx_component_use_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_use_buffer %x\n",(unsigned)hComp); + + if(pThis) + { + eRet = pThis->use_buffer(hComp, + bufferHdr, + port, + appData, + bytes, + buffer); + } + return eRet; +} + + +// qc_omx_component_allocate_buffer -- API Call + OMX_ERRORTYPE +qc_omx_component_allocate_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_allocate_buffer %x, %x , %d\n",(unsigned)hComp,(unsigned)bufferHdr,(unsigned)port); + + if(pThis) + { + eRet = pThis->allocate_buffer(hComp,bufferHdr,port,appData,bytes); + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_free_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_free_buffer[%d] %x, %x\n", (unsigned)port, (unsigned)hComp, (unsigned)buffer); + + if(pThis) + { + eRet = pThis->free_buffer(hComp,port,buffer); + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_empty_this_buffer %x, %x\n",(unsigned)hComp,(unsigned)buffer); + + if(pThis) + { + eRet = pThis->empty_this_buffer(hComp,buffer); + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_fill_this_buffer %x, %x\n",(unsigned)hComp,(unsigned)buffer); + if(pThis) + { + eRet = pThis->fill_this_buffer(hComp,buffer); + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_set_callbacks(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_CALLBACKTYPE* callbacks, + OMX_IN OMX_PTR appData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_set_callbacks %x, %x , %x\n",(unsigned)hComp,(unsigned)callbacks,(unsigned)appData); + + if(pThis) + { + eRet = pThis->set_callbacks(hComp,callbacks,appData); + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_deinit(OMX_IN OMX_HANDLETYPE hComp) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_deinit %x\n",(unsigned)hComp); + + if(pThis) + { + // call the deinit fuction first + OMX_STATETYPE state; + pThis->get_state(hComp,&state); + DEBUG_PRINT("Calling FreeHandle in state %d \n", state); + eRet = pThis->component_deinit(hComp); + // destroy the component. + delete pThis; + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_use_EGL_image(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN void* eglImage) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_use_EGL_image %x, %x , %d\n",(unsigned)hComp,(unsigned)bufferHdr,(unsigned)port); + if(pThis) + { + eRet = pThis->use_EGL_image(hComp,bufferHdr,port,appData,eglImage); + } + return eRet; +} + + OMX_ERRORTYPE +qc_omx_component_role_enum(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_U8* role, + OMX_IN OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorBadParameter; + qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL; + DEBUG_PRINT("OMXCORE: qc_omx_component_role_enum %x, %x , %d\n",(unsigned)hComp,(unsigned)role,(unsigned)index); + + if(pThis) + { + eRet = pThis->component_role_enum(hComp,role,index); + } + return eRet; +} diff --git a/mm-core/src/common/omx_core_cmp.h b/mm-core/src/common/omx_core_cmp.h new file mode 100755 index 0000000..1daf26e --- /dev/null +++ b/mm-core/src/common/omx_core_cmp.h @@ -0,0 +1,160 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + OpenMAX Core Macros interface. + +============================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// +#ifndef OMX_CORE_CMP_H +#define OMX_CORE_CMP_H + + + +#ifdef __cplusplus +extern "C" { +#endif + + +void * qc_omx_create_component_wrapper(OMX_PTR obj_ptr); + + +OMX_ERRORTYPE +qc_omx_component_init(OMX_IN OMX_HANDLETYPE hComp, OMX_IN OMX_STRING componentName); + + +OMX_ERRORTYPE +qc_omx_component_get_version(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STRING componentName, + OMX_OUT OMX_VERSIONTYPE* componentVersion, + OMX_OUT OMX_VERSIONTYPE* specVersion, + OMX_OUT OMX_UUIDTYPE* componentUUID); + +OMX_ERRORTYPE +qc_omx_component_send_command(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData); + +OMX_ERRORTYPE +qc_omx_component_get_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_INOUT OMX_PTR paramData); + +OMX_ERRORTYPE +qc_omx_component_set_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_IN OMX_PTR paramData); + +OMX_ERRORTYPE +qc_omx_component_get_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_INOUT OMX_PTR configData); + +OMX_ERRORTYPE +qc_omx_component_set_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_IN OMX_PTR configData); + +OMX_ERRORTYPE +qc_omx_component_get_extension_index(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_STRING paramName, + OMX_OUT OMX_INDEXTYPE* indexType); + +OMX_ERRORTYPE +qc_omx_component_get_state(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STATETYPE* state); + +OMX_ERRORTYPE +qc_omx_component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_HANDLETYPE peerComponent, + OMX_IN OMX_U32 peerPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup); + +OMX_ERRORTYPE +qc_omx_component_use_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer); + + +// qc_omx_component_allocate_buffer -- API Call +OMX_ERRORTYPE +qc_omx_component_allocate_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes); + +OMX_ERRORTYPE +qc_omx_component_free_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_BUFFERHEADERTYPE* buffer); + +OMX_ERRORTYPE +qc_omx_component_empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer); + +OMX_ERRORTYPE +qc_omx_component_fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer); + +OMX_ERRORTYPE +qc_omx_component_set_callbacks(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_CALLBACKTYPE* callbacks, + OMX_IN OMX_PTR appData); + +OMX_ERRORTYPE +qc_omx_component_deinit(OMX_IN OMX_HANDLETYPE hComp); + +OMX_ERRORTYPE +qc_omx_component_use_EGL_image(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN void* eglImage); + +OMX_ERRORTYPE +qc_omx_component_role_enum(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_U8* role, + OMX_IN OMX_U32 index); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/mm-core/src/common/qc_omx_core.c b/mm-core/src/common/qc_omx_core.c new file mode 100755 index 0000000..f332f65 --- /dev/null +++ b/mm-core/src/common/qc_omx_core.c @@ -0,0 +1,830 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the implementation of the OpenMAX core. + +*//*========================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +#include // dynamic library +#include +#include +#include +#include +#include +#include + +#include "qc_omx_core.h" +#include "omx_core_cmp.h" + +extern omx_core_cb_type core[]; +extern const unsigned int SIZE_OF_CORE; +static pthread_mutex_t lock_core = PTHREAD_MUTEX_INITIALIZER; + +/* ====================================================================== +FUNCTION + omx_core_load_cmp_library + +DESCRIPTION + Loads up the libary name mentioned in the argument + +PARAMETERS + None + +RETURN VALUE + Constructor for creating component instances. +========================================================================== */ +static create_qc_omx_component +omx_core_load_cmp_library(char *libname, void **handle_ptr) +{ + create_qc_omx_component fn_ptr = NULL; + if(handle_ptr) + { + DEBUG_PRINT("Dynamically Loading the library : %s\n",libname); + *handle_ptr = dlopen(libname,RTLD_NOW); + if(*handle_ptr) + { + fn_ptr = dlsym(*handle_ptr, "get_omx_component_factory_fn"); + + if(fn_ptr == NULL) + { + DEBUG_PRINT("Error: Library %s incompatible as QCOM OMX component loader - %s\n", + libname, dlerror()); + *handle_ptr = NULL; + } + } + else + { + DEBUG_PRINT("Error: Couldn't load %s: %s\n",libname,dlerror()); + } + } + return fn_ptr; +} + +/* ====================================================================== +FUNCTION + OMX_Init + +DESCRIPTION + This is the first function called by the application. + There is nothing to do here since components shall be loaded + whenever the get handle method is called. + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY +OMX_Init() +{ + DEBUG_PRINT("OMXCORE API - OMX_Init \n"); + /* Nothing to do here ; shared objects shall be loaded at the get handle method */ + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + get_cmp_index + +DESCRIPTION + Obtains the index associated with the name. + +PARAMETERS + None + +RETURN VALUE + Error None. +========================================================================== */ +static int get_cmp_index(char *cmp_name) +{ + int rc = -1,i=0; + DEBUG_PRINT("before get_cmp_index **********%d\n", rc); + + for(i=0; i< (int)SIZE_OF_CORE; i++) + { + DEBUG_PRINT("get_cmp_index: cmp_name = %s , core[i].name = %s ,count = %d \n",cmp_name,core[i].name,i); + + if(!strcmp(cmp_name, core[i].name)) + { + rc = i; + break; + } + } + DEBUG_PRINT("returning index %d\n", rc); + return rc; +} + +/* ====================================================================== +FUNCTION + clear_cmp_handle + +DESCRIPTION + Clears the component handle from the component table. + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +static void clear_cmp_handle(OMX_HANDLETYPE inst) +{ + unsigned i = 0,j=0; + + if(NULL == inst) + return; + + for(i=0; i< SIZE_OF_CORE; i++) + { + for(j=0; j< OMX_COMP_MAX_INST; j++) + { + if(inst == core[i].inst[j]) + { + core[i].inst[j] = NULL; + return; + } + } + } + return; +} +/* ====================================================================== +FUNCTION + is_cmp_handle_exists + +DESCRIPTION + Check if the component handle already exists or not. + +PARAMETERS + None + +RETURN VALUE + index pointer if the handle exists + negative value otherwise +========================================================================== */ +static int is_cmp_handle_exists(OMX_HANDLETYPE inst) +{ + unsigned i=0,j=0; + int rc = -1; + + if(NULL == inst) + return rc; + + pthread_mutex_lock(&lock_core); + for(i=0; i< SIZE_OF_CORE; i++) + { + for(j=0; j< OMX_COMP_MAX_INST; j++) + { + if(inst == core[i].inst[j]) + { + rc = i; + goto finish; + } + } + } +finish: + pthread_mutex_unlock(&lock_core); + return rc; +} + +/* ====================================================================== +FUNCTION + get_comp_handle_index + +DESCRIPTION + Gets the index to store the next handle for specified component name. + +PARAMETERS + cmp_name : Component Name + +RETURN VALUE + Index of next handle to be stored +========================================================================== */ +static int get_comp_handle_index(char *cmp_name) +{ + unsigned i=0,j=0; + int rc = -1; + for(i=0; i< SIZE_OF_CORE; i++) + { + if(!strcmp(cmp_name, core[i].name)) + { + for(j=0; j< OMX_COMP_MAX_INST; j++) + { + if(NULL == core[i].inst[j]) + { + rc = j; + DEBUG_PRINT("free handle slot exists %d\n", rc); + return rc; + } + } + break; + } + } + return rc; +} + +/* ====================================================================== +FUNCTION + check_lib_unload + +DESCRIPTION + Check if any component instance is using the library + +PARAMETERS + index: Component Index in core array. + +RETURN VALUE + 1: Library Unused and can be unloaded. + 0: Library used and shouldnt be unloaded. +========================================================================== */ +static int check_lib_unload(int index) +{ + unsigned i=0; + int rc = 1; + + for(i=0; i< OMX_COMP_MAX_INST; i++) + { + if(core[index].inst[i]) + { + rc = 0; + DEBUG_PRINT("Library Used \n"); + break; + } + } + return rc; +} +/* ====================================================================== +FUNCTION + is_cmp_already_exists + +DESCRIPTION + Check if the component already exists or not. Used in the + management of component handles. + +PARAMETERS + None + +RETURN VALUE + Error None. +========================================================================== */ +static int is_cmp_already_exists(char *cmp_name) +{ + unsigned i =0,j=0; + int rc = -1; + for(i=0; i< SIZE_OF_CORE; i++) + { + if(!strcmp(cmp_name, core[i].name)) + { + for(j=0; j< OMX_COMP_MAX_INST; j++) + { + if(core[i].inst[j]) + { + rc = i; + DEBUG_PRINT("Component exists %d\n", rc); + return rc; + } + } + break; + } + } + return rc; +} + +/* ====================================================================== +FUNCTION + get_cmp_handle + +DESCRIPTION + Get component handle. + +PARAMETERS + None + +RETURN VALUE + Error None. +========================================================================== */ +void* get_cmp_handle(char *cmp_name) +{ + unsigned i =0,j=0; + + DEBUG_PRINT("get_cmp_handle \n"); + for(i=0; i< SIZE_OF_CORE; i++) + { + if(!strcmp(cmp_name, core[i].name)) + { + for(j=0; j< OMX_COMP_MAX_INST; j++) + { + if(core[i].inst[j]) + { + DEBUG_PRINT("get_cmp_handle match\n"); + return core[i].inst[j]; + } + } + } + } + DEBUG_PRINT("get_cmp_handle returning NULL \n"); + return NULL; +} + +/* ====================================================================== +FUNCTION + OMX_DeInit + +DESCRIPTION + DeInitialize all the the relevant OMX components. + +PARAMETERS + None + +RETURN VALUE + Error None. +========================================================================== */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY +OMX_Deinit() +{ + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + OMX_GetHandle + +DESCRIPTION + Constructs requested component. Relevant library is loaded if needed. + +PARAMETERS + None + +RETURN VALUE + Error None if everything goes fine. +========================================================================== */ + + OMX_API OMX_ERRORTYPE OMX_APIENTRY +OMX_GetHandle(OMX_OUT OMX_HANDLETYPE* handle, + OMX_IN OMX_STRING componentName, + OMX_IN OMX_PTR appData, + OMX_IN OMX_CALLBACKTYPE* callBacks) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + int cmp_index = -1; + int hnd_index = -1; + + DEBUG_PRINT("OMXCORE API : Get Handle %x %s %x\n",(unsigned) handle, + componentName, + (unsigned) appData); + pthread_mutex_lock(&lock_core); + if(handle) + { + struct stat sd; + + *handle = NULL; + + cmp_index = get_cmp_index(componentName); + + if(cmp_index >= 0) + { + DEBUG_PRINT("getting fn pointer\n"); + + // dynamically load the so + core[cmp_index].fn_ptr = + omx_core_load_cmp_library(core[cmp_index].so_lib_name, + &core[cmp_index].so_lib_handle); + + if(core[cmp_index].fn_ptr) + { + // Construct the component requested + // Function returns the opaque handle + void* pThis = (*(core[cmp_index].fn_ptr))(); + if(pThis) + { + void *hComp = NULL; + hComp = qc_omx_create_component_wrapper((OMX_PTR)pThis); + if((eRet = qc_omx_component_init(hComp, core[cmp_index].name)) != + OMX_ErrorNone) + { + DEBUG_PRINT("Component not created succesfully\n"); + pthread_mutex_unlock(&lock_core); + return eRet; + + } + qc_omx_component_set_callbacks(hComp,callBacks,appData); + hnd_index = get_comp_handle_index(componentName); + if(hnd_index >= 0) + { + core[cmp_index].inst[hnd_index]= *handle = (OMX_HANDLETYPE) hComp; + } + else + { + DEBUG_PRINT("OMX_GetHandle:NO free slot available to store Component Handle\n"); + pthread_mutex_unlock(&lock_core); + return OMX_ErrorInsufficientResources; + } + DEBUG_PRINT("Component %x Successfully created\n",(unsigned)*handle); + } + else + { + eRet = OMX_ErrorInsufficientResources; + DEBUG_PRINT("Component Creation failed\n"); + } + } + else + { + eRet = OMX_ErrorNotImplemented; + DEBUG_PRINT("library couldnt return create instance fn\n"); + } + + } + else + { + eRet = OMX_ErrorNotImplemented; + DEBUG_PRINT("ERROR: Already another instance active ;rejecting \n"); + } + } + else + { + eRet = OMX_ErrorBadParameter; + DEBUG_PRINT("\n OMX_GetHandle: NULL handle \n"); + } + pthread_mutex_unlock(&lock_core); + return eRet; +} +/* ====================================================================== +FUNCTION + OMX_FreeHandle + +DESCRIPTION + Destructs the component handles. + +PARAMETERS + None + +RETURN VALUE + Error None. +========================================================================== */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY +OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComp) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + int err = 0, i = 0; + DEBUG_PRINT("OMXCORE API : Free Handle %x\n",(unsigned) hComp); + + // 0. Check that we have an active instance + if((i=is_cmp_handle_exists(hComp)) >=0) + { + // 1. Delete the component + if ((eRet = qc_omx_component_deinit(hComp)) == OMX_ErrorNone) + { + pthread_mutex_lock(&lock_core); + /* Unload component library */ + if( (i < SIZE_OF_CORE) && core[i].so_lib_handle) + { + if(check_lib_unload(i)) + { + DEBUG_PRINT_ERROR(" Unloading the dynamic library for %s\n", + core[i].name); + err = dlclose(core[i].so_lib_handle); + if(err) + { + DEBUG_PRINT_ERROR("Error %d in dlclose of lib %s\n", + err,core[i].name); + } + core[i].so_lib_handle = NULL; + } + } + clear_cmp_handle(hComp); + pthread_mutex_unlock(&lock_core); + } + else + { + DEBUG_PRINT(" OMX_FreeHandle failed on %x\n",(unsigned) hComp); + return eRet; + } + } + else + { + DEBUG_PRINT_ERROR("OMXCORE Warning: Free Handle called with no active instances\n"); + } + return OMX_ErrorNone; +} +/* ====================================================================== +FUNCTION + OMX_SetupTunnel + +DESCRIPTION + Not Implemented. + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY +OMX_SetupTunnel(OMX_IN OMX_HANDLETYPE outputComponent, + OMX_IN OMX_U32 outputPort, + OMX_IN OMX_HANDLETYPE inputComponent, + OMX_IN OMX_U32 inputPort) +{ + /* Not supported right now */ + DEBUG_PRINT("OMXCORE API: OMX_SetupTunnel Not implemented \n"); + return OMX_ErrorNotImplemented; +} +/* ====================================================================== +FUNCTION + OMX_GetContentPipe + +DESCRIPTION + Not Implemented. + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +OMX_API OMX_ERRORTYPE +OMX_GetContentPipe(OMX_OUT OMX_HANDLETYPE* pipe, + OMX_IN OMX_STRING uri) +{ + /* Not supported right now */ + DEBUG_PRINT("OMXCORE API: OMX_GetContentPipe Not implemented \n"); + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + OMX_GetComponentNameEnum + +DESCRIPTION + Returns the component name associated with the index. + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY +OMX_ComponentNameEnum(OMX_OUT OMX_STRING componentName, + OMX_IN OMX_U32 nameLen, + OMX_IN OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + DEBUG_PRINT("OMXCORE API - OMX_ComponentNameEnum %x %d %d\n",(unsigned) componentName + ,(unsigned)nameLen + ,(unsigned)index); + if(index < SIZE_OF_CORE) + { + #ifdef _ANDROID_ + strlcpy(componentName, core[index].name,nameLen); + #else + strncpy(componentName, core[index].name,nameLen); + #endif + } + else + { + eRet = OMX_ErrorNoMore; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + OMX_GetComponentsOfRole + +DESCRIPTION + Returns the component name which can fulfill the roles passed in the + argument. + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +OMX_API OMX_ERRORTYPE +OMX_GetComponentsOfRole(OMX_IN OMX_STRING role, + OMX_INOUT OMX_U32* numComps, + OMX_INOUT OMX_U8** compNames) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned i,j,namecount=0; + + printf(" Inside OMX_GetComponentsOfRole \n"); + + /*If CompNames is NULL then return*/ + if (compNames == NULL) + { + if (numComps == NULL) + { + eRet = OMX_ErrorBadParameter; + } + else + { + *numComps = 0; + for (i=0; iwidth = 176; //setting width to QCIF + aOmxOutputParameters->height = 144; //setting height to QCIF + + //TODO + //Qcom component do not use the level/profile from IL client .They are parsing the first buffer + //sent in ETB so for now setting the defalut values . Going farward we can call + //QC parser here. + if (0 == strcmp(aOmxInputParameters->cComponentRole, (OMX_STRING)"video_decoder.avc")) + { + aOmxOutputParameters->profile = 66; //minimum supported h264 profile - setting to baseline profile + aOmxOutputParameters->level = 0; // minimum supported h264 level + } + else if ((0 == strcmp(aOmxInputParameters->cComponentRole, (OMX_STRING)"video_decoder.mpeg4")) || (0 == strcmp(aOmxInputParameters ->cComponentRole, (OMX_STRING)"video_decoder.h263"))) + { + aOmxOutputParameters->profile = 8; //minimum supported h263/mpeg4 profile + aOmxOutputParameters->level = 0; // minimum supported h263/mpeg4 level + } + + return Status; +} diff --git a/mm-core/src/common/qc_omx_core.h b/mm-core/src/common/qc_omx_core.h new file mode 100755 index 0000000..c3ae26a --- /dev/null +++ b/mm-core/src/common/qc_omx_core.h @@ -0,0 +1,72 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains the definitions of the OpenMAX core. + +*//*========================================================================*/ + +#ifndef QC_OMX_CORE_H +#define QC_OMX_CORE_H + +#include "qc_omx_common.h" // OMX API +#include + +#define OMX_COMP_MAX_INST 4 + +typedef struct _omx_core_cb_type +{ + char* name;// Component name + create_qc_omx_component fn_ptr;// create instance fn ptr + void* inst[OMX_COMP_MAX_INST];// Instance handle + void* so_lib_handle;// So Library handle + char* so_lib_name;// so directory + char* roles[OMX_CORE_MAX_CMP_ROLES];// roles played +}omx_core_cb_type; + +typedef struct +{ + OMX_U32 width; + OMX_U32 height; + OMX_U32 profile; + OMX_U32 level; +} VideoOMXConfigParserOutputs; + + +typedef struct +{ + OMX_U8* inPtr; //pointer to codec configuration header + OMX_U32 inBytes; //length of codec configuration header + OMX_STRING cComponentRole; //OMX component codec type + OMX_STRING cComponentName; //OMX component name +} OMXConfigParserInputs; + +#endif + diff --git a/mm-core/src/default/qc_registry_table.c b/mm-core/src/default/qc_registry_table.c new file mode 100755 index 0000000..5cf6dd9 --- /dev/null +++ b/mm-core/src/default/qc_registry_table.c @@ -0,0 +1,65 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains a dummy registry table for the QCOM's OpenMAX core + with placeholders for actual values + +*//*========================================================================*/ + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.xxx.yyy.zzz", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + #ifdef _ANDROID_ + "abc.so", + #else + "efg.so.1", + #endif + { + "ijk.lmn" + } + } +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-core/src/default/qc_registry_table_android.c b/mm-core/src/default/qc_registry_table_android.c new file mode 100755 index 0000000..118a111 --- /dev/null +++ b/mm-core/src/default/qc_registry_table_android.c @@ -0,0 +1,62 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2009, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + + This module contains a dummy registry table for the QCOM's OpenMAX core + with placeholders for actual values + +*//*========================================================================*/ + + +#include "qc_omx_core.h" + +omx_core_cb_type core[] = +{ + { + "OMX.qcom.xxx.yyy.zzz", + NULL, // Create instance function + // Unique instance handle + { + NULL, + NULL, + NULL, + NULL + }, + NULL, // Shared object library handle + "abc.so", + { + "efg.ijk" + } + } +}; + +const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type); + + diff --git a/mm-video/Android.mk b/mm-video/Android.mk new file mode 100755 index 0000000..2d0a533 --- /dev/null +++ b/mm-video/Android.mk @@ -0,0 +1,6 @@ +OMX_VIDEO_PATH := $(call my-dir) +include $(CLEAR_VARS) + +include $(OMX_VIDEO_PATH)/vidc/vdec/Android.mk +include $(OMX_VIDEO_PATH)/vidc/venc/Android.mk +include $(OMX_VIDEO_PATH)/DivxDrmDecrypt/Android.mk diff --git a/mm-video/DivxDrmDecrypt/Android.mk b/mm-video/DivxDrmDecrypt/Android.mk new file mode 100755 index 0000000..0af340a --- /dev/null +++ b/mm-video/DivxDrmDecrypt/Android.mk @@ -0,0 +1,29 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +#=============================================================================== +# Deploy the headers that can be exposed +#=============================================================================== + +LOCAL_COPY_HEADERS_TO := mm-video/DivxDrmDecrypt +LOCAL_COPY_HEADERS := inc/DivXDrmDecrypt.h + +LOCAL_CFLAGS := \ + -D_ANDROID_ + +LOCAL_SRC_FILES:= \ + src/DivXDrmDecrypt.cpp + +LOCAL_C_INCLUDES:= \ + $(LOCAL_PATH)/inc \ + $(TARGET_OUT_HEADERS)/mm-core/omxcore + +LOCAL_PRELINK_MODULE:= false + +LOCAL_MODULE:= libdivxdrmdecrypt +LOCAL_MODULE_TAGS := optional + +LOCAL_SHARED_LIBRARIES := liblog libdl + +LOCAL_LDLIBS += +include $(BUILD_SHARED_LIBRARY) diff --git a/mm-video/DivxDrmDecrypt/inc/DivXDrmDecrypt.h b/mm-video/DivxDrmDecrypt/inc/DivXDrmDecrypt.h new file mode 100755 index 0000000..6c595b7 --- /dev/null +++ b/mm-video/DivxDrmDecrypt/inc/DivXDrmDecrypt.h @@ -0,0 +1,49 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#ifndef __DIVXDRMDECRYPT_H__ +#define __DIVXDRMDECRYPT_H__ + +#include + +//Abstract base class of API to decrypt DRM content. +class DivXDrmDecrypt +{ +public: + static DivXDrmDecrypt* Create(); + virtual OMX_ERRORTYPE Init() = 0; + virtual OMX_ERRORTYPE Decrypt(OMX_BUFFERHEADERTYPE* buffer) = 0; + inline virtual ~DivXDrmDecrypt() {} +}; + +//.so file should provide a function with the name createDivXDrmDecrypt with +//prototype of DivXDrmDecryptFactory. +static const char* MEDIA_CREATE_DIVX_DRM_DECRYPT = "createDivXDrmDecrypt"; +typedef DivXDrmDecrypt* (*DivXDrmDecryptFactory)(); + +#endif //__DIVXDRMDECRYPT_H__ diff --git a/mm-video/DivxDrmDecrypt/src/DivXDrmDecrypt.cpp b/mm-video/DivxDrmDecrypt/src/DivXDrmDecrypt.cpp new file mode 100755 index 0000000..f723427 --- /dev/null +++ b/mm-video/DivxDrmDecrypt/src/DivXDrmDecrypt.cpp @@ -0,0 +1,98 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#include "DivXDrmDecrypt.h" +#include // for dlopen/dlclose + +//#define LOG_NDEBUG 0 +#define LOG_TAG "DivXDrmDecrypt" +#ifdef _ANDROID_ +#include +#else +#include +#define ALOGE(fmt, args...) fprintf(stderr, fmt, ##args) +#endif /* _ANDROID_ */ + +static const char* DIVX_DRM_SHIM_LIB = "libSHIMDivxDrm.so"; + +void* getDecryptHandle() { + static void* decryptLib = NULL; + static bool decryptLibOpened = false; + + if(decryptLibOpened) { + return decryptLib; + } + + decryptLib = ::dlopen(DIVX_DRM_SHIM_LIB, RTLD_NOW); + decryptLibOpened = true; + + if (decryptLib == NULL) { + ALOGE("Failed to open DIVX_DRM_SHIM_LIB \n"); + } + + return decryptLib; +} + +DivXDrmDecryptFactory DrmDecryptFactoryFunction() { + static DivXDrmDecryptFactory drmDecryptFactoryFunction = NULL; + static bool alreadyTriedToFindFactoryFunction = false; + + if(alreadyTriedToFindFactoryFunction) { + return drmDecryptFactoryFunction; + } + + void *pDecryptLib = getDecryptHandle(); + if (pDecryptLib == NULL) { + return NULL; + } + + drmDecryptFactoryFunction = (DivXDrmDecryptFactory) dlsym(pDecryptLib, MEDIA_CREATE_DIVX_DRM_DECRYPT); + alreadyTriedToFindFactoryFunction = true; + + if(!drmDecryptFactoryFunction) { + ALOGE(" dlsym for DrmDecrypt factory function failed \n"); + } + + return drmDecryptFactoryFunction; +} + + + +DivXDrmDecrypt* DivXDrmDecrypt::Create() { + DivXDrmDecryptFactory drmCreateFunc = DrmDecryptFactoryFunction(); + if( drmCreateFunc == NULL ) { + return NULL; + } + + DivXDrmDecrypt* decrypt = drmCreateFunc(); + if( decrypt == NULL ) { + ALOGE(" failed to instantiate DrmDecoder \n"); + } + return decrypt; +} + diff --git a/mm-video/vidc/common/inc/extra_data_handler.h b/mm-video/vidc/common/inc/extra_data_handler.h new file mode 100755 index 0000000..19e3ca7 --- /dev/null +++ b/mm-video/vidc/common/inc/extra_data_handler.h @@ -0,0 +1,103 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#ifndef __EXTRA_DATA_HANDLER_H__ +#define __EXTRA_DATA_HANDLER_H__ + +#include +#include +#include +#include +#include "OMX_QCOMExtns.h" +#include +#include + + +#ifdef _ANDROID_ +extern "C"{ +#include +} +#ifdef ENABLE_DEBUG_LOW +#define DEBUG_PRINT_LOW ALOGV +#else +#define DEBUG_PRINT_LOW +#endif +#ifdef ENABLE_DEBUG_HIGH +#define DEBUG_PRINT_HIGH ALOGV +#else +#define DEBUG_PRINT_HIGH +#endif +#ifdef ENABLE_DEBUG_ERROR +#define DEBUG_PRINT_ERROR ALOGE +#else +#define DEBUG_PRINT_ERROR +#endif + +#else //_ANDROID_ +#define DEBUG_PRINT_LOW printf +#define DEBUG_PRINT_HIGH printf +#define DEBUG_PRINT_ERROR printf +#endif // _ANDROID_ + +#define SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT 0x2D +#define H264_START_CODE 0x01 +#define NAL_TYPE_SEI 0x06 +#define VDEC_OMX_SEI 0x7F000007 +#define FRAME_PACK_SIZE 18 +#define H264_EMULATION_BYTE 0x03 +class extra_data_handler +{ +public: + extra_data_handler(); + ~extra_data_handler(); + OMX_U32 parse_extra_data(OMX_BUFFERHEADERTYPE *buf_hdr); + OMX_U32 create_extra_data(OMX_BUFFERHEADERTYPE *buf_hdr); + OMX_U32 get_frame_pack_data(OMX_QCOM_FRAME_PACK_ARRANGEMENT *frame_pack); + OMX_U32 set_frame_pack_data(OMX_QCOM_FRAME_PACK_ARRANGEMENT *frame_pack); +private: + OMX_QCOM_FRAME_PACK_ARRANGEMENT frame_packing_arrangement; + OMX_U8 *rbsp_buf; + OMX_U32 bit_ptr; + OMX_U32 byte_ptr; + OMX_U32 pack_sei; + OMX_U32 sei_payload_type; + OMX_U32 d_u(OMX_U32 num_bits); + OMX_U32 d_ue(); + OMX_U32 parse_frame_pack(OMX_U32 payload_size); + OMX_S32 parse_rbsp(OMX_U8 *buf, OMX_U32 len); + OMX_S32 parse_sei(OMX_U8 *buffer, OMX_U32 buffer_length); + OMX_U32 e_u(OMX_U32 symbol, OMX_U32 num_bits); + OMX_U32 e_ue(OMX_U32 symbol); + OMX_U32 create_frame_pack(); + OMX_S32 create_rbsp(OMX_U8 *buf, OMX_U32 nalu_type); + OMX_U32 create_sei(OMX_U8 *buffer); + OMX_S32 parse_sliceinfo(OMX_BUFFERHEADERTYPE *pBufHdr, + OMX_OTHER_EXTRADATATYPE *pExtra); +}; + +#endif diff --git a/mm-video/vidc/common/src/extra_data_handler.cpp b/mm-video/vidc/common/src/extra_data_handler.cpp new file mode 100755 index 0000000..28f2d95 --- /dev/null +++ b/mm-video/vidc/common/src/extra_data_handler.cpp @@ -0,0 +1,478 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#include "extra_data_handler.h" + +extra_data_handler::extra_data_handler() +{ + rbsp_buf = (OMX_U8 *) calloc(1,100); + memset(&frame_packing_arrangement,0,sizeof(frame_packing_arrangement)); + frame_packing_arrangement.cancel_flag = 1; + pack_sei = false; + sei_payload_type = -1; +} + +extra_data_handler::~extra_data_handler() +{ + if(rbsp_buf) { + free(rbsp_buf); + rbsp_buf = NULL; + } +} + +OMX_U32 extra_data_handler::d_u(OMX_U32 num_bits) +{ + OMX_U32 rem_bits = num_bits, bins = 0, shift = 0; + + while(rem_bits >= bit_ptr) { + DEBUG_PRINT_LOW("\nIn %s() bit_ptr/byte_ptr :%d/%d/%x", __func__, bit_ptr, + byte_ptr, rbsp_buf[byte_ptr]); + bins <<= shift; + shift = (8-bit_ptr); + bins |= ((rbsp_buf[byte_ptr] << shift) & 0xFF) >> shift; + rem_bits -= bit_ptr; + bit_ptr = 8; + byte_ptr ++; + } + DEBUG_PRINT_LOW("\nIn %s() bit_ptr/byte_ptr :%d/%d/%x", __func__, bit_ptr, + byte_ptr, rbsp_buf[byte_ptr]); + + if (rem_bits) { + bins <<= rem_bits; + bins |= ((rbsp_buf[byte_ptr] << (8-bit_ptr)) & 0xFF) >> (8-rem_bits); + bit_ptr -= rem_bits; + if (bit_ptr == 0) { + bit_ptr = 8; + byte_ptr++; + } + } + DEBUG_PRINT_LOW("\nIn %s() bit_ptr/byte_ptr :%d/%d/%x", __func__, bit_ptr, + byte_ptr, rbsp_buf[byte_ptr]); + + DEBUG_PRINT_LOW("\nIn %s() bin/num_bits : %x/%d", __func__, bins, num_bits); + return bins; +} + +OMX_U32 extra_data_handler::d_ue() +{ + OMX_S32 lead_zeros = -1; + OMX_U32 symbol, bit; + do{ + bit = d_u(1); + lead_zeros++; + }while (!bit); + + symbol = ((1 << lead_zeros) - 1) + d_u(lead_zeros); + + DEBUG_PRINT_LOW("\nIn %s() symbol : %d", __func__,symbol); + return symbol; +} + +OMX_U32 extra_data_handler::parse_frame_pack(OMX_U32 payload_size) +{ + frame_packing_arrangement.id = d_ue(); + frame_packing_arrangement.cancel_flag = d_u(1); + if(!frame_packing_arrangement.cancel_flag) { + frame_packing_arrangement.type = d_u(7); + frame_packing_arrangement.quincunx_sampling_flag = d_u(1); + frame_packing_arrangement.content_interpretation_type = d_u(6); + frame_packing_arrangement.spatial_flipping_flag = d_u(1); + frame_packing_arrangement.frame0_flipped_flag = d_u(1); + frame_packing_arrangement.field_views_flag = d_u(1); + frame_packing_arrangement.current_frame_is_frame0_flag = d_u(1); + frame_packing_arrangement.frame0_self_contained_flag = d_u(1); + frame_packing_arrangement.frame1_self_contained_flag = d_u(1); + + if(!frame_packing_arrangement.quincunx_sampling_flag && + frame_packing_arrangement.type != 5) { + frame_packing_arrangement.frame0_grid_position_x = d_u(4); + frame_packing_arrangement.frame0_grid_position_y = d_u(4); + frame_packing_arrangement.frame1_grid_position_x = d_u(4); + frame_packing_arrangement.frame1_grid_position_y = d_u(4); + } + frame_packing_arrangement.reserved_byte = d_u(8); + frame_packing_arrangement.repetition_period = d_ue(); + } + frame_packing_arrangement.extension_flag = d_u(1); + + return 1; +} + +OMX_S32 extra_data_handler::parse_rbsp(OMX_U8 *buf, OMX_U32 len) +{ + OMX_U32 i = 3, j=0, startcode; + OMX_U32 nal_unit_type, nal_ref_idc, forbidden_zero_bit; + + bit_ptr = 8; + byte_ptr = 0; + + startcode = buf[0] << 16 | buf[1] <<8 | buf[2]; + + if (!startcode) { + startcode |= buf[i++]; + } + if(startcode != H264_START_CODE) { + DEBUG_PRINT_ERROR("\nERROR: In %s() Start code not found", __func__); + return -1; + } + forbidden_zero_bit = (buf[i] & 0x80) >>7; + if(forbidden_zero_bit) { + DEBUG_PRINT_ERROR("\nERROR: In %s() Non-zero forbidden bit", __func__); + return -1; + } + nal_ref_idc = (buf[i] & 0x60) >>5; + DEBUG_PRINT_LOW("\nIn %s() nal_ref_idc ; %d", __func__, nal_ref_idc); + + nal_unit_type = (buf[i++] & 0x1F); + + while(ipBuffer; + OMX_U32 *data = (OMX_U32 *)pExtra->data; + OMX_U32 num_slices = *data; + DEBUG_PRINT_HIGH("number of slices = %d", num_slices); + if ((4 + num_slices * 8) != (OMX_U32)pExtra->nDataSize) { + DEBUG_PRINT_ERROR("unknown error in slice info extradata"); + return -1; + } + for (int i = 0; i < num_slices; i++) { + slice_offset = (OMX_U32)(*(data + (i*2 + 1))); + if ((*(pBuffer + slice_offset + 0) != 0x00) || + (*(pBuffer + slice_offset + 1) != 0x00) || + (*(pBuffer + slice_offset + 2) != 0x00) || + (*(pBuffer + slice_offset + 3) != H264_START_CODE)) { + DEBUG_PRINT_ERROR("found 0x%x instead of start code at offset[%d] " + "for slice[%d]", (OMX_U32)(*(OMX_U32 *)(pBuffer + slice_offset)), + slice_offset, i); + return -1; + } + if (slice_offset != total_size) { + DEBUG_PRINT_ERROR("offset of slice number %d is not correct " + "or previous slice size is not correct", i); + return -1; + } + slice_size = (OMX_U32)(*(data + (i*2 + 2))); + total_size += slice_size; + DEBUG_PRINT_HIGH("slice number %d offset/size = %d/%d", + i, slice_offset, slice_size); + } + if (pBufHdr->nFilledLen != total_size) { + DEBUG_PRINT_ERROR("frame_size[%d] is not equal to " + "total slices size[%d]", pBufHdr->nFilledLen, total_size); + return -1; + } + return 0; +} + +OMX_U32 extra_data_handler::parse_extra_data(OMX_BUFFERHEADERTYPE *buf_hdr) +{ + OMX_OTHER_EXTRADATATYPE *extra_data = (OMX_OTHER_EXTRADATATYPE *) + ((unsigned)(buf_hdr->pBuffer + buf_hdr->nOffset + + buf_hdr->nFilledLen + 3)&(~3)); + + DEBUG_PRINT_LOW("\nIn %s() symbol : %u", __func__,buf_hdr->nFlags); + + if (buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA) { + while(extra_data && (OMX_U8*)extra_data < (buf_hdr->pBuffer + + buf_hdr->nAllocLen) && extra_data->eType != VDEC_EXTRADATA_NONE) { + DEBUG_PRINT_LOW("\nExtra data type(%x) Extra data size(%u)", + extra_data->eType, extra_data->nDataSize); + if (extra_data->eType == VDEC_EXTRADATA_SEI) { + parse_sei(extra_data->data, extra_data->nDataSize); + } + else if (extra_data->eType == VEN_EXTRADATA_QCOMFILLER) { + DEBUG_PRINT_HIGH("Extradata Qcom Filler found, skip %d bytes", + extra_data->nSize); + } + else if (extra_data->eType == VEN_EXTRADATA_SLICEINFO) { + DEBUG_PRINT_HIGH("Extradata SliceInfo of size %d found, " + "parsing it", extra_data->nDataSize); + parse_sliceinfo(buf_hdr, extra_data); + } + extra_data = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) extra_data) + + extra_data->nSize); + } + } + return 1; +} + +OMX_U32 extra_data_handler::get_frame_pack_data( + OMX_QCOM_FRAME_PACK_ARRANGEMENT *frame_pack) +{ + DEBUG_PRINT_LOW("\n%s:%d get frame data", __func__, __LINE__); + memcpy(&frame_pack->id,&frame_packing_arrangement.id, + FRAME_PACK_SIZE*sizeof(OMX_U32)); + return 1; +} + +OMX_U32 extra_data_handler::set_frame_pack_data(OMX_QCOM_FRAME_PACK_ARRANGEMENT + *frame_pack) +{ + DEBUG_PRINT_LOW("\n%s:%d set frame data", __func__, __LINE__); + memcpy(&frame_packing_arrangement.id, &frame_pack->id, + FRAME_PACK_SIZE*sizeof(OMX_U32)); + pack_sei = true; + sei_payload_type = SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT; + return 1; +} + +OMX_U32 extra_data_handler::e_u(OMX_U32 symbol, OMX_U32 num_bits) +{ + OMX_U32 rem_bits = num_bits, shift; + + DEBUG_PRINT_LOW("\n%s bin : %x/%d", __func__, symbol, num_bits); + + while(rem_bits >= bit_ptr) { + shift = rem_bits - bit_ptr; + rbsp_buf[byte_ptr] |= (symbol >> shift); + symbol = (symbol << (32 - shift)) >> (32 - shift); + rem_bits -= bit_ptr; + DEBUG_PRINT_LOW("\n%sstream byte/rem_bits %x/%d", __func__, + rbsp_buf[byte_ptr], rem_bits); + byte_ptr ++; + bit_ptr = 8; + } + + if(rem_bits) { + shift = bit_ptr - rem_bits; + rbsp_buf[byte_ptr] |= (symbol << shift); + bit_ptr -= rem_bits; + DEBUG_PRINT_LOW("\n%s 2 stream byte/rem_bits %x", __func__, + rbsp_buf[byte_ptr], rem_bits); + if(bit_ptr == 0) { + bit_ptr = 8; + byte_ptr++; + } + } + return 1; +} + +OMX_U32 extra_data_handler::e_ue(OMX_U32 symbol) +{ + OMX_U32 i, sym_len, sufix_len, info; + OMX_U32 nn =(symbol + 1) >> 1; + + DEBUG_PRINT_LOW("\n%s bin : %x", __func__, symbol); + + for(i=0; i < 33 && nn != 0; i++) + nn >>= 1; + + sym_len = ((i << 1) + 1); + info = symbol + 1 - (1 << i); + sufix_len = (1 << (sym_len >>1)); + info = sufix_len | (info & (sufix_len - 1)); + e_u(info, sym_len); + return 1; +} + +OMX_U32 extra_data_handler::create_frame_pack() +{ + e_ue(frame_packing_arrangement.id); + e_u(frame_packing_arrangement.cancel_flag, 1); + if(!frame_packing_arrangement.cancel_flag) { + e_u(frame_packing_arrangement.type, 7); + e_u(frame_packing_arrangement.quincunx_sampling_flag, 1); + e_u(frame_packing_arrangement.content_interpretation_type, 6); + e_u(frame_packing_arrangement.spatial_flipping_flag, 1); + e_u(frame_packing_arrangement.frame0_flipped_flag, 1); + e_u(frame_packing_arrangement.field_views_flag, 1); + e_u(frame_packing_arrangement.current_frame_is_frame0_flag, 1); + e_u(frame_packing_arrangement.frame0_self_contained_flag, 1); + e_u(frame_packing_arrangement.frame1_self_contained_flag, 1); + if(!frame_packing_arrangement.quincunx_sampling_flag && + frame_packing_arrangement.type != 5) { + e_u(frame_packing_arrangement.frame0_grid_position_x, 4); + e_u(frame_packing_arrangement.frame0_grid_position_y, 4); + e_u(frame_packing_arrangement.frame1_grid_position_x, 4); + e_u(frame_packing_arrangement.frame1_grid_position_y, 4); + } + e_u(frame_packing_arrangement.reserved_byte, 8); + e_ue(frame_packing_arrangement.repetition_period); + } + e_u(frame_packing_arrangement.extension_flag, 1); + return 1; +} + +OMX_S32 extra_data_handler::create_rbsp(OMX_U8 *buf, OMX_U32 nalu_type) +{ + OMX_U32 i, j = 7; + for(i = 0;i < 3;i++) + *buf++ = 0x00; + *buf++ = H264_START_CODE; + *buf++ = nalu_type; + *buf++ = (sei_payload_type & 0x000000FF); + *buf++ = byte_ptr - 1; //payload will contain 1 byte of rbsp_trailing_bits + //that shouldn't be taken into account + + for(i = 0;i < byte_ptr ;i += 2) { + *buf++ = rbsp_buf[i]; + j++; + if(i+1 < byte_ptr) { + *buf++ = rbsp_buf[i+1]; + j++; + if(!(rbsp_buf[i] + rbsp_buf[i+1])) { + *buf++ = H264_EMULATION_BYTE; + j++; + } + } + } + + DEBUG_PRINT_LOW("\n%s rbsp length %d", __func__, j); + return j; +} + +OMX_U32 extra_data_handler::create_sei(OMX_U8 *buffer) +{ + OMX_U32 i, ret_val = 0; + + byte_ptr = 0; + bit_ptr = 8; + + if(sei_payload_type == SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT) { + create_frame_pack(); + + if(bit_ptr != 8) { + e_u(1,1); + if(bit_ptr != 8) + e_u(0,bit_ptr); + } + + //Payload will have been byte aligned by now, + //insert the rbsp trailing bits + e_u(1, 1); + e_u(0, 7); + + ret_val = create_rbsp(buffer, NAL_TYPE_SEI); + } + + pack_sei = false; + sei_payload_type = -1; + + return ret_val; +} + +OMX_U32 extra_data_handler::create_extra_data(OMX_BUFFERHEADERTYPE *buf_hdr) +{ + OMX_U8 *buffer = (OMX_U8 *) ((unsigned)(buf_hdr->pBuffer + + buf_hdr->nOffset + buf_hdr->nFilledLen)); + OMX_U32 msg_size; + + DEBUG_PRINT_LOW("\n filled_len/orig_len %d/%d", buf_hdr->nFilledLen, + buf_hdr->nAllocLen); + + if(buf_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + DEBUG_PRINT_LOW("\n%s:%d create extra data with config", __func__, + __LINE__); + if(pack_sei) { + msg_size = create_sei(buffer); + if( msg_size > 0) + buf_hdr->nFilledLen += msg_size; + } + } + DEBUG_PRINT_LOW("\n filled_len/orig_len %d/%d", buf_hdr->nFilledLen, + buf_hdr->nAllocLen); + return 1; +} + diff --git a/mm-video/vidc/vdec/Android.mk b/mm-video/vidc/vdec/Android.mk new file mode 100755 index 0000000..9c85217 --- /dev/null +++ b/mm-video/vidc/vdec/Android.mk @@ -0,0 +1,154 @@ +ifneq ($(BUILD_TINY_ANDROID),true) + +ROOT_DIR := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_PATH:= $(ROOT_DIR) + +# --------------------------------------------------------------------------------- +# Common definitons +# --------------------------------------------------------------------------------- + +libOmxVdec-def := -D__alignx\(x\)=__attribute__\(\(__aligned__\(x\)\)\) +libOmxVdec-def += -D__align=__alignx +libOmxVdec-def += -Dinline=__inline +libOmxVdec-def += -g -O3 +libOmxVdec-def += -DIMAGE_APPS_PROC +libOmxVdec-def += -D_ANDROID_ +libOmxVdec-def += -DCDECL +libOmxVdec-def += -DT_ARM +libOmxVdec-def += -DNO_ARM_CLZ +libOmxVdec-def += -UENABLE_DEBUG_LOW +#libOmxVdec-def += -DENABLE_DEBUG_HIGH +libOmxVdec-def += -DENABLE_DEBUG_ERROR +libOmxVdec-def += -UINPUT_BUFFER_LOG +libOmxVdec-def += -UOUTPUT_BUFFER_LOG +ifeq ($(TARGET_BOARD_PLATFORM),msm8660) +libOmxVdec-def += -DMAX_RES_1080P +libOmxVdec-def += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT +libOmxVdec-def += -DTEST_TS_FROM_SEI +endif +ifeq ($(TARGET_BOARD_PLATFORM),msm8960) +libOmxVdec-def += -DMAX_RES_1080P +libOmxVdec-def += -DMAX_RES_1080P_EBI +libOmxVdec-def += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT +endif +ifeq ($(TARGET_BOARD_PLATFORM),msm8974) +libOmxVdec-def += -DMAX_RES_1080P +libOmxVdec-def += -DMAX_RES_1080P_EBI +libOmxVdec-def += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT +libOmxVdec-def += -D_MSM8974_ +endif +ifeq ($(TARGET_BOARD_PLATFORM),msm7627a) +libOmxVdec-def += -DMAX_RES_720P +endif +ifeq ($(TARGET_BOARD_PLATFORM),msm7x30) +libOmxVdec-def += -DMAX_RES_720P +endif + +libOmxVdec-def += -D_ANDROID_ICS_ + +ifeq ($(TARGET_USES_ION),true) +libOmxVdec-def += -DUSE_ION +endif + +# --------------------------------------------------------------------------------- +# Make the Shared library (libOmxVdec) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) +LOCAL_PATH:= $(ROOT_DIR) + +libmm-vdec-inc := bionic/libc/include +libmm-vdec-inc += bionic/libstdc++/include +libmm-vdec-inc += $(LOCAL_PATH)/inc +libmm-vdec-inc += $(OMX_VIDEO_PATH)/vidc/common/inc +libmm-vdec-inc += hardware/qcom/media-legacy/mm-core/inc +libmm-vdec-inc += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +#libmm-vdec-inc += bionic/libc/kernel/common/linux +#DRM include - Interface which loads the DRM library +libmm-vdec-inc += $(OMX_VIDEO_PATH)/DivxDrmDecrypt/inc +libmm-vdec-inc += hardware/qcom/display-legacy/libgralloc +libmm-vdec-inc += hardware/qcom/display-legacy/libgenlock +libmm-vdec-inc += frameworks/native/include/media/openmax +libmm-vdec-inc += frameworks/native/include/media/hardware + +LOCAL_MODULE := libOmxVdec +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxVdec-def) +LOCAL_C_INCLUDES += $(libmm-vdec-inc) + +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := liblog libutils libbinder libcutils + +LOCAL_SHARED_LIBRARIES += libgenlock +LOCAL_SHARED_LIBRARIES += libdivxdrmdecrypt + +LOCAL_SRC_FILES := src/frameparser.cpp +LOCAL_SRC_FILES += src/h264_utils.cpp +LOCAL_SRC_FILES += src/ts_parser.cpp +LOCAL_SRC_FILES += src/mp4_utils.cpp +ifeq ($(TARGET_BOARD_PLATFORM),msm8974) +LOCAL_SRC_FILES += src/omx_vdec_msm8974.cpp +else +LOCAL_SRC_FILES += src/omx_vdec.cpp +endif +LOCAL_SRC_FILES += ../common/src/extra_data_handler.cpp + +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + +include $(BUILD_SHARED_LIBRARY) + +# --------------------------------------------------------------------------------- +# Make the apps-test (mm-vdec-omx-test) +# --------------------------------------------------------------------------------- +include $(CLEAR_VARS) + +mm-vdec-test-inc := hardware/qcom/media-legacy/mm-core/inc +mm-vdec-test-inc += $(LOCAL_PATH)/inc +mm-vdec-test-inc += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +#mm-vdec-test-inc += bionic/libc/kernel/common/linux + +LOCAL_MODULE := mm-vdec-omx-test +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxVdec-def) +LOCAL_C_INCLUDES := $(mm-vdec-test-inc) + +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libutils libOmxCore libOmxVdec libbinder + +LOCAL_SRC_FILES := src/queue.c +LOCAL_SRC_FILES += test/omx_vdec_test.cpp + +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + +include $(BUILD_EXECUTABLE) + +# --------------------------------------------------------------------------------- +# Make the driver-test (mm-video-driver-test) +# --------------------------------------------------------------------------------- +include $(CLEAR_VARS) + +mm-vdec-drv-test-inc := hardware/qcom/media-legacy/mm-core/inc +mm-vdec-drv-test-inc += $(LOCAL_PATH)/inc +mm-vdec-drv-test-inc += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +#mm-vdec-drv-test-inc += bionic/libc/kernel/common/linux + +LOCAL_MODULE := mm-video-driver-test +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libOmxVdec-def) +LOCAL_C_INCLUDES := $(mm-vdec-drv-test-inc) +LOCAL_PRELINK_MODULE := false + +LOCAL_SRC_FILES := src/message_queue.c +LOCAL_SRC_FILES += test/decoder_driver_test.c + +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + +include $(BUILD_EXECUTABLE) + +endif #BUILD_TINY_ANDROID + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- diff --git a/mm-video/vidc/vdec/inc/Map.h b/mm-video/vidc/vdec/inc/Map.h new file mode 100755 index 0000000..a9b7981 --- /dev/null +++ b/mm-video/vidc/vdec/inc/Map.h @@ -0,0 +1,237 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef _MAP_H_ +#define _MAP_H_ + +#include +using namespace std; + +template +class Map +{ + struct node + { + T data; + T2 data2; + node* prev; + node* next; + node(T t, T2 t2,node* p, node* n) : + data(t), data2(t2), prev(p), next(n) {} + }; + node* head; + node* tail; + node* tmp; + unsigned size_of_list; + static Map *m_self; +public: + Map() : head( NULL ), tail ( NULL ),tmp(head),size_of_list(0) {} + bool empty() const { return ( !head || !tail ); } + operator bool() const { return !empty(); } + void insert(T,T2); + void show(); + int size(); + T2 find(T); // Return VALUE + T find_ele(T);// Check if the KEY is present or not + T2 begin(); //give the first ele + bool erase(T); + bool eraseall(); + bool isempty(); + ~Map() + { + while(head) + { + node* temp(head); + head=head->next; + size_of_list--; + delete temp; + } + } +}; + +template +T2 Map::find(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data2; + } + tmp = tmp->next; + } + return 0; +} + +template +T Map::find_ele(T d1) +{ + tmp = head; + while(tmp) + { + if(tmp->data == d1) + { + return tmp->data; + } + tmp = tmp->next; + } + return 0; +} + +template +T2 Map::begin() +{ + tmp = head; + if(tmp) + { + return (tmp->data2); + } + return 0; +} + +template +void Map::show() +{ + tmp = head; + while(tmp) + { + printf("%d-->%d\n",tmp->data,tmp->data2); + tmp = tmp->next; + } +} + +template +int Map::size() +{ + int count =0; + tmp = head; + while(tmp) + { + tmp = tmp->next; + count++; + } + return count; +} + +template +void Map::insert(T data, T2 data2) +{ + tail = new node(data, data2,tail, NULL); + if( tail->prev ) + tail->prev->next = tail; + + if( empty() ) + { + head = tail; + tmp=head; + } + tmp = head; + size_of_list++; +} + +template +bool Map::erase(T d) +{ + bool found = false; + tmp = head; + node* prevnode = tmp; + node *tempnode; + + while(tmp) + { + if((head == tail) && (head->data == d)) + { + found = true; + tempnode = head; + head = tail = NULL; + delete tempnode; + break; + } + if((tmp ==head) && (tmp->data ==d)) + { + found = true; + tempnode = tmp; + tmp = tmp->next; + tmp->prev = NULL; + head = tmp; + tempnode->next = NULL; + delete tempnode; + break; + } + if((tmp == tail) && (tmp->data ==d)) + { + found = true; + tempnode = tmp; + prevnode->next = NULL; + tmp->prev = NULL; + tail = prevnode; + delete tempnode; + break; + } + if(tmp->data == d) + { + found = true; + prevnode->next = tmp->next; + tmp->next->prev = prevnode->next; + tempnode = tmp; + //tmp = tmp->next; + delete tempnode; + break; + } + prevnode = tmp; + tmp = tmp->next; + } + if(found)size_of_list--; + return found; +} + +template +bool Map::eraseall() +{ + node *tempnode; + tmp = head; + while(head) + { + tempnode = head; + tempnode->next = NULL; + head = head->next; + delete tempnode; + } + tail = head = NULL; + return true; +} + + +template +bool Map::isempty() +{ + if(!size_of_list) return true; + else return false; +} + +#endif // _MAP_H_ diff --git a/mm-video/vidc/vdec/inc/decoder_driver_test.h b/mm-video/vidc/vdec/inc/decoder_driver_test.h new file mode 100755 index 0000000..cb8e035 --- /dev/null +++ b/mm-video/vidc/vdec/inc/decoder_driver_test.h @@ -0,0 +1,70 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include +#include +#include "message_queue.h" +#include +#include +#include +#include +#include +#include +#include +#include + +struct video_decoder_context +{ + enum vdec_codec decoder_format; + enum vdec_output_fromat output_format; + struct vdec_picsize video_resoultion; + struct vdec_allocatorproperty input_buffer; + struct vdec_allocatorproperty output_buffer; + struct vdec_bufferpayload **ptr_inputbuffer; + struct vdec_bufferpayload **ptr_outputbuffer; + struct vdec_output_frameinfo **ptr_respbuffer; + struct video_queue_context queue_context; + int video_driver_fd; + + FILE * inputBufferFile; + FILE * outputBufferFile; + + pthread_t videothread_id; + pthread_t asyncthread_id; + sem_t sem_synchronize; +}; + +int init_decoder ( struct video_decoder_context *init_decode ); +int allocate_buffer ( enum vdec_buffer, + struct video_decoder_context *decode_context + ); +int free_buffer ( enum vdec_buffer, + struct video_decoder_context *decode_context + ); +int start_decoding (struct video_decoder_context *decode_context); +int stop_decoding (struct video_decoder_context *decode_context); +int deinit_decoder (struct video_decoder_context *init_decode); diff --git a/mm-video/vidc/vdec/inc/frameparser.h b/mm-video/vidc/vdec/inc/frameparser.h new file mode 100755 index 0000000..015bce5 --- /dev/null +++ b/mm-video/vidc/vdec/inc/frameparser.h @@ -0,0 +1,106 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef FRAMEPARSER_H +#define FRAMEPARSER_H + +#include "OMX_Core.h" +#include "OMX_QCOMExtns.h" +#include "h264_utils.h" +//#include + +enum codec_type +{ + CODEC_TYPE_MPEG4 = 0, + CODEC_TYPE_DIVX = 0, + CODEC_TYPE_H263 = 1, + CODEC_TYPE_H264 = 2, + CODEC_TYPE_VC1 = 3, + CODEC_TYPE_MPEG2 = 4, +#ifdef _MSM8974_ + CODEC_TYPE_VP8 = 5, + CODEC_TYPE_MAX = CODEC_TYPE_VP8 +#else + CODEC_TYPE_MAX = CODEC_TYPE_MPEG2 +#endif +}; + +enum state_start_code_parse +{ + A0, + A1, + A2, + A3, + A4, + A5 +}; + +enum state_nal_parse +{ + NAL_LENGTH_ACC, + NAL_PARSING +}; + +class frame_parse +{ + +public: + H264_Utils *mutils; + int init_start_codes (codec_type codec_type_parse); + int parse_sc_frame (OMX_BUFFERHEADERTYPE *source, + OMX_BUFFERHEADERTYPE *dest , + OMX_U32 *partialframe); + int init_nal_length (unsigned int nal_length); + int parse_h264_nallength (OMX_BUFFERHEADERTYPE *source, + OMX_BUFFERHEADERTYPE *dest , + OMX_U32 *partialframe); + void flush (); + frame_parse (); + ~frame_parse (); + +private: + /*Variables for Start code based Parsing*/ + enum state_start_code_parse parse_state; + unsigned char *start_code; + unsigned char *mask_code; + unsigned char last_byte_h263; + unsigned char last_byte; + bool header_found; + bool skip_frame_boundary; + + /*Variables for NAL Length Parsing*/ + enum state_nal_parse state_nal; + unsigned int nal_length; + unsigned int accum_length; + unsigned int bytes_tobeparsed; + /*Functions to support additional start code parsing*/ + void parse_additional_start_code(OMX_U8 *psource, OMX_U32 *parsed_length); + void check_skip_frame_boundary(OMX_U32 *partial_frame); + void update_skip_frame(); +}; + +#endif /* FRAMEPARSER_H */ diff --git a/mm-video/vidc/vdec/inc/h264_utils.h b/mm-video/vidc/vdec/inc/h264_utils.h new file mode 100755 index 0000000..9a903b1 --- /dev/null +++ b/mm-video/vidc/vdec/inc/h264_utils.h @@ -0,0 +1,479 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef H264_UTILS_H +#define H264_UTILS_H + +/*======================================================================== + + O p e n M M + U t i l i t i e s a n d H e l p e r R o u t i n e s + +*//** @file H264_Utils.h +This module contains H264 video decoder utilities and helper routines. + +*//*====================================================================== */ + +/* ======================================================================= + + INCLUDE FILES FOR MODULE + +========================================================================== */ +#include +#include "Map.h" +#include "qtypes.h" +#include "OMX_Core.h" +#include "OMX_QCOMExtns.h" + +#define STD_MIN(x,y) (((x) < (y)) ? (x) : (y)) + +#define OMX_CORE_720P_HEIGHT 720 +#define OMX_CORE_720P_WIDTH 1280 + +#define PANSCAN_HDLR + +/* ======================================================================= + + DATA DECLARATIONS + +========================================================================== */ + +/* ----------------------------------------------------------------------- +** Constant / Define Declarations +** ----------------------------------------------------------------------- */ +// Common format block header definitions +#define MT_VIDEO_META_STREAM_HEADER 0x00 +#define MT_VIDEO_MEDIA_STREAM_HEADER 0x01 +#define MT_VIDEO_META_MEDIA_STREAM_HEADER 0x02 + +// H.264 format block header definitions +#define MT_VIDEO_H264_ACCESS_UNIT_FORMAT 0x00 +#define MT_VIDEO_H264_NAL_FORMT 0x01 +#define MT_VIDEO_H264_BYTE_FORMAT 0x02 +#define MT_VIDEO_H264_BYTE_STREAM_FORMAT 0x00 +#define MT_VIDEO_H264_NAL_UNIT_STREAM_FORMAT 0x01 +#define MT_VIDEO_H264_FORMAT_BLOCK_HEADER_SIZE 18 + +// MPEG-4 format block header definitions +#define MT_VIDEO_MPEG4_VOP_FORMAT 0x00 +#define MT_VIDEO_MPEG4_SLICE_FORMAT 0x01 +#define MT_VIDEO_MPEG4_BYTE_FORMAT 0x02 +#define MT_VIDEO_MPEG4_FORMAT_BLOCK_HEADER_SIZE 15 + +// H.263 format block header definitions +#define MT_VIDEO_H263_PICTURE_FORMAT 0x00 +#define MT_VIDEO_H263_GOB_FORMAT 0x01 +#define MT_VIDEO_H263_SLICE_STRUCTURED_FORMAT 0x02 +#define MT_VIDEO_H263_BYTE_FORMAT 0x03 +#define MT_VIDEO_H263_FORMAT_BLOCK_HEADER_SIZE 16 + +/* ======================================================================= +** Function Declarations +** ======================================================================= */ + +/* ----------------------------------------------------------------------- +** Type Declarations +** ----------------------------------------------------------------------- */ + +// This type is used when parsing an H.264 bitstream to collect H.264 NAL +// units that need to go in the meta data. +struct H264ParamNalu { + uint32 picSetID; + uint32 seqSetID; + uint32 picOrderCntType; + bool frameMbsOnlyFlag; + bool picOrderPresentFlag; + uint32 picWidthInMbsMinus1; + uint32 picHeightInMapUnitsMinus1; + uint32 log2MaxFrameNumMinus4; + uint32 log2MaxPicOrderCntLsbMinus4; + bool deltaPicOrderAlwaysZeroFlag; + //std::vector nalu; + uint32 nalu; + uint32 crop_left; + uint32 crop_right; + uint32 crop_top; + uint32 crop_bot; +}; +//typedef map H264ParamNaluSet; +typedef Map H264ParamNaluSet; + +typedef enum { + NALU_TYPE_UNSPECIFIED = 0, + NALU_TYPE_NON_IDR, + NALU_TYPE_PARTITION_A, + NALU_TYPE_PARTITION_B, + NALU_TYPE_PARTITION_C, + NALU_TYPE_IDR, + NALU_TYPE_SEI, + NALU_TYPE_SPS, + NALU_TYPE_PPS, + NALU_TYPE_ACCESS_DELIM, + NALU_TYPE_EOSEQ, + NALU_TYPE_EOSTREAM, + NALU_TYPE_FILLER_DATA, + NALU_TYPE_RESERVED, +} NALU_TYPE; + +// NAL header information +typedef struct { + uint32 nal_ref_idc; + uint32 nalu_type; + uint32 forbidden_zero_bit; +} NALU; + +// This structure contains persistent information about an H.264 stream as it +// is parsed. +//struct H264StreamInfo { +// H264ParamNaluSet pic; +// H264ParamNaluSet seq; +//}; + +class extra_data_parser; + +class RbspParser +/****************************************************************************** + ** This class is used to convert an H.264 NALU (network abstraction layer + ** unit) into RBSP (raw byte sequence payload) and extract bits from it. + *****************************************************************************/ +{ +public: + RbspParser (const uint8 *begin, const uint8 *end); + + virtual ~RbspParser (); + + uint32 next (); + void advance (); + uint32 u (uint32 n); + uint32 ue (); + int32 se (); + +private: + const uint8 *begin, *end; + int32 pos; + uint32 bit; + uint32 cursor; + bool advanceNeeded; +}; + +class H264_Utils +{ +public: + H264_Utils(); + ~H264_Utils(); + void initialize_frame_checking_environment(); + void allocate_rbsp_buffer(uint32 inputBufferSize); + bool isNewFrame(OMX_BUFFERHEADERTYPE *p_buf_hdr, + OMX_IN OMX_U32 size_of_nal_length_field, + OMX_OUT OMX_BOOL &isNewFrame); + uint32 nalu_type; + +private: + boolean extract_rbsp(OMX_IN OMX_U8 *buffer, + OMX_IN OMX_U32 buffer_length, + OMX_IN OMX_U32 size_of_nal_length_field, + OMX_OUT OMX_U8 *rbsp_bistream, + OMX_OUT OMX_U32 *rbsp_length, + OMX_OUT NALU *nal_unit); + + unsigned m_height; + unsigned m_width; + H264ParamNaluSet pic; + H264ParamNaluSet seq; + uint8 *m_rbspBytes; + NALU m_prv_nalu; + bool m_forceToStichNextNAL; + bool m_au_data; +}; + +class perf_metrics +{ + public: + perf_metrics() : + start_time(0), + proc_time(0), + active(false) + { + }; + ~perf_metrics() {}; + void start(); + void stop(); + void end(OMX_U32 units_cntr = 0); + void reset(); + OMX_U64 processing_time_us(); + private: + inline OMX_U64 get_act_time(); + OMX_U64 start_time; + OMX_U64 proc_time; + bool active; +}; + +#define EMULATION_PREVENTION_THREE_BYTE 0x03 +#define MAX_CPB_COUNT 32 +#define NO_PAN_SCAN_BIT 0x00000100 +#define MAX_PAN_SCAN_RECT 3 +#define VALID_TS(ts) ((ts < LLONG_MAX)? true : false) +#define NALU_TYPE_VUI (NALU_TYPE_RESERVED + 1) + +enum SEI_PAYLOAD_TYPE +{ + BUFFERING_PERIOD = 0, + PIC_TIMING, + PAN_SCAN_RECT, + FILLER_PAYLOAD, + USER_DATA_REGISTERED_ITU_T_T35, + USER_DATA_UNREGISTERED, + RECOVERY_POINT, + DEC_REF_PIC_MARKING_REPETITION, + SPARE_PIC, + SCENE_INFO, + SUB_SEQ_INFO, + SUB_SEQ_LAYER_CHARACTERISTICS, + SUB_SEQ_CHARACTERISTICS, + FULL_FRAME_FREEZE, + FULL_FRAME_FREEZE_RELEASE, + FULL_FRAME_SNAPSHOT, + PROGRESSIVE_REFINEMENT_SEGMENT_START, + PROGRESSIVE_REFINEMENT_SEGMENT_END, + SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT = 0x2D +}; + +typedef struct +{ + OMX_U32 cpb_cnt; + OMX_U8 bit_rate_scale; + OMX_U8 cpb_size_scale; + OMX_U32 bit_rate_value[MAX_CPB_COUNT]; + OMX_U32 cpb_size_value[MAX_CPB_COUNT]; + OMX_U8 cbr_flag[MAX_CPB_COUNT]; + OMX_U8 initial_cpb_removal_delay_length; + OMX_U8 cpb_removal_delay_length; + OMX_U8 dpb_output_delay_length; + OMX_U8 time_offset_length; +} h264_hrd_param; + +typedef struct +{ + OMX_U32 aspect_ratio_idc; + OMX_U32 aspect_ratio_x; + OMX_U32 aspect_ratio_y; +} h264_aspect_ratio_info; + +typedef struct +{ + OMX_U8 aspect_ratio_info_present_flag; + h264_aspect_ratio_info aspect_ratio_info; + OMX_U8 timing_info_present_flag; + OMX_U32 num_units_in_tick; + OMX_U32 time_scale; + OMX_U8 fixed_frame_rate_flag; + OMX_U8 nal_hrd_parameters_present_flag; + h264_hrd_param nal_hrd_parameters; + OMX_U8 vcl_hrd_parameters_present_flag; + h264_hrd_param vcl_hrd_parameters; + OMX_U8 low_delay_hrd_flag; + OMX_U8 pic_struct_present_flag; + OMX_S64 fixed_fps_prev_ts; +} h264_vui_param; + +typedef struct +{ + OMX_U32 cpb_removal_delay; + OMX_U32 dpb_output_delay; + OMX_U8 pic_struct; + OMX_U32 num_clock_ts; + bool clock_ts_flag; + OMX_U8 ct_type; + OMX_U32 nuit_field_based_flag; + OMX_U8 counting_type; + OMX_U8 full_timestamp_flag; + OMX_U8 discontinuity_flag; + OMX_U8 cnt_dropped_flag; + OMX_U32 n_frames; + OMX_U32 seconds_value; + OMX_U32 minutes_value; + OMX_U32 hours_value; + OMX_S32 time_offset; + bool is_valid; +} h264_sei_pic_timing; + +typedef struct +{ + OMX_U32 initial_cpb_removal_delay[MAX_CPB_COUNT]; + OMX_U32 initial_cpb_removal_delay_offset[MAX_CPB_COUNT]; + OMX_U32 au_cntr; + OMX_S64 reference_ts; + bool is_valid; +} h264_sei_buf_period; + +typedef struct +{ + OMX_U32 rect_id; + OMX_U8 rect_cancel_flag; + OMX_U32 cnt; + OMX_S32 rect_left_offset[MAX_PAN_SCAN_RECT]; + OMX_S32 rect_right_offset[MAX_PAN_SCAN_RECT]; + OMX_S32 rect_top_offset[MAX_PAN_SCAN_RECT]; + OMX_S32 rect_bottom_offset[MAX_PAN_SCAN_RECT]; + OMX_U32 rect_repetition_period; +} h264_pan_scan; + +#ifdef PANSCAN_HDLR +template +class omx_dl_list +{ +public: + omx_dl_list() { head = tail = NULL; } ; + ~omx_dl_list() {}; + void add_multiple(NODE_STRUCT *data_arr, int data_num); + NODE_STRUCT *remove_first(); + NODE_STRUCT *remove_last(); + void add_last(NODE_STRUCT *data_ptr); + NODE_STRUCT *watch_first(); + NODE_STRUCT *watch_last(); +private: + NODE_STRUCT *head, *tail; +}; + +class panscan_handler +{ +public: + panscan_handler(); + ~panscan_handler(); + bool initialize(int num_data); + h264_pan_scan *get_free(); + h264_pan_scan *get_populated(OMX_S64 frame_ts); + void update_last(OMX_S64 frame_ts); +private: + typedef struct PANSCAN_NODE + { + h264_pan_scan pan_scan_param; + OMX_S64 start_ts, end_ts; + bool active; + PANSCAN_NODE *next, *prev; + } PANSCAN_NODE; + omx_dl_list panscan_used; + omx_dl_list panscan_free; + PANSCAN_NODE *panscan_data; +}; + +#if 1 // Debug panscan data + +#define PRINT_PANSCAN_PARAM(H264_PARAM) +#define PRINT_PANSCAN_DATA(NODE) + +#else + +#define PRINT_PANSCAN_PARAM(H264_PARAM) \ +do {\ + ALOGE("%s(): left_off(%ld) right_off(%ld) top_off(%ld) bottom_off(%ld)",\ + __FUNCTION__,\ + (H264_PARAM).rect_left_offset[0],\ + (H264_PARAM).rect_right_offset[0],\ + (H264_PARAM).rect_top_offset[0],\ + (H264_PARAM).rect_bottom_offset[0]);\ +}while(0) + +#define PRINT_PANSCAN_DATA(NODE) \ +do {\ + if (NODE) {\ + ALOGE("%s(): PANSCAN DATA start_ts(%lld) end_ts(%lld)", __FUNCTION__,\ + (NODE)->start_ts, (NODE)->end_ts);\ + PRINT_PANSCAN_PARAM(NODE->pan_scan_param);\ + }\ +}while(0) + +#endif // End debug panscan data + +#endif + +class h264_stream_parser +{ + public: + h264_stream_parser(); + ~h264_stream_parser(); + void reset(); + void fill_pan_scan_data(OMX_QCOM_PANSCAN *dest_pan_scan, OMX_S64 timestamp); + void fill_aspect_ratio_info(OMX_QCOM_ASPECT_RATIO *dest_aspect_ratio); + void parse_nal(OMX_U8* data_ptr, OMX_U32 data_len, + OMX_U32 nal_type = NALU_TYPE_UNSPECIFIED, + bool enable_emu_sc = true); + OMX_S64 process_ts_with_sei_vui(OMX_S64 timestamp); + void get_frame_pack_data(OMX_QCOM_FRAME_PACK_ARRANGEMENT *frame_pack); + bool is_mbaff(); + void get_frame_rate(OMX_U32 *frame_rate); +#ifdef PANSCAN_HDLR + void update_panscan_data(OMX_S64 timestamp); +#endif + private: + void init_bitstream(OMX_U8* data, OMX_U32 size); + OMX_U32 extract_bits(OMX_U32 n); + inline bool more_bits(); + void read_word(); + OMX_U32 uev(); + OMX_S32 sev(); + OMX_S32 iv(OMX_U32 n_bits); + void parse_sps(); + void parse_vui(bool vui_in_extradata = true); + void aspect_ratio_info(); + void hrd_parameters(h264_hrd_param *hrd_param); + void parse_sei(); + void sei_buffering_period(); + void sei_picture_timing(); + void sei_pan_scan(); + void scaling_list(OMX_U32 size_of_scaling_list); + + void print_pan_data(h264_pan_scan *pan_scan_param); + void print_frame_pack(); + + OMX_U32 get_nal_unit_type(OMX_U32 *nal_unit_type); + OMX_S64 calculate_buf_period_ts(OMX_S64 timestamp); + OMX_S64 calculate_fixed_fps_ts(OMX_S64 timestamp, OMX_U32 DeltaTfiDivisor); + void parse_frame_pack(); + + OMX_U32 curr_32_bit; + OMX_U32 bits_read; + OMX_U32 zero_cntr; + OMX_U32 emulation_code_skip_cntr; + OMX_U8* bitstream; + OMX_U32 bitstream_bytes; + OMX_U32 frame_rate; + bool emulation_sc_enabled; + + h264_vui_param vui_param; + h264_sei_buf_period sei_buf_period; + h264_sei_pic_timing sei_pic_timing; +#ifdef PANSCAN_HDLR + panscan_handler *panscan_hdl; +#else + h264_pan_scan panscan_param; +#endif + OMX_QCOM_FRAME_PACK_ARRANGEMENT frame_packing_arrangement; + bool mbaff_flag; +}; + +#endif /* H264_UTILS_H */ diff --git a/mm-video/vidc/vdec/inc/message_queue.h b/mm-video/vidc/vdec/inc/message_queue.h new file mode 100755 index 0000000..cbd547b --- /dev/null +++ b/mm-video/vidc/vdec/inc/message_queue.h @@ -0,0 +1,78 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef QUEUE_H +#define QUEUE_H + +#include +#include +#include +#include + +/* Message Queue structure */ +struct video_msgq +{ + /* Command to be executed */ + unsigned int cmd; + + unsigned int status; + + /* Client-specific data */ + void *clientdata; +}; + + +/* Thread & Message Queue information */ +struct video_queue_context +{ + /* Message Queue related members */ + pthread_mutex_t mutex; + sem_t sem_message; + int commandq_size; + int dataq_size; + struct video_msgq *ptr_dataq; + struct video_msgq *ptr_cmdq; + int write_dataq ; + int read_dataq; + int write_comq ; + int read_comq ; + +}; + +int check_if_queue_empty ( unsigned int queuetocheck,void* queuecontext ); + +struct video_msgq * queue_get_cmd ( void* queuecontext ); + +int queue_post_cmdq ( void *queuecontext, + struct video_msgq *post_msg + ); + +int queue_post_dataq ( void *queuecontext, + struct video_msgq *post_msg + ); + +#endif /* QUEUE_H */ diff --git a/mm-video/vidc/vdec/inc/mp4_utils.h b/mm-video/vidc/vdec/inc/mp4_utils.h new file mode 100644 index 0000000..59d3aeb --- /dev/null +++ b/mm-video/vidc/vdec/inc/mp4_utils.h @@ -0,0 +1,170 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef MP4_UTILS_H +#define MP4_UTILS_H +#include "OMX_Core.h" +#include "OMX_QCOMExtns.h" +typedef signed long long int64; +typedef unsigned long int uint32; /* Unsigned 32 bit value */ +typedef unsigned short uint16; /* Unsigned 16 bit value */ +typedef unsigned char uint8; /* Unsigned 8 bit value */ + +typedef signed long int int32; /* Signed 32 bit value */ +typedef signed short int16; /* Signed 16 bit value */ +typedef signed char int8; /* Signed 8 bit value */ + +typedef unsigned char byte; /* Unsigned 8 bit value type. */ +#define SIMPLE_PROFILE_LEVEL0 0x08 +#define SIMPLE_PROFILE_LEVEL1 0x01 +#define SIMPLE_PROFILE_LEVEL2 0x02 +#define SIMPLE_PROFILE_LEVEL3 0x03 +#define SIMPLE_PROFILE_LEVEL4A 0x04 +#define SIMPLE_PROFILE_LEVEL5 0x05 +#define SIMPLE_PROFILE_LEVEL6 0x06 +#define SIMPLE_PROFILE_LEVEL0B 0x09 + +#define SIMPLE_SCALABLE_PROFILE_LEVEL0 0x10 +#define SIMPLE_SCALABLE_PROFILE_LEVEL1 0x11 +#define SIMPLE_SCALABLE_PROFILE_LEVEL2 0x12 + +#define SIMPLE_SCALABLE_PROFILE_LEVEL0 0x10 +#define SIMPLE_SCALABLE_PROFILE_LEVEL1 0x11 +#define SIMPLE_SCALABLE_PROFILE_LEVEL2 0x12 +#define ADVANCED_SIMPLE_PROFILE_LEVEL0 0xF0 +#define ADVANCED_SIMPLE_PROFILE_LEVEL1 0xF1 +#define ADVANCED_SIMPLE_PROFILE_LEVEL2 0xF2 +#define ADVANCED_SIMPLE_PROFILE_LEVEL3 0xF3 +#define ADVANCED_SIMPLE_PROFILE_LEVEL4 0xF4 +#define ADVANCED_SIMPLE_PROFILE_LEVEL5 0xF5 + +#define VISUAL_OBJECT_SEQUENCE_START_CODE 0x000001B0 +#define MP4ERROR_SUCCESS 0 + +#define VIDEO_OBJECT_LAYER_START_CODE_MASK 0xFFFFFFF0 +#define VIDEO_OBJECT_LAYER_START_CODE 0x00000120 +#define VOP_START_CODE_MASK 0xFFFFFFFF +#define VOP_START_CODE 0x000001B6 +#define GOV_START_CODE 0x000001B3 +#define SHORT_HEADER_MASK 0xFFFFFC00 +#define SHORT_HEADER_START_MARKER 0x00008000 +#define SHORT_HEADER_START_CODE 0x00008000 +#define SPARK1_START_CODE 0x00008400 +#define MPEG4_SHAPE_RECTANGULAR 0x00 +#define EXTENDED_PAR 0xF +#define SHORT_VIDEO_START_MARKER 0x20 +#define MP4_INVALID_VOL_PARAM (0x0001) // unsupported VOL parameter +#define MP4ERROR_UNSUPPORTED_UFEP -1068 +#define MP4ERROR_UNSUPPORTED_SOURCE_FORMAT -1069 +#define MASK(x) (0xFFFFFFFF >> (32 - (x))) +#define VISUAL_OBJECT_TYPE_VIDEO_ID 0x1 +#define VISUAL_OBJECT_START_CODE 0x000001B5 +#define VIDEO_OBJECT_START_CODE_MASK 0xFFFFFFE0 +#define VIDEO_OBJECT_START_CODE 0x00000100 + +#define RESERVED_OBJECT_TYPE 0x0 +#define SIMPLE_OBJECT_TYPE 0x1 +#define SIMPLE_SCALABLE_OBJECT_TYPE 0x2 +#define CORE_OBJECT_TYPE 0x3 +#define MAIN_OBJECT_TYPE 0x4 +#define N_BIT_OBJECT_TYPE 0x5 +#define BASIC_ANIMATED_2D_TEXTURE 0x6 +#define ANIMATED_2D_MESH 0x7 +#define ADVANCED_SIMPLE 0x11 + + +#define SIMPLE_L1_MAX_VBVBUFFERSIZE 10 /* VBV Max Buffer size=10 (p. 498) */ +#define SIMPLE_L1_MAX_BITRATE 160 /* is is 64kpbs or 160 400bits/sec units */ +#define SIMPLE_L2_MAX_VBVBUFFERSIZE 40 /* VBV Max Buffer size = 40 */ +#define SIMPLE_L2_MAX_BITRATE 320 /* 320 400bps units = 128kpbs */ +#define SIMPLE_L3_MAX_VBVBUFFERSIZE 40 /* VBV Max Buffer size = 40 */ +#define SIMPLE_L3_MAX_BITRATE 960 /* 960 400bps units = 384kpbs */ + +/* The MP4 decoder currently supports Simple Profile@L3 */ +#define MAX_VBVBUFFERSIZE (SIMPLE_L3_MAX_VBVBUFFERSIZE) +#define MAX_BITRATE (SIMPLE_L3_MAX_BITRATE) + +#define MAX_QUANTPRECISION 9 +#define MIN_QUANTPRECISION 3 + +#define MP4_VGA_WIDTH 640 +#define MP4_VGA_HEIGHT 480 +#define MP4_WVGA_WIDTH 800 +#define MP4_WVGA_HEIGHT 480 +#define MP4_720P_WIDTH 1280 +#define MP4_720P_HEIGHT 720 + +#define MP4_MAX_DECODE_WIDTH MP4_720P_WIDTH +#define MP4_MAX_DECODE_HEIGHT MP4_720P_HEIGHT + +typedef struct { + unsigned char *data; + unsigned long int numBytes; +} mp4StreamType; + +#define MAX_FRAMES_IN_CHUNK 10 +#define VOP_START_CODE 0x000001B6 +#define VOL_START_CODE 0x000001B0 + +typedef enum VOPTYPE +{ + NO_VOP = -1, // bitstream contains no VOP. + MPEG4_I_VOP = 0, // bitstream contains an MPEG4 I-VOP + MPEG4_P_VOP = 1, // bitstream contains an MPEG4 P-VOP + MPEG4_B_VOP = 2, // bitstream contains an MPEG4 B-VOP + MPEG4_S_VOP = 3, // bitstream contains an MPEG4 S-VOP +} VOP_TYPE; + +typedef struct +{ + uint32 timestamp_increment; + uint32 offset; + uint32 size; + VOP_TYPE vopType; +} mp4_frame_info_type; + +class MP4_Utils { +private: + struct posInfoType { + uint8 *bytePtr; + uint8 bitPos; + }; + + posInfoType m_posInfo; + byte *m_dataBeginPtr; + unsigned int vop_time_resolution; + bool vop_time_found; + uint16 m_SrcWidth, m_SrcHeight; // Dimensions of the source clip +public: + MP4_Utils(); + ~MP4_Utils(); + int16 populateHeightNWidthFromShortHeader(mp4StreamType * psBits); + bool parseHeader(mp4StreamType * psBits); + static uint32 read_bit_field(posInfoType * posPtr, uint32 size); + bool is_notcodec_vop(unsigned char *pbuffer, unsigned int len); +}; +#endif diff --git a/mm-video/vidc/vdec/inc/omx_vdec.h b/mm-video/vidc/vdec/inc/omx_vdec.h new file mode 100755 index 0000000..507ecab --- /dev/null +++ b/mm-video/vidc/vdec/inc/omx_vdec.h @@ -0,0 +1,863 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef __OMX_VDEC_H__ +#define __OMX_VDEC_H__ +/*============================================================================ + O p e n M A X Component + Video Decoder + +*//** @file comx_vdec.h + This module contains the class definition for openMAX decoder component. + +*//*========================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +static ptrdiff_t x; + +#ifdef _ANDROID_ +#ifdef MAX_RES_720P +#define LOG_TAG "OMX-VDEC-720P" +#elif MAX_RES_1080P +#define LOG_TAG "OMX-VDEC-1080P" +#else +#define LOG_TAG "OMX-VDEC" +#endif + +#ifdef USE_ION +#include +//#include //TBD - uncomment this +//#include +//#else +#endif +#include +#include +extern "C"{ +#include +} +#include +#include +#define TIMEOUT 5000 +#ifdef ENABLE_DEBUG_LOW +#define DEBUG_PRINT_LOW ALOGE +#else +#define DEBUG_PRINT_LOW +#endif +#ifdef ENABLE_DEBUG_HIGH +#define DEBUG_PRINT_HIGH ALOGE +#else +#define DEBUG_PRINT_HIGH +#endif +#ifdef ENABLE_DEBUG_ERROR +#define DEBUG_PRINT_ERROR ALOGE +#else +#define DEBUG_PRINT_ERROR +#endif + +#else //_ANDROID_ +#define DEBUG_PRINT_LOW printf +#define DEBUG_PRINT_HIGH printf +#define DEBUG_PRINT_ERROR printf +#endif // _ANDROID_ + +#ifdef _MSM8974_ +#define DEBUG_PRINT_LOW +#define DEBUG_PRINT_HIGH printf +#define DEBUG_PRINT_ERROR printf +#endif + +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) +#include +#endif + +#include + +#if defined (_ANDROID_ICS_) +#include +#endif + +#include +#ifndef PC_DEBUG +#include +#endif +#include "OMX_Core.h" +#include "OMX_QCOMExtns.h" +#include "qc_omx_component.h" +#include +#include "frameparser.h" +#ifdef MAX_RES_1080P +#include "mp4_utils.h" +#endif +#include +#include "extra_data_handler.h" +#include "ts_parser.h" + +extern "C" { + OMX_API void * get_omx_component_factory_fn(void); +} + +#ifdef _ANDROID_ + using namespace android; +#ifdef USE_ION + class VideoHeap : public MemoryHeapBase + { + public: + VideoHeap(int devicefd, size_t size, void* base,struct ion_handle *handle,int mapfd); + virtual ~VideoHeap() {} + private: + int m_ion_device_fd; + struct ion_handle *m_ion_handle; + }; +#else + // local pmem heap object + class VideoHeap : public MemoryHeapBase + { + public: + VideoHeap(int fd, size_t size, void* base); + virtual ~VideoHeap() {} + }; +#endif +#endif // _ANDROID_ +////////////////////////////////////////////////////////////////////////////// +// Module specific globals +////////////////////////////////////////////////////////////////////////////// +#define OMX_SPEC_VERSION 0x00000101 + + +////////////////////////////////////////////////////////////////////////////// +// Macros +////////////////////////////////////////////////////////////////////////////// +#define PrintFrameHdr(bufHdr) DEBUG_PRINT("bufHdr %x buf %x size %d TS %d\n",\ + (unsigned) bufHdr,\ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->pBuffer,\ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFilledLen,\ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nTimeStamp) + +// BitMask Management logic +#define BITS_PER_BYTE 32 +#define BITMASK_SIZE(mIndex) (((mIndex) + BITS_PER_BYTE - 1)/BITS_PER_BYTE) +#define BITMASK_OFFSET(mIndex) ((mIndex)/BITS_PER_BYTE) +#define BITMASK_FLAG(mIndex) (1 << ((mIndex) % BITS_PER_BYTE)) +#define BITMASK_CLEAR(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \ + &= ~(BITMASK_FLAG(mIndex)) +#define BITMASK_SET(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \ + |= BITMASK_FLAG(mIndex) +#define BITMASK_PRESENT(mArray,mIndex) ((mArray)[BITMASK_OFFSET(mIndex)] \ + & BITMASK_FLAG(mIndex)) +#define BITMASK_ABSENT(mArray,mIndex) (((mArray)[BITMASK_OFFSET(mIndex)] \ + & BITMASK_FLAG(mIndex)) == 0x0) +#define BITMASK_PRESENT(mArray,mIndex) ((mArray)[BITMASK_OFFSET(mIndex)] \ + & BITMASK_FLAG(mIndex)) +#define BITMASK_ABSENT(mArray,mIndex) (((mArray)[BITMASK_OFFSET(mIndex)] \ + & BITMASK_FLAG(mIndex)) == 0x0) + +#define OMX_CORE_CONTROL_CMDQ_SIZE 100 +#define OMX_CORE_QCIF_HEIGHT 144 +#define OMX_CORE_QCIF_WIDTH 176 +#define OMX_CORE_VGA_HEIGHT 480 +#define OMX_CORE_VGA_WIDTH 640 +#define OMX_CORE_WVGA_HEIGHT 480 +#define OMX_CORE_WVGA_WIDTH 800 + +#define DESC_BUFFER_SIZE (8192 * 16) + +#ifdef _ANDROID_ +#define MAX_NUM_INPUT_OUTPUT_BUFFERS 32 +#endif + +#define OMX_FRAMEINFO_EXTRADATA 0x00010000 +#define OMX_INTERLACE_EXTRADATA 0x00020000 +#define OMX_TIMEINFO_EXTRADATA 0x00040000 +#define OMX_PORTDEF_EXTRADATA 0x00080000 +#define DRIVER_EXTRADATA_MASK 0x0000FFFF + +#define OMX_INTERLACE_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\ + sizeof(OMX_STREAMINTERLACEFORMAT) + 3)&(~3)) +#define OMX_FRAMEINFO_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\ + sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO) + 3)&(~3)) +#define OMX_PORTDEF_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\ + sizeof(OMX_PARAM_PORTDEFINITIONTYPE) + 3)&(~3)) + +// Define next macro with required values to enable default extradata, +// VDEC_EXTRADATA_MB_ERROR_MAP +// OMX_INTERLACE_EXTRADATA +// OMX_FRAMEINFO_EXTRADATA +// OMX_TIMEINFO_EXTRADATA + +//#define DEFAULT_EXTRADATA (OMX_FRAMEINFO_EXTRADATA|OMX_INTERLACE_EXTRADATA) + +enum port_indexes +{ + OMX_CORE_INPUT_PORT_INDEX =0, + OMX_CORE_OUTPUT_PORT_INDEX =1 +}; +#ifdef USE_ION +struct vdec_ion +{ + int ion_device_fd; + struct ion_fd_data fd_ion_data; + struct ion_allocation_data ion_alloc_data; +}; +#endif + +struct video_driver_context +{ + int video_driver_fd; + enum vdec_codec decoder_format; + enum vdec_output_fromat output_format; + enum vdec_interlaced_format interlace; + enum vdec_output_order picture_order; + struct vdec_picsize video_resolution; + struct vdec_allocatorproperty ip_buf; + struct vdec_allocatorproperty op_buf; + struct vdec_bufferpayload *ptr_inputbuffer; + struct vdec_bufferpayload *ptr_outputbuffer; + struct vdec_output_frameinfo *ptr_respbuffer; +#ifdef USE_ION + struct vdec_ion *ip_buf_ion_info; + struct vdec_ion *op_buf_ion_info; + struct vdec_ion h264_mv; +#endif + struct vdec_framerate frame_rate; + unsigned extradata; + bool timestamp_adjust; + char kind[128]; + bool idr_only_decoding; + unsigned disable_dmx; +}; + +#ifdef _ANDROID_ +class DivXDrmDecrypt; +#endif //_ANDROID_ + +// OMX video decoder class +class omx_vdec: public qc_omx_component +{ + +public: + omx_vdec(); // constructor + virtual ~omx_vdec(); // destructor + + static int async_message_process (void *context, void* message); + static void process_event_cb(void *ctxt,unsigned char id); + + OMX_ERRORTYPE allocate_buffer( + OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes + ); + + + OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE hComp); + + OMX_ERRORTYPE component_init(OMX_STRING role); + + OMX_ERRORTYPE component_role_enum( + OMX_HANDLETYPE hComp, + OMX_U8 *role, + OMX_U32 index + ); + + OMX_ERRORTYPE component_tunnel_request( + OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_HANDLETYPE peerComponent, + OMX_U32 peerPort, + OMX_TUNNELSETUPTYPE *tunnelSetup + ); + + OMX_ERRORTYPE empty_this_buffer( + OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer + ); + + + + OMX_ERRORTYPE fill_this_buffer( + OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer + ); + + + OMX_ERRORTYPE free_buffer( + OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_BUFFERHEADERTYPE *buffer + ); + + OMX_ERRORTYPE get_component_version( + OMX_HANDLETYPE hComp, + OMX_STRING componentName, + OMX_VERSIONTYPE *componentVersion, + OMX_VERSIONTYPE *specVersion, + OMX_UUIDTYPE *componentUUID + ); + + OMX_ERRORTYPE get_config( + OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData + ); + + OMX_ERRORTYPE get_extension_index( + OMX_HANDLETYPE hComp, + OMX_STRING paramName, + OMX_INDEXTYPE *indexType + ); + + OMX_ERRORTYPE get_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + + OMX_ERRORTYPE get_state(OMX_HANDLETYPE hComp, + OMX_STATETYPE *state); + + + + OMX_ERRORTYPE send_command(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + + + OMX_ERRORTYPE set_callbacks(OMX_HANDLETYPE hComp, + OMX_CALLBACKTYPE *callbacks, + OMX_PTR appData); + + OMX_ERRORTYPE set_config(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData); + + OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + + OMX_ERRORTYPE use_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes, + OMX_U8 *buffer); + + OMX_ERRORTYPE use_input_heap_buffers( + OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes, + OMX_U8* buffer); + + OMX_ERRORTYPE use_EGL_image(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + void * eglImage); + void complete_pending_buffer_done_cbs(); + struct video_driver_context drv_ctx; + int m_pipe_in; + int m_pipe_out; + pthread_t msg_thread_id; + pthread_t async_thread_id; + +private: + // Bit Positions + enum flags_bit_positions + { + // Defer transition to IDLE + OMX_COMPONENT_IDLE_PENDING =0x1, + // Defer transition to LOADING + OMX_COMPONENT_LOADING_PENDING =0x2, + // First Buffer Pending + OMX_COMPONENT_FIRST_BUFFER_PENDING =0x3, + // Second Buffer Pending + OMX_COMPONENT_SECOND_BUFFER_PENDING =0x4, + // Defer transition to Enable + OMX_COMPONENT_INPUT_ENABLE_PENDING =0x5, + // Defer transition to Enable + OMX_COMPONENT_OUTPUT_ENABLE_PENDING =0x6, + // Defer transition to Disable + OMX_COMPONENT_INPUT_DISABLE_PENDING =0x7, + // Defer transition to Disable + OMX_COMPONENT_OUTPUT_DISABLE_PENDING =0x8, + //defer flush notification + OMX_COMPONENT_OUTPUT_FLUSH_PENDING =0x9, + OMX_COMPONENT_INPUT_FLUSH_PENDING =0xA, + OMX_COMPONENT_PAUSE_PENDING =0xB, + OMX_COMPONENT_EXECUTE_PENDING =0xC, + OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING =0xD, + OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED=0xE + }; + + // Deferred callback identifiers + enum + { + //Event Callbacks from the vdec component thread context + OMX_COMPONENT_GENERATE_EVENT = 0x1, + //Buffer Done callbacks from the vdec component thread context + OMX_COMPONENT_GENERATE_BUFFER_DONE = 0x2, + //Frame Done callbacks from the vdec component thread context + OMX_COMPONENT_GENERATE_FRAME_DONE = 0x3, + //Buffer Done callbacks from the vdec component thread context + OMX_COMPONENT_GENERATE_FTB = 0x4, + //Frame Done callbacks from the vdec component thread context + OMX_COMPONENT_GENERATE_ETB = 0x5, + //Command + OMX_COMPONENT_GENERATE_COMMAND = 0x6, + //Push-Pending Buffers + OMX_COMPONENT_PUSH_PENDING_BUFS = 0x7, + // Empty Buffer Done callbacks + OMX_COMPONENT_GENERATE_EBD = 0x8, + //Flush Event Callbacks from the vdec component thread context + OMX_COMPONENT_GENERATE_EVENT_FLUSH = 0x9, + OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH = 0x0A, + OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH = 0x0B, + OMX_COMPONENT_GENERATE_FBD = 0xc, + OMX_COMPONENT_GENERATE_START_DONE = 0xD, + OMX_COMPONENT_GENERATE_PAUSE_DONE = 0xE, + OMX_COMPONENT_GENERATE_RESUME_DONE = 0xF, + OMX_COMPONENT_GENERATE_STOP_DONE = 0x10, + OMX_COMPONENT_GENERATE_HARDWARE_ERROR = 0x11, + OMX_COMPONENT_GENERATE_ETB_ARBITRARY = 0x12, + OMX_COMPONENT_GENERATE_PORT_RECONFIG = 0x13, + OMX_COMPONENT_GENERATE_EOS_DONE = 0x14, + OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG = 0x15, + OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED = 0x16, + }; + + enum vc1_profile_type + { + VC1_SP_MP_RCV = 1, + VC1_AP = 2 + }; + +#ifdef _MSM8974_ + enum v4l2_ports + { + CAPTURE_PORT, + OUTPUT_PORT, + MAX_PORT + }; +#endif + + struct omx_event + { + unsigned param1; + unsigned param2; + unsigned id; + }; + + struct omx_cmd_queue + { + omx_event m_q[OMX_CORE_CONTROL_CMDQ_SIZE]; + unsigned m_read; + unsigned m_write; + unsigned m_size; + + omx_cmd_queue(); + ~omx_cmd_queue(); + bool insert_entry(unsigned p1, unsigned p2, unsigned id); + bool pop_entry(unsigned *p1,unsigned *p2, unsigned *id); + // get msgtype of the first ele from the queue + unsigned get_q_msg_type(); + + }; + +#ifdef _ANDROID_ + struct ts_entry + { + OMX_TICKS timestamp; + bool valid; + }; + + struct ts_arr_list + { + ts_entry m_ts_arr_list[MAX_NUM_INPUT_OUTPUT_BUFFERS]; + + ts_arr_list(); + ~ts_arr_list(); + + bool insert_ts(OMX_TICKS ts); + bool pop_min_ts(OMX_TICKS &ts); + bool reset_ts_list(); + }; +#endif + + struct desc_buffer_hdr + { + OMX_U8 *buf_addr; + OMX_U32 desc_data_size; + }; + bool allocate_done(void); + bool allocate_input_done(void); + bool allocate_output_done(void); + + OMX_ERRORTYPE free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr); + OMX_ERRORTYPE free_input_buffer(unsigned int bufferindex, + OMX_BUFFERHEADERTYPE *pmem_bufferHdr); + OMX_ERRORTYPE free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr); + void free_output_buffer_header(); + void free_input_buffer_header(); + + OMX_ERRORTYPE allocate_input_heap_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes); + + + OMX_ERRORTYPE allocate_input_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes); + + OMX_ERRORTYPE allocate_output_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port,OMX_PTR appData, + OMX_U32 bytes); + + OMX_ERRORTYPE use_output_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes, + OMX_U8 *buffer); +#ifdef MAX_RES_720P + OMX_ERRORTYPE get_supported_profile_level_for_720p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType); +#endif +#ifdef MAX_RES_1080P + OMX_ERRORTYPE get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType); +#endif + + OMX_ERRORTYPE allocate_desc_buffer(OMX_U32 index); + OMX_ERRORTYPE allocate_output_headers(); + bool execute_omx_flush(OMX_U32); + bool execute_output_flush(); + bool execute_input_flush(); + OMX_ERRORTYPE empty_buffer_done(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE * buffer); + + OMX_ERRORTYPE fill_buffer_done(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE * buffer); + OMX_ERRORTYPE empty_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + OMX_ERRORTYPE empty_this_buffer_proxy_arbitrary(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer + ); + + OMX_ERRORTYPE push_input_buffer (OMX_HANDLETYPE hComp); + OMX_ERRORTYPE push_input_sc_codec (OMX_HANDLETYPE hComp); + OMX_ERRORTYPE push_input_h264 (OMX_HANDLETYPE hComp); + OMX_ERRORTYPE push_input_vc1 (OMX_HANDLETYPE hComp); + + OMX_ERRORTYPE fill_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + bool release_done(); + + bool release_output_done(); + bool release_input_done(); + OMX_ERRORTYPE get_buffer_req(vdec_allocatorproperty *buffer_prop); + OMX_ERRORTYPE set_buffer_req(vdec_allocatorproperty *buffer_prop); + OMX_ERRORTYPE start_port_reconfig(); + OMX_ERRORTYPE update_picture_resolution(); + void stream_off(); + void adjust_timestamp(OMX_S64 &act_timestamp); + void set_frame_rate(OMX_S64 act_timestamp); + void handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr); + OMX_ERRORTYPE enable_extradata(OMX_U32 requested_extradata, bool enable = true); + void print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra); + void append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra, + OMX_U32 interlaced_format_type); + void append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra, + OMX_U32 num_conceal_mb, + OMX_U32 picture_type, + OMX_S64 timestamp, + OMX_U32 frame_rate, + struct vdec_aspectratioinfo *aspect_ratio_info); + void fill_aspect_ratio_info(struct vdec_aspectratioinfo *aspect_ratio_info, + OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info); + void append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra); + OMX_ERRORTYPE update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn); + void append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra); + void insert_demux_addr_offset(OMX_U32 address_offset); + void extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr); + OMX_ERRORTYPE handle_demux_data(OMX_BUFFERHEADERTYPE *buf_hdr); + OMX_U32 count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra); + + bool align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size, + OMX_U32 alignment); +#ifdef USE_ION + int alloc_map_ion_memory(OMX_U32 buffer_size, + OMX_U32 alignment, struct ion_allocation_data *alloc_data, + struct ion_fd_data *fd_data,int flag); + void free_ion_memory(struct vdec_ion *buf_ion_info); +#endif + + + OMX_ERRORTYPE send_command_proxy(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + bool post_event( unsigned int p1, + unsigned int p2, + unsigned int id + ); + inline int clip2(int x) + { + x = x -1; + x = x | x >> 1; + x = x | x >> 2; + x = x | x >> 4; + x = x | x >> 16; + x = x + 1; + return x; + } + +#ifdef MAX_RES_1080P + OMX_ERRORTYPE vdec_alloc_h264_mv(); + void vdec_dealloc_h264_mv(); +#endif + + inline void omx_report_error () + { + if (m_cb.EventHandler && !m_error_propogated) + { + ALOGE("\nERROR: Sending OMX_EventError to Client"); + m_error_propogated = true; + m_cb.EventHandler(&m_cmp,m_app_data, + OMX_EventError,OMX_ErrorHardware,0,NULL); + } + } +#ifdef _ANDROID_ + OMX_ERRORTYPE createDivxDrmContext(); +#endif //_ANDROID_ +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) + OMX_ERRORTYPE use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data); +#endif +#if defined (_ANDROID_ICS_) + struct nativebuffer{ + native_handle_t *nativehandle; + int inuse; + }; + nativebuffer native_buffer[MAX_NUM_INPUT_OUTPUT_BUFFERS]; +#endif + + + //************************************************************* + //*******************MEMBER VARIABLES ************************* + //************************************************************* + pthread_mutex_t m_lock; + //sem to handle the minimum procesing of commands + sem_t m_cmd_lock; + bool m_error_propogated; + // compression format + OMX_VIDEO_CODINGTYPE eCompressionFormat; + // OMX State + OMX_STATETYPE m_state; + // Application data + OMX_PTR m_app_data; + // Application callbacks + OMX_CALLBACKTYPE m_cb; + OMX_PRIORITYMGMTTYPE m_priority_mgm ; + OMX_PARAM_BUFFERSUPPLIERTYPE m_buffer_supplier; + // fill this buffer queue + omx_cmd_queue m_ftb_q; + // Command Q for rest of the events + omx_cmd_queue m_cmd_q; + omx_cmd_queue m_etb_q; + // Input memory pointer + OMX_BUFFERHEADERTYPE *m_inp_mem_ptr; + // Output memory pointer + OMX_BUFFERHEADERTYPE *m_out_mem_ptr; + // number of input bitstream error frame count + unsigned int m_inp_err_count; +#ifdef _ANDROID_ + // Timestamp list + ts_arr_list m_timestamp_list; +#endif + + bool input_flush_progress; + bool output_flush_progress; + bool input_use_buffer; + bool output_use_buffer; + bool ouput_egl_buffers; + OMX_BOOL m_use_output_pmem; + OMX_BOOL m_out_mem_region_smi; + OMX_BOOL m_out_pvt_entry_pmem; + + int pending_input_buffers; + int pending_output_buffers; + // bitmask array size for output side + unsigned int m_out_bm_count; + // bitmask array size for input side + unsigned int m_inp_bm_count; + //Input port Populated + OMX_BOOL m_inp_bPopulated; + //Output port Populated + OMX_BOOL m_out_bPopulated; + // encapsulate the waiting states. + unsigned int m_flags; + +#ifdef _ANDROID_ + // Heap pointer to frame buffers + struct vidc_heap + { + sp video_heap_ptr; + }; + struct vidc_heap *m_heap_ptr; + unsigned int m_heap_count; +#endif //_ANDROID_ + // store I/P PORT state + OMX_BOOL m_inp_bEnabled; + // store O/P PORT state + OMX_BOOL m_out_bEnabled; + OMX_U32 m_in_alloc_cnt; + OMX_U8 m_cRole[OMX_MAX_STRINGNAME_SIZE]; + // Platform specific details + OMX_QCOM_PLATFORM_PRIVATE_LIST *m_platform_list; + OMX_QCOM_PLATFORM_PRIVATE_ENTRY *m_platform_entry; + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *m_pmem_info; + // SPS+PPS sent as part of set_config + OMX_VENDOR_EXTRADATATYPE m_vendor_config; + + /*Variables for arbitrary Byte parsing support*/ + frame_parse m_frame_parser; + omx_cmd_queue m_input_pending_q; + omx_cmd_queue m_input_free_q; + bool arbitrary_bytes; + OMX_BUFFERHEADERTYPE h264_scratch; + OMX_BUFFERHEADERTYPE *psource_frame; + OMX_BUFFERHEADERTYPE *pdest_frame; + OMX_BUFFERHEADERTYPE *m_inp_heap_ptr; + OMX_BUFFERHEADERTYPE **m_phdr_pmem_ptr; + unsigned int m_heap_inp_bm_count; + codec_type codec_type_parse; + bool first_frame_meta; + unsigned frame_count; + unsigned nal_count; + unsigned nal_length; + bool look_ahead_nal; + int first_frame; + unsigned char *first_buffer; + int first_frame_size; + unsigned char m_hwdevice_name[80]; + FILE *m_device_file_ptr; + enum vc1_profile_type m_vc1_profile; + OMX_S64 h264_last_au_ts; + OMX_U32 h264_last_au_flags; + OMX_U32 m_demux_offsets[8192]; + OMX_U32 m_demux_entries; + + OMX_S64 prev_ts; + bool rst_prev_ts; + OMX_U32 frm_int; + + struct vdec_allocatorproperty op_buf_rcnfg; + bool in_reconfig; + OMX_NATIVE_WINDOWTYPE m_display_id; + h264_stream_parser *h264_parser; + OMX_U32 client_extradata; +#ifdef _ANDROID_ + bool m_debug_timestamp; + bool perf_flag; + OMX_U32 proc_frms, latency; + perf_metrics fps_metrics; + perf_metrics dec_time; + bool m_enable_android_native_buffers; + bool m_use_android_native_buffers; + bool m_debug_extradata; + bool m_debug_concealedmb; +#endif +#ifdef MAX_RES_1080P + MP4_Utils mp4_headerparser; +#endif + + struct h264_mv_buffer{ + unsigned char* buffer; + int size; + int count; + int pmem_fd; + int offset; + }; + h264_mv_buffer h264_mv_buff; + extra_data_handler extra_data_handle; +#ifdef _ANDROID_ + DivXDrmDecrypt* iDivXDrmDecrypt; +#endif //_ANDROID_ + OMX_PARAM_PORTDEFINITIONTYPE m_port_def; + omx_time_stamp_reorder time_stamp_dts; + desc_buffer_hdr *m_desc_buffer_ptr; + bool secure_mode; + OMX_QCOM_EXTRADATA_FRAMEINFO *m_extradata; + bool codec_config_flag; +#ifdef _MSM8974_ + int capture_capability; + int output_capability; + bool streaming[MAX_PORT]; +#endif +}; + +#ifdef _MSM8974_ +enum instance_state { + MSM_VIDC_CORE_UNINIT_DONE = 0x0001, + MSM_VIDC_CORE_INIT, + MSM_VIDC_CORE_INIT_DONE, + MSM_VIDC_OPEN, + MSM_VIDC_OPEN_DONE, + MSM_VIDC_LOAD_RESOURCES, + MSM_VIDC_LOAD_RESOURCES_DONE, + MSM_VIDC_START, + MSM_VIDC_START_DONE, + MSM_VIDC_STOP, + MSM_VIDC_STOP_DONE, + MSM_VIDC_RELEASE_RESOURCES, + MSM_VIDC_RELEASE_RESOURCES_DONE, + MSM_VIDC_CLOSE, + MSM_VIDC_CLOSE_DONE, + MSM_VIDC_CORE_UNINIT, +}; + +enum vidc_resposes_id { + MSM_VIDC_DECODER_FLUSH_DONE = 0x11, + MSM_VIDC_DECODER_EVENT_CHANGE, +}; + +#endif // _MSM8974_ + +#endif // __OMX_VDEC_H__ diff --git a/mm-video/vidc/vdec/inc/qtypes.h b/mm-video/vidc/vdec/inc/qtypes.h new file mode 100755 index 0000000..3cff46e --- /dev/null +++ b/mm-video/vidc/vdec/inc/qtypes.h @@ -0,0 +1,90 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef QTYPES_H +#define QTYPES_H +/*=========================================================================== + + Data Declarations + +===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------------------------------------------------------ +** Constants +** ------------------------------------------------------------------------ */ + +#ifdef TRUE +#undef TRUE +#endif + +#ifdef FALSE +#undef FALSE +#endif + +#define TRUE 1 /* Boolean true value. */ +#define FALSE 0 /* Boolean false value. */ + + + +/* ----------------------------------------------------------------------- +** Standard Types +** ----------------------------------------------------------------------- */ + +/* The following definitions are the same accross platforms. This first +** group are the sanctioned types. +*/ + +typedef unsigned char boolean; /* Boolean value type. */ + +typedef unsigned long int uint32; /* Unsigned 32 bit value */ +typedef unsigned short uint16; /* Unsigned 16 bit value */ +typedef unsigned char uint8; /* Unsigned 8 bit value */ + +typedef signed long int int32; /* Signed 32 bit value */ +typedef signed short int16; /* Signed 16 bit value */ +typedef signed char int8; /* Signed 8 bit value */ + +/* This group are the deprecated types. Their use should be +** discontinued and new code should use the types above +*/ +typedef unsigned char byte; /* Unsigned 8 bit value type. */ +typedef unsigned short word; /* Unsinged 16 bit value type. */ +typedef unsigned long dword; /* Unsigned 32 bit value type. */ + +typedef long long int64; +typedef unsigned long long uint64; + + +#ifdef __cplusplus +} +#endif + +#endif /* QTYPES_H */ diff --git a/mm-video/vidc/vdec/inc/queue.h b/mm-video/vidc/vdec/inc/queue.h new file mode 100755 index 0000000..195d9b2 --- /dev/null +++ b/mm-video/vidc/vdec/inc/queue.h @@ -0,0 +1,39 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef QUEUE_H +#define QUEUE_H + +typedef struct Queue Queue; + +Queue *alloc_queue(); +void free_queue(Queue *q); +void free_queue_and_qelement(Queue *q); +int push(Queue *q, void * element); +void *pop(Queue *q); + +#endif diff --git a/mm-video/vidc/vdec/inc/ts_parser.h b/mm-video/vidc/vdec/inc/ts_parser.h new file mode 100755 index 0000000..273c899 --- /dev/null +++ b/mm-video/vidc/vdec/inc/ts_parser.h @@ -0,0 +1,88 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef __DTSPARSER_H +#define __DTSPARSER_H + +#include "OMX_Core.h" +#include "OMX_QCOMExtns.h" +#include "qc_omx_component.h" + +#include + +#include +#include + +#ifdef _ANDROID_ +extern "C"{ +#include +} +#else +#define ALOGE(fmt, args...) fprintf(stderr, fmt, ##args) +#endif /* _ANDROID_ */ + +class omx_time_stamp_reorder { +public: + omx_time_stamp_reorder(); + ~omx_time_stamp_reorder(); + void set_timestamp_reorder_mode(bool flag); + void enable_debug_print(bool flag); + bool insert_timestamp(OMX_BUFFERHEADERTYPE *header); + bool get_next_timestamp(OMX_BUFFERHEADERTYPE *header, bool is_interlaced); + bool remove_time_stamp(OMX_TICKS ts, bool is_interlaced); + void flush_timestamp(); + +private: + #define TIME_SZ 64 + typedef struct timestamp { + OMX_TICKS timestamps; + bool in_use; + }timestamp; + typedef struct time_stamp_list { + timestamp input_timestamps[TIME_SZ]; + time_stamp_list *next; + time_stamp_list *prev; + unsigned int entries_filled; + }time_stamp_list; + bool error; + time_stamp_list *phead,*pcurrent; + bool get_current_list(); + bool add_new_list(); + bool update_head(); + void delete_list(); + void handle_error() + { + ALOGE("Error handler called for TS Parser"); + if (error) + return; + error = true; + delete_list(); + } + bool reorder_ts; + bool print_debug; +}; +#endif diff --git a/mm-video/vidc/vdec/src/frameparser.cpp b/mm-video/vidc/vdec/src/frameparser.cpp new file mode 100755 index 0000000..e1768b0 --- /dev/null +++ b/mm-video/vidc/vdec/src/frameparser.cpp @@ -0,0 +1,668 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "frameparser.h" +#include "omx_vdec.h" + +#ifdef _ANDROID_ + extern "C"{ + #include + } +#endif//_ANDROID_ + +static unsigned char H264_mask_code[4] = {0xFF,0xFF,0xFF,0xFF}; +static unsigned char H264_start_code[4] = {0x00,0x00,0x00,0x01}; + +static unsigned char MPEG4_start_code[4] = {0x00,0x00,0x01,0xB6}; +static unsigned char MPEG4_mask_code[4] = {0xFF,0xFF,0xFF,0xFF}; + +static unsigned char H263_start_code[4] = {0x00,0x00,0x80,0x00}; +static unsigned char H263_mask_code[4] = {0xFF,0xFF,0xFC,0x00}; + +static unsigned char VC1_AP_start_code[4] = {0x00,0x00,0x01,0x0C}; +static unsigned char VC1_AP_mask_code[4] = {0xFF,0xFF,0xFF,0xFC}; + +static unsigned char MPEG2_start_code[4] = {0x00, 0x00, 0x01, 0x00}; +static unsigned char MPEG2_mask_code[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + +frame_parse::frame_parse():parse_state(A0), + last_byte_h263(0), + state_nal(NAL_LENGTH_ACC), + nal_length(0), + accum_length(0), + bytes_tobeparsed(0), + mutils(NULL), + start_code(NULL), + mask_code(NULL), + header_found(false), + skip_frame_boundary(false) +{ +} + +frame_parse::~frame_parse () +{ + if (mutils) + delete mutils; + + mutils = NULL; +} + +int frame_parse::init_start_codes (codec_type codec_type_parse) +{ + /*Check if Codec Type is proper and we are in proper state*/ + if (codec_type_parse > CODEC_TYPE_MAX || parse_state != A0) + { + return -1; + } + + switch (codec_type_parse) + { + case CODEC_TYPE_MPEG4: + start_code = MPEG4_start_code; + mask_code = MPEG4_mask_code; + break; + case CODEC_TYPE_H263: + start_code = H263_start_code; + mask_code = H263_mask_code; + break; + case CODEC_TYPE_H264: + start_code = H264_start_code; + mask_code = H264_mask_code; + break; + case CODEC_TYPE_VC1: + start_code = VC1_AP_start_code; + mask_code = VC1_AP_mask_code; + break; + case CODEC_TYPE_MPEG2: + start_code = MPEG2_start_code; + mask_code = MPEG2_mask_code; + break; + } + return 1; +} + + +int frame_parse::init_nal_length (unsigned int nal_len) +{ + if (nal_len == 0 || nal_len > 4 || state_nal != NAL_LENGTH_ACC) + { + return -1; + } + nal_length = nal_len; + + return 1; +} + +int frame_parse::parse_sc_frame ( OMX_BUFFERHEADERTYPE *source, + OMX_BUFFERHEADERTYPE *dest , + OMX_U32 *partialframe) +{ + OMX_U8 *pdest = NULL,*psource = NULL, match_found = FALSE, is_byte_match = 0; + OMX_U32 dest_len =0, source_len = 0, temp_len = 0; + OMX_U32 parsed_length = 0,i=0; + int residue_byte = 0; + + if (source == NULL || dest == NULL || partialframe == NULL) + { + return -1; + } + + /*Calculate how many bytes are left in source and destination*/ + dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset); + psource = source->pBuffer + source->nOffset; + pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset); + source_len = source->nFilledLen; + + /*Need Minimum Start Code size for destination to copy atleast Start code*/ + if ((start_code == H263_start_code && dest_len < 3) || + (start_code != H263_start_code && dest_len < 4) || (source_len == 0)) + { + DEBUG_PRINT_LOW("\n FrameParser: dest_len %d source_len %d",dest_len,source_len); + if (source_len == 0 && (source->nFlags & 0x01)) + { + DEBUG_PRINT_LOW("\n FrameParser: EOS rxd!! Notify it as a complete frame"); + *partialframe = 0; + return 1; + } + DEBUG_PRINT_LOW("\n FrameParser: Bitstream Parsing error"); + return -1; + } + + /*Check if State of the previous find is a Start code*/ + if (parse_state == A4 || parse_state == A5) + { + /*Check for minimun size should be 4*/ + dest->nFlags = source->nFlags; + dest->nTimeStamp = source->nTimeStamp; + + if(start_code == H263_start_code) + { + memcpy (pdest,start_code,2); + pdest[2] = last_byte_h263; + dest->nFilledLen += 3; + pdest += 3; + } + else + { + memcpy (pdest,start_code,4); + if (start_code == VC1_AP_start_code + || start_code == MPEG4_start_code + || start_code == MPEG2_start_code) + { + pdest[3] = last_byte; + update_skip_frame(); + } + dest->nFilledLen += 4; + pdest += 4; + } + parse_state = A0; + } + + /*Entry State Machine*/ + while ( source->nFilledLen > 0 && parse_state != A0 + && parse_state != A4 && parse_state != A5 && dest_len > 0 + ) + { + //printf ("\n In the Entry Loop"); + switch (parse_state) + { + case A3: + parse_additional_start_code(psource,&parsed_length); + if (parse_state == A4) { + source->nFilledLen--; + source->nOffset++; + psource++; + break; + } + /*If fourth Byte is matching then start code is found*/ + if ((*psource & mask_code [3]) == start_code [3]) + { + parse_state = A4; + last_byte = *psource; + source->nFilledLen--; + source->nOffset++; + psource++; + } + else if ((start_code [1] == start_code [0]) && (start_code [2] == start_code [1])) + { + parse_state = A2; + memcpy (pdest,start_code,1); + pdest++; + dest->nFilledLen++; + dest_len--; + } + else if (start_code [2] == start_code [0]) + { + parse_state = A1; + memcpy (pdest,start_code,2); + pdest += 2; + dest->nFilledLen += 2; + dest_len -= 2; + } + else + { + parse_state = A0; + memcpy (pdest,start_code,3); + pdest += 3; + dest->nFilledLen +=3; + dest_len -= 3; + } + break; + + case A2: + is_byte_match = ((*psource & mask_code [2]) == start_code [2]); + match_found = FALSE; + + if (start_code == H263_start_code) + { + if (is_byte_match) + { + last_byte_h263 = *psource; + parse_state = A5; + match_found = TRUE; + } + } + else if (start_code == H264_start_code && + (*psource & mask_code [3]) == start_code [3]) + { + parse_state = A5; + match_found = TRUE; + } + else + { + if (is_byte_match) + { + parse_state = A3; + match_found = TRUE; + } + } + + if (match_found) + { + source->nFilledLen--; + source->nOffset++; + psource++; + } + else if (start_code [1] == start_code [0]) + { + parse_state = A1; + memcpy (pdest,start_code,1); + dest->nFilledLen +=1; + dest_len--; + pdest++; + } + else + { + parse_state = A0; + memcpy (pdest,start_code,2); + dest->nFilledLen +=2; + dest_len -= 2; + pdest += 2; + } + + break; + + case A1: + if ((*psource & mask_code [1]) == start_code [1]) + { + parse_state = A2; + source->nFilledLen--; + source->nOffset++; + psource++; + } + else + { + memcpy (pdest,start_code,1); + dest->nFilledLen +=1; + pdest++; + dest_len--; + parse_state = A0; + } + break; + case A4: + case A0: + break; + } + dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset); + } + + if (parse_state == A4 || parse_state == A5) + { + *partialframe = 0; + check_skip_frame_boundary(partialframe); + DEBUG_PRINT_LOW("\n FrameParser: Parsed Len = %d", dest->nFilledLen); + return 1; + } + + /*Partial Frame is true*/ + *partialframe = 1; + + /*Calculate how many bytes are left in source and destination*/ + dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset); + psource = source->pBuffer + source->nOffset; + pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset); + source_len = source->nFilledLen; + + temp_len = (source_len < dest_len)?source_len:dest_len; + + /*Check if entry state machine consumed source or destination*/ + if (temp_len == 0) + { + return 1; + } + + /*Parsing State Machine*/ + while (parsed_length < temp_len) + { + switch (parse_state) + { + case A0: + if ((psource [parsed_length] & mask_code [0]) == start_code[0]) + { + parse_state = A1; + } + parsed_length++; + break; + case A1: + if ((psource [parsed_length] & mask_code [1]) == start_code [1]) + { + parsed_length++; + parse_state = A2; + } + else + { + parse_state = A0; + } + break; + case A2: + is_byte_match = ((psource[parsed_length] & mask_code [2]) == start_code [2]); + match_found = FALSE; + + if (start_code == H263_start_code) + { + if (is_byte_match) + { + last_byte_h263 = psource[parsed_length]; + parse_state = A5; + match_found = TRUE; + } + } + else if (start_code == H264_start_code && + (psource[parsed_length] & mask_code [3]) == start_code [3]) + { + parse_state = A5; + match_found = TRUE; + } + else + { + if(is_byte_match) + { + parse_state = A3; + match_found = TRUE; + } + } + + if (match_found) + { + parsed_length++; + } + else if (start_code [1] == start_code [0]) + { + parse_state = A1; + } + else + { + parse_state = A0; + } + + break; + case A3: + parse_additional_start_code(psource,&parsed_length); + if (parse_state == A4) break; + + if ((psource [parsed_length] & mask_code [3]) == start_code [3]) + { + last_byte = psource [parsed_length]; + parsed_length++; + parse_state = A4; + } + else if ((start_code [1] == start_code [0]) && (start_code [2] == start_code [1])) + { + parse_state = A2; + } + else if (start_code [2] == start_code [0]) + { + parse_state = A1; + } + else + { + parse_state = A0; + } + break; + } + + /*Found the code break*/ + if (parse_state == A4 || parse_state == A5) + { + break; + } + } + + /*Exit State Machine*/ + psource = source->pBuffer + source->nOffset; + switch (parse_state) + { + case A5: + *partialframe = 0; + check_skip_frame_boundary(partialframe); + if (parsed_length > 3) + { + memcpy (pdest,psource,(parsed_length-3)); + dest->nFilledLen += (parsed_length-3); + } + break; + case A4: + *partialframe = 0; + check_skip_frame_boundary(partialframe); + if (parsed_length > 4) + { + memcpy (pdest,psource,(parsed_length-4)); + dest->nFilledLen += (parsed_length-4); + } + break; + case A3: + if (parsed_length > 3) + { + memcpy (pdest,psource,(parsed_length-3)); + dest->nFilledLen += (parsed_length-3); + } + break; + case A2: + if (parsed_length > 2) + { + memcpy (pdest,psource,(parsed_length-2)); + dest->nFilledLen += (parsed_length-2); + } + break; + case A1: + if (parsed_length > 1) + { + memcpy (pdest,psource,(parsed_length-1)); + dest->nFilledLen += (parsed_length-1); + } + break; + case A0: + memcpy (pdest,psource,(parsed_length)); + dest->nFilledLen += (parsed_length); + break; + } + + if (source->nFilledLen < parsed_length) + { + printf ("\n FATAL Error"); + return -1; + } + source->nFilledLen -= parsed_length; + source->nOffset += parsed_length; + + return 1; +} + + +int frame_parse::parse_h264_nallength (OMX_BUFFERHEADERTYPE *source, + OMX_BUFFERHEADERTYPE *dest , + OMX_U32 *partialframe) +{ + OMX_U8 *pdest = NULL,*psource = NULL; + OMX_U32 dest_len =0, source_len = 0, temp_len = 0,parsed_length = 0; + + if (source == NULL || dest == NULL || partialframe == NULL) + { + return -1; + } + + /*Calculate the length's*/ + dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset); + source_len = source->nFilledLen; + + if (dest_len < 4 || source_len == 0 || nal_length == 0) + { + DEBUG_PRINT_LOW("\n FrameParser: NAL Parsing Error! dest_len %d " + "source_len %d nal_length %d", dest_len, source_len, nal_length); + return -1; + } + *partialframe = 1; + temp_len = (source_len < dest_len)?source_len:dest_len; + psource = source->pBuffer + source->nOffset; + pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset); + + /* Find the Bytes to Accumalte*/ + if (state_nal == NAL_LENGTH_ACC) + { + while (parsed_length < temp_len ) + { + bytes_tobeparsed |= (((OMX_U32)(*psource))) << (((nal_length-accum_length-1) << 3)); + + /*COPY THE DATA FOR C-SIM TO BE REOMVED ON TARGET*/ + //*pdest = *psource; + accum_length++; + source->nFilledLen--; + source->nOffset++; + psource++; + //dest->nFilledLen++; + //pdest++; + parsed_length++; + + if (accum_length == nal_length) + { + accum_length = 0; + state_nal = NAL_PARSING; + memcpy (pdest,H264_start_code,4); + dest->nFilledLen += 4; + break; + } + } + } + + dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset); + source_len = source->nFilledLen; + temp_len = (source_len < dest_len)?source_len:dest_len; + + psource = source->pBuffer + source->nOffset; + pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset); + + dest->nTimeStamp = source->nTimeStamp; + dest->nFlags = source->nFlags; + + /*Already in Parsing state go ahead and copy*/ + if(state_nal == NAL_PARSING && temp_len > 0) + { + if (temp_len < bytes_tobeparsed) + { + memcpy (pdest,psource,temp_len); + dest->nFilledLen += temp_len; + source->nOffset += temp_len; + source->nFilledLen -= temp_len; + bytes_tobeparsed -= temp_len; + } + else + { + memcpy (pdest,psource,bytes_tobeparsed); + temp_len -= bytes_tobeparsed; + dest->nFilledLen += bytes_tobeparsed; + source->nOffset += bytes_tobeparsed; + source->nFilledLen -= bytes_tobeparsed; + bytes_tobeparsed = 0; + } + } + + if (bytes_tobeparsed == 0 && state_nal == NAL_PARSING) + { + *partialframe = 0; + state_nal = NAL_LENGTH_ACC; + } + + return 1; +} + +void frame_parse::flush () +{ + parse_state = A0; + state_nal = NAL_LENGTH_ACC; + accum_length = 0; + bytes_tobeparsed = 0; + header_found = false; + skip_frame_boundary = false; +} + +void frame_parse::parse_additional_start_code(OMX_U8 *psource, + OMX_U32 *parsed_length) +{ + + if (((start_code == MPEG4_start_code) || + (start_code == MPEG2_start_code)) && + psource && + parsed_length) + { + OMX_U32 index = *parsed_length; + if ((start_code == MPEG4_start_code && + (psource [index] & 0xF0) == 0x20) || + (start_code == MPEG2_start_code && + psource [index] == 0xB3)) + { + if (header_found) + { + last_byte = psource [index]; + index++; + parse_state = A4; + } else + header_found = true; + } + *parsed_length = index; + } +} + +void frame_parse::check_skip_frame_boundary(OMX_U32 *partialframe) +{ + if ((start_code == MPEG4_start_code || + start_code == MPEG2_start_code) && + partialframe) { + + *partialframe = 1; + if (!skip_frame_boundary) + *partialframe = 0; + skip_frame_boundary = false; + } +} + +void frame_parse::update_skip_frame() +{ + if (((start_code == MPEG4_start_code) && + ((last_byte & 0xF0) == 0x20)) || + ((start_code == MPEG2_start_code) && + (last_byte == 0xB3))) { + + skip_frame_boundary = true; + } +} diff --git a/mm-video/vidc/vdec/src/h264_utils.cpp b/mm-video/vidc/vdec/src/h264_utils.cpp new file mode 100755 index 0000000..554aa0b --- /dev/null +++ b/mm-video/vidc/vdec/src/h264_utils.cpp @@ -0,0 +1,1692 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*======================================================================== + + O p e n M M + V i d e o U t i l i t i e s + +*//** @file VideoUtils.cpp + This module contains utilities and helper routines. + +@par EXTERNALIZED FUNCTIONS + +@par INITIALIZATION AND SEQUENCING REQUIREMENTS + (none) + +*//*====================================================================== */ + +/* ======================================================================= + + INCLUDE FILES FOR MODULE + +========================================================================== */ +#include "h264_utils.h" +#include "omx_vdec.h" +#include +#include +#include +#include +#ifdef _ANDROID_ +#include +#endif + +/* ======================================================================= + + DEFINITIONS AND DECLARATIONS FOR MODULE + +This section contains definitions for constants, macros, types, variables +and other items needed by this module. + +========================================================================== */ + +#define SIZE_NAL_FIELD_MAX 4 +#define BASELINE_PROFILE 66 +#define MAIN_PROFILE 77 +#define HIGH_PROFILE 100 + +#define MAX_SUPPORTED_LEVEL 32 + +RbspParser::RbspParser (const uint8 *_begin, const uint8 *_end) +: begin (_begin), end(_end), pos (- 1), bit (0), +cursor (0xFFFFFF), advanceNeeded (true) +{ +} + +// Destructor +/*lint -e{1540} Pointer member neither freed nor zeroed by destructor + * No problem + */ +RbspParser::~RbspParser () {} + +// Return next RBSP byte as a word +uint32 RbspParser::next () +{ + if (advanceNeeded) advance (); + //return static_cast (*pos); + return static_cast (begin[pos]); +} + +// Advance RBSP decoder to next byte +void RbspParser::advance () +{ + ++pos; + //if (pos >= stop) + if (begin + pos == end) + { + /*lint -e{730} Boolean argument to function + * I don't see a problem here + */ + //throw false; + ALOGV("H264Parser-->NEED TO THROW THE EXCEPTION...\n"); + } + cursor <<= 8; + //cursor |= static_cast (*pos); + cursor |= static_cast (begin[pos]); + if ((cursor & 0xFFFFFF) == 0x000003) + { + advance (); + } + advanceNeeded = false; +} + +// Decode unsigned integer +uint32 RbspParser::u (uint32 n) +{ + uint32 i, s, x = 0; + for (i = 0; i < n; i += s) + { + s = static_castSTD_MIN(static_cast(8 - bit), + static_cast(n - i)); + x <<= s; + + x |= ((next () >> ((8 - static_cast(bit)) - s)) & + ((1 << s) - 1)); + + bit = (bit + s) % 8; + if (!bit) + { + advanceNeeded = true; + } + } + return x; +} + +// Decode unsigned integer Exp-Golomb-coded syntax element +uint32 RbspParser::ue () +{ + int leadingZeroBits = -1; + for (uint32 b = 0; !b; ++leadingZeroBits) + { + b = u (1); + } + return ((1 << leadingZeroBits) - 1) + + u (static_cast(leadingZeroBits)); +} + +// Decode signed integer Exp-Golomb-coded syntax element +int32 RbspParser::se () +{ + const uint32 x = ue (); + if (!x) return 0; + else if (x & 1) return static_cast ((x >> 1) + 1); + else return - static_cast (x >> 1); +} + +void H264_Utils::allocate_rbsp_buffer(uint32 inputBufferSize) +{ + m_rbspBytes = (byte *) calloc(1,inputBufferSize); + m_prv_nalu.nal_ref_idc = 0; + m_prv_nalu.nalu_type = NALU_TYPE_UNSPECIFIED; +} + +H264_Utils::H264_Utils(): m_height(0), + m_width(0), + m_rbspBytes(NULL), + m_au_data (false) +{ + initialize_frame_checking_environment(); +} + +H264_Utils::~H264_Utils() +{ +/* if(m_pbits) + { + delete(m_pbits); + m_pbits = NULL; + } +*/ + if (m_rbspBytes) + { + free(m_rbspBytes); + m_rbspBytes = NULL; + } +} + +/***********************************************************************/ +/* +FUNCTION: + H264_Utils::initialize_frame_checking_environment + +DESCRIPTION: + Extract RBSP data from a NAL + +INPUT/OUTPUT PARAMETERS: + None + +RETURN VALUE: + boolean + +SIDE EFFECTS: + None. +*/ +/***********************************************************************/ +void H264_Utils::initialize_frame_checking_environment() +{ + m_forceToStichNextNAL = false; + m_au_data = false; + m_prv_nalu.nal_ref_idc = 0; + m_prv_nalu.nalu_type = NALU_TYPE_UNSPECIFIED; +} + +/***********************************************************************/ +/* +FUNCTION: + H264_Utils::extract_rbsp + +DESCRIPTION: + Extract RBSP data from a NAL + +INPUT/OUTPUT PARAMETERS: + + buffer : buffer containing start code or nal length + NAL units + buffer_length : the length of the NAL buffer + start_code : If true, start code is detected, + otherwise size nal length is detected + size_of_nal_length_field: size of nal length field + + + rbsp_bistream : extracted RBSP bistream + rbsp_length : the length of the RBSP bitstream + nal_unit : decoded NAL header information + +RETURN VALUE: + boolean + +SIDE EFFECTS: + None. +*/ +/***********************************************************************/ + +boolean H264_Utils::extract_rbsp(OMX_IN OMX_U8 *buffer, + OMX_IN OMX_U32 buffer_length, + OMX_IN OMX_U32 size_of_nal_length_field, + OMX_OUT OMX_U8 *rbsp_bistream, + OMX_OUT OMX_U32 *rbsp_length, + OMX_OUT NALU *nal_unit) +{ + byte coef1, coef2, coef3; + uint32 pos = 0; + uint32 nal_len = buffer_length; + uint32 sizeofNalLengthField = 0; + uint32 zero_count; + boolean eRet = true; + boolean start_code = (size_of_nal_length_field==0)?true:false; + + if(start_code) { + // Search start_code_prefix_one_3bytes (0x000001) + coef2 = buffer[pos++]; + coef3 = buffer[pos++]; + do { + if(pos >= buffer_length) + { + ALOGE("ERROR: In %s() - line %d", __func__, __LINE__); + return false; + } + + coef1 = coef2; + coef2 = coef3; + coef3 = buffer[pos++]; + } while(coef1 || coef2 || coef3 != 1); + } + else if (size_of_nal_length_field) + { + /* This is the case to play multiple NAL units inside each access unit*/ + /* Extract the NAL length depending on sizeOfNALength field */ + sizeofNalLengthField = size_of_nal_length_field; + nal_len = 0; + while(size_of_nal_length_field--) + { + nal_len |= buffer[pos++]<<(size_of_nal_length_field<<3); + } + if (nal_len >= buffer_length) + { + ALOGE("ERROR: In %s() - line %d", __func__, __LINE__); + return false; + } + } + + if (nal_len > buffer_length) + { + ALOGE("ERROR: In %s() - line %d", __func__, __LINE__); + return false; + } + if(pos + 1 > (nal_len + sizeofNalLengthField)) + { + ALOGE("ERROR: In %s() - line %d", __func__, __LINE__); + return false; + } + if (nal_unit->forbidden_zero_bit = (buffer[pos] & 0x80)) + { + ALOGE("ERROR: In %s() - line %d", __func__, __LINE__); + } + nal_unit->nal_ref_idc = (buffer[pos] & 0x60) >> 5; + nal_unit->nalu_type = buffer[pos++] & 0x1f; + ALOGV("\n@#@# Pos = %x NalType = %x buflen = %d", + pos-1, nal_unit->nalu_type, buffer_length); + *rbsp_length = 0; + + + if( nal_unit->nalu_type == NALU_TYPE_EOSEQ || + nal_unit->nalu_type == NALU_TYPE_EOSTREAM) + return (nal_len + sizeofNalLengthField); + + zero_count = 0; + while (pos < (nal_len+sizeofNalLengthField)) //similar to for in p-42 + { + if( zero_count == 2 ) { + if( buffer[pos] == 0x03 ) { + pos ++; + zero_count = 0; + continue; + } + if( buffer[pos] <= 0x01 ) { + if( start_code ) { + *rbsp_length -= 2; + pos -= 2; + return pos; + } + } + zero_count = 0; + } + zero_count ++; + if( buffer[pos] != 0 ) + zero_count = 0; + + rbsp_bistream[(*rbsp_length)++] = buffer[pos++]; + } + + return eRet; +} + +/*=========================================================================== +FUNCTION: + H264_Utils::iSNewFrame + +DESCRIPTION: + Returns true if NAL parsing successfull otherwise false. + +INPUT/OUTPUT PARAMETERS: + + buffer : buffer containing start code or nal length + NAL units + buffer_length : the length of the NAL buffer + start_code : If true, start code is detected, + otherwise size nal length is detected + size_of_nal_length_field: size of nal length field + + isNewFrame: true if the NAL belongs to a differenet frame + false if the NAL belongs to a current frame + +RETURN VALUE: + boolean true, if nal parsing is successful + false, if the nal parsing has errors + +SIDE EFFECTS: + None. +===========================================================================*/ +bool H264_Utils::isNewFrame(OMX_BUFFERHEADERTYPE *p_buf_hdr, + OMX_IN OMX_U32 size_of_nal_length_field, + OMX_OUT OMX_BOOL &isNewFrame) +{ + NALU nal_unit; + uint16 first_mb_in_slice = 0; + uint32 numBytesInRBSP = 0; + OMX_IN OMX_U8 *buffer = p_buf_hdr->pBuffer; + OMX_IN OMX_U32 buffer_length = p_buf_hdr->nFilledLen; + bool eRet = true; + + ALOGV("isNewFrame: buffer %p buffer_length %d " + "size_of_nal_length_field %d\n", buffer, buffer_length, + size_of_nal_length_field); + + if ( false == extract_rbsp(buffer, buffer_length, size_of_nal_length_field, + m_rbspBytes, &numBytesInRBSP, &nal_unit) ) + { + ALOGE("ERROR: In %s() - extract_rbsp() failed", __func__); + isNewFrame = OMX_FALSE; + eRet = false; + } + else + { + nalu_type = nal_unit.nalu_type; + switch (nal_unit.nalu_type) + { + case NALU_TYPE_IDR: + case NALU_TYPE_NON_IDR: + { + ALOGV("\n AU Boundary with NAL type %d ",nal_unit.nalu_type); + if (m_forceToStichNextNAL) + { + isNewFrame = OMX_FALSE; + } + else + { + RbspParser rbsp_parser(m_rbspBytes, (m_rbspBytes+numBytesInRBSP)); + first_mb_in_slice = rbsp_parser.ue(); + + if((!first_mb_in_slice) || /*(slice.prv_frame_num != slice.frame_num ) ||*/ + ( (m_prv_nalu.nal_ref_idc != nal_unit.nal_ref_idc) && ( nal_unit.nal_ref_idc * m_prv_nalu.nal_ref_idc == 0 ) ) || + /*( ((m_prv_nalu.nalu_type == NALU_TYPE_IDR) && (nal_unit.nalu_type == NALU_TYPE_IDR)) && (slice.idr_pic_id != slice.prv_idr_pic_id) ) || */ + ( (m_prv_nalu.nalu_type != nal_unit.nalu_type ) && ((m_prv_nalu.nalu_type == NALU_TYPE_IDR) || (nal_unit.nalu_type == NALU_TYPE_IDR)) ) ) + { + //ALOGV("Found a New Frame due to NALU_TYPE_IDR/NALU_TYPE_NON_IDR"); + isNewFrame = OMX_TRUE; + } + else + { + isNewFrame = OMX_FALSE; + } + } + m_au_data = true; + m_forceToStichNextNAL = false; + break; + } + case NALU_TYPE_SPS: + case NALU_TYPE_PPS: + case NALU_TYPE_SEI: + { + ALOGV("\n Non-AU boundary with NAL type %d", nal_unit.nalu_type); + if(m_au_data) + { + isNewFrame = OMX_TRUE; + m_au_data = false; + } + else + { + isNewFrame = OMX_FALSE; + } + + m_forceToStichNextNAL = true; + break; + } + case NALU_TYPE_ACCESS_DELIM: + case NALU_TYPE_UNSPECIFIED: + case NALU_TYPE_EOSEQ: + case NALU_TYPE_EOSTREAM: + default: + { + isNewFrame = OMX_FALSE; + // Do not update m_forceToStichNextNAL + break; + } + } // end of switch + } // end of if + m_prv_nalu = nal_unit; + ALOGV("get_h264_nal_type - newFrame value %d\n",isNewFrame); + return eRet; +} + +void perf_metrics::start() +{ + if (!active) + { + start_time = get_act_time(); + active = true; + } +} + +void perf_metrics::stop() +{ + OMX_U64 stop_time = get_act_time(); + if (active) + { + proc_time += (stop_time - start_time); + active = false; + } +} + +void perf_metrics::end(OMX_U32 units_cntr) +{ + stop(); + ALOGV("--> Processing time : [%.2f] Sec", (float)proc_time / 1e6); + if (units_cntr) + { + ALOGV("--> Avrg proc time : [%.2f] mSec", proc_time / (float)(units_cntr * 1e3)); + } +} + +void perf_metrics::reset() +{ + start_time = 0; + proc_time = 0; + active = false; +} + +OMX_U64 perf_metrics::get_act_time() +{ + struct timeval act_time = {0, 0}; + gettimeofday(&act_time, NULL); + return (act_time.tv_usec + act_time.tv_sec * 1e6); +} + +OMX_U64 perf_metrics::processing_time_us() +{ + return proc_time; +} + +h264_stream_parser::h264_stream_parser() +{ + reset(); +#ifdef PANSCAN_HDLR + panscan_hdl = new panscan_handler(); + if (!panscan_hdl) + { + ALOGE("ERROR: Panscan hdl was not allocated!"); + } + else if (!panscan_hdl->initialize(10)) + { + ALOGE("ERROR: Allocating memory for panscan!"); + delete panscan_hdl; + panscan_hdl = NULL; + } +#else + memset(&panscan_param, 0, sizeof(panscan_param)); + panscan_param.rect_id = NO_PAN_SCAN_BIT; +#endif +} + +h264_stream_parser::~h264_stream_parser() +{ +#ifdef PANSCAN_HDLR + if (panscan_hdl) + { + delete panscan_hdl; + panscan_hdl = NULL; + } +#endif +} + +void h264_stream_parser::reset() +{ + curr_32_bit = 0; + bits_read = 0; + zero_cntr = 0; + emulation_code_skip_cntr = 0; + emulation_sc_enabled = true; + bitstream = NULL; + bitstream_bytes = 0; + memset(&vui_param, 0, sizeof(vui_param)); + vui_param.fixed_fps_prev_ts = LLONG_MAX; + memset(&sei_buf_period, 0, sizeof(sei_buf_period)); + memset(&sei_pic_timing, 0, sizeof(sei_pic_timing)); + memset(&frame_packing_arrangement,0,sizeof(frame_packing_arrangement)); + frame_packing_arrangement.cancel_flag = 1; + mbaff_flag = 0; +} + +void h264_stream_parser::init_bitstream(OMX_U8* data, OMX_U32 size) +{ + bitstream = data; + bitstream_bytes = size; + curr_32_bit = 0; + bits_read = 0; + zero_cntr = 0; + emulation_code_skip_cntr = 0; +} + +void h264_stream_parser::parse_vui(bool vui_in_extradata) +{ + OMX_U32 value = 0; + ALOGV("parse_vui: IN"); + if (vui_in_extradata) + while (!extract_bits(1) && more_bits()); // Discard VUI enable flag + if (!more_bits()) + return; + + vui_param.aspect_ratio_info_present_flag = extract_bits(1); //aspect_ratio_info_present_flag + if (vui_param.aspect_ratio_info_present_flag) + { + ALOGV("Aspect Ratio Info present!"); + aspect_ratio_info(); + } + + if (extract_bits(1)) //overscan_info_present_flag + extract_bits(1); //overscan_appropriate_flag + if (extract_bits(1)) //video_signal_type_present_flag + { + extract_bits(3); //video_format + extract_bits(1); //video_full_range_flag + if (extract_bits(1)) //colour_description_present_flag + { + extract_bits(8); //colour_primaries + extract_bits(8); //transfer_characteristics + extract_bits(8); //matrix_coefficients + } + } + if (extract_bits(1)) //chroma_location_info_present_flag + { + uev(); //chroma_sample_loc_type_top_field + uev(); //chroma_sample_loc_type_bottom_field + } + vui_param.timing_info_present_flag = extract_bits(1); + if (vui_param.timing_info_present_flag) + { + vui_param.num_units_in_tick = extract_bits(32); + vui_param.time_scale = extract_bits(32); + vui_param.fixed_frame_rate_flag = extract_bits(1); + ALOGV("Timing info present in VUI!"); + ALOGV(" num units in tick : %u", vui_param.num_units_in_tick); + ALOGV(" time scale : %u", vui_param.time_scale); + ALOGV(" fixed frame rate : %u", vui_param.fixed_frame_rate_flag); + } + vui_param.nal_hrd_parameters_present_flag = extract_bits(1); + if (vui_param.nal_hrd_parameters_present_flag) + { + ALOGV("nal hrd params present!"); + hrd_parameters(&vui_param.nal_hrd_parameters); + } + vui_param.vcl_hrd_parameters_present_flag = extract_bits(1); + if (vui_param.vcl_hrd_parameters_present_flag) + { + ALOGV("vcl hrd params present!"); + hrd_parameters(&vui_param.vcl_hrd_parameters); + } + if (vui_param.nal_hrd_parameters_present_flag || + vui_param.vcl_hrd_parameters_present_flag) + vui_param.low_delay_hrd_flag = extract_bits(1); + vui_param.pic_struct_present_flag = extract_bits(1); + ALOGV("pic_struct_present_flag : %u", vui_param.pic_struct_present_flag); + if (extract_bits(1)) //bitstream_restriction_flag + { + extract_bits(1); //motion_vectors_over_pic_boundaries_flag + uev(); //max_bytes_per_pic_denom + uev(); //max_bits_per_mb_denom + uev(); //log2_max_mv_length_vertical + uev(); //log2_max_mv_length_horizontal + uev(); //num_reorder_frames + uev(); //max_dec_frame_buffering + } + ALOGV("parse_vui: OUT"); +} + +void h264_stream_parser::aspect_ratio_info() +{ + ALOGV("aspect_ratio_info: IN"); + OMX_U32 aspect_ratio_idc = 0; + OMX_U32 aspect_ratio_x = 0; + OMX_U32 aspect_ratio_y = 0; + aspect_ratio_idc = extract_bits(8); //aspect_ratio_idc + switch (aspect_ratio_idc) + { + case 1: + aspect_ratio_x = 1; + aspect_ratio_y = 1; + break; + case 2: + aspect_ratio_x = 12; + aspect_ratio_y = 11; + break; + case 3: + aspect_ratio_x = 10; + aspect_ratio_y = 11; + break; + case 4: + aspect_ratio_x = 16; + aspect_ratio_y = 11; + break; + case 5: + aspect_ratio_x = 40; + aspect_ratio_y = 33; + break; + case 6: + aspect_ratio_x = 24; + aspect_ratio_y = 11; + break; + case 7: + aspect_ratio_x = 20; + aspect_ratio_y = 11; + break; + case 8: + aspect_ratio_x = 32; + aspect_ratio_y = 11; + break; + case 9: + aspect_ratio_x = 80; + aspect_ratio_y = 33; + break; + case 10: + aspect_ratio_x = 18; + aspect_ratio_y = 11; + break; + case 11: + aspect_ratio_x = 15; + aspect_ratio_y = 11; + break; + case 12: + aspect_ratio_x = 64; + aspect_ratio_y = 33; + break; + case 13: + aspect_ratio_x = 160; + aspect_ratio_y = 99; + break; + case 14: + aspect_ratio_x = 4; + aspect_ratio_y = 3; + break; + case 15: + aspect_ratio_x = 3; + aspect_ratio_y = 2; + break; + case 16: + aspect_ratio_x = 2; + aspect_ratio_y = 1; + break; + case 255: + aspect_ratio_x = extract_bits(16); //sar_width + aspect_ratio_y = extract_bits(16); //sar_height + break; + default: + ALOGV("-->aspect_ratio_idc: Reserved Value "); + break; + } + ALOGV("-->aspect_ratio_idc : %u", aspect_ratio_idc); + ALOGV("-->aspect_ratio_x : %u", aspect_ratio_x); + ALOGV("-->aspect_ratio_y : %u", aspect_ratio_y); + vui_param.aspect_ratio_info.aspect_ratio_idc = aspect_ratio_idc; + vui_param.aspect_ratio_info.aspect_ratio_x = aspect_ratio_x; + vui_param.aspect_ratio_info.aspect_ratio_y = aspect_ratio_y; + ALOGV("aspect_ratio_info: OUT"); +} + +void h264_stream_parser::hrd_parameters(h264_hrd_param *hrd_param) +{ + int idx; + ALOGV("hrd_parameters: IN"); + hrd_param->cpb_cnt = uev() + 1; + hrd_param->bit_rate_scale = extract_bits(4); + hrd_param->cpb_size_scale = extract_bits(4); + ALOGV("-->cpb_cnt : %u", hrd_param->cpb_cnt); + ALOGV("-->bit_rate_scale : %u", hrd_param->bit_rate_scale); + ALOGV("-->cpb_size_scale : %u", hrd_param->cpb_size_scale); + if (hrd_param->cpb_cnt > MAX_CPB_COUNT) + { + ALOGV("ERROR: Invalid hrd_param->cpb_cnt [%u]!", hrd_param->cpb_cnt); + return; + } + for (idx = 0; idx < hrd_param->cpb_cnt && more_bits(); idx++) + { + hrd_param->bit_rate_value[idx] = uev() + 1; + hrd_param->cpb_size_value[idx] = uev() + 1; + hrd_param->cbr_flag[idx] = extract_bits(1); + ALOGV("-->bit_rate_value [%d] : %u", idx, hrd_param->bit_rate_value[idx]); + ALOGV("-->cpb_size_value [%d] : %u", idx, hrd_param->cpb_size_value[idx]); + ALOGV("-->cbr_flag [%d] : %u", idx, hrd_param->cbr_flag[idx]); + } + hrd_param->initial_cpb_removal_delay_length = extract_bits(5) + 1; + hrd_param->cpb_removal_delay_length = extract_bits(5) + 1; + hrd_param->dpb_output_delay_length = extract_bits(5) + 1; + hrd_param->time_offset_length = extract_bits(5); + ALOGV("-->initial_cpb_removal_delay_length : %u", hrd_param->initial_cpb_removal_delay_length); + ALOGV("-->cpb_removal_delay_length : %u", hrd_param->cpb_removal_delay_length); + ALOGV("-->dpb_output_delay_length : %u", hrd_param->dpb_output_delay_length); + ALOGV("-->time_offset_length : %u", hrd_param->time_offset_length); + ALOGV("hrd_parameters: OUT"); +} + +void h264_stream_parser::parse_sei() +{ + OMX_U32 value = 0, processed_bytes = 0; + OMX_U8 *sei_msg_start = bitstream; + OMX_U32 sei_unit_size = bitstream_bytes; + ALOGV("@@parse_sei: IN sei_unit_size(%u)", sei_unit_size); + while ((processed_bytes + 2) < sei_unit_size && more_bits()) + { + init_bitstream(sei_msg_start + processed_bytes, sei_unit_size - processed_bytes); + ALOGV("-->NALU_TYPE_SEI"); + OMX_U32 payload_type = 0, payload_size = 0, aux = 0; + do { + value = extract_bits(8); + payload_type += value; + processed_bytes++; + } while (value == 0xFF); + ALOGV("-->payload_type : %u", payload_type); + do { + value = extract_bits(8); + payload_size += value; + processed_bytes++; + } while (value == 0xFF); + ALOGV("-->payload_size : %u", payload_size); + if (payload_size > 0) + { + switch (payload_type) + { + case BUFFERING_PERIOD: + sei_buffering_period(); + break; + case PIC_TIMING: + sei_picture_timing(); + break; + case PAN_SCAN_RECT: + sei_pan_scan(); + break; + case SEI_PAYLOAD_FRAME_PACKING_ARRANGEMENT: + parse_frame_pack(); + break; + default: + ALOGV("-->SEI payload type [%u] not implemented! size[%u]", payload_type, payload_size); + } + } + processed_bytes += (payload_size + emulation_code_skip_cntr); + ALOGV("-->SEI processed_bytes[%u]", processed_bytes); + } + ALOGV("@@parse_sei: OUT"); +} + +void h264_stream_parser::sei_buffering_period() +{ + int idx; + OMX_U32 value = 0; + h264_hrd_param *hrd_param = NULL; + ALOGV("@@sei_buffering_period: IN"); + value = uev(); // seq_parameter_set_id + ALOGV("-->seq_parameter_set_id : %u", value); + if (value > 31) + { + ALOGV("ERROR: Invalid seq_parameter_set_id [%u]!", value); + return; + } + sei_buf_period.is_valid = false; + if (vui_param.nal_hrd_parameters_present_flag) + { + hrd_param = &vui_param.nal_hrd_parameters; + if (hrd_param->cpb_cnt > MAX_CPB_COUNT) + { + ALOGV("ERROR: Invalid hrd_param->cpb_cnt [%u]!", hrd_param->cpb_cnt); + return; + } + for (idx = 0; idx < hrd_param->cpb_cnt ; idx++) + { + sei_buf_period.is_valid = true; + sei_buf_period.initial_cpb_removal_delay[idx] = extract_bits(hrd_param->initial_cpb_removal_delay_length); + sei_buf_period.initial_cpb_removal_delay_offset[idx] = extract_bits(hrd_param->initial_cpb_removal_delay_length); + ALOGV("-->initial_cpb_removal_delay : %u", sei_buf_period.initial_cpb_removal_delay[idx]); + ALOGV("-->initial_cpb_removal_delay_offset : %u", sei_buf_period.initial_cpb_removal_delay_offset[idx]); + } + } + if (vui_param.vcl_hrd_parameters_present_flag) + { + hrd_param = &vui_param.vcl_hrd_parameters; + if (hrd_param->cpb_cnt > MAX_CPB_COUNT) + { + ALOGV("ERROR: Invalid hrd_param->cpb_cnt [%u]!", hrd_param->cpb_cnt); + return; + } + for (idx = 0; idx < hrd_param->cpb_cnt ; idx++) + { + sei_buf_period.is_valid = true; + sei_buf_period.initial_cpb_removal_delay[idx] = extract_bits(hrd_param->initial_cpb_removal_delay_length); + sei_buf_period.initial_cpb_removal_delay_offset[idx] = extract_bits(hrd_param->initial_cpb_removal_delay_length); + ALOGV("-->initial_cpb_removal_delay : %u", sei_buf_period.initial_cpb_removal_delay[idx]); + ALOGV("-->initial_cpb_removal_delay_offset : %u", sei_buf_period.initial_cpb_removal_delay_offset[idx]); + } + } + sei_buf_period.au_cntr = 0; + ALOGV("@@sei_buffering_period: OUT"); +} + +void h264_stream_parser::sei_picture_timing() +{ + ALOGV("@@sei_picture_timing: IN"); + OMX_U32 time_offset_len = 0, cpb_removal_len = 24, dpb_output_len = 24; + OMX_U8 cbr_flag = 0; + sei_pic_timing.is_valid = true; + if (vui_param.nal_hrd_parameters_present_flag) + { + cpb_removal_len = vui_param.nal_hrd_parameters.cpb_removal_delay_length; + dpb_output_len = vui_param.nal_hrd_parameters.dpb_output_delay_length; + time_offset_len = vui_param.nal_hrd_parameters.time_offset_length; + cbr_flag = vui_param.nal_hrd_parameters.cbr_flag[0]; + } + else if (vui_param.vcl_hrd_parameters_present_flag) + { + cpb_removal_len = vui_param.vcl_hrd_parameters.cpb_removal_delay_length; + dpb_output_len = vui_param.vcl_hrd_parameters.dpb_output_delay_length; + time_offset_len = vui_param.vcl_hrd_parameters.time_offset_length; + cbr_flag = vui_param.vcl_hrd_parameters.cbr_flag[0]; + } + sei_pic_timing.cpb_removal_delay = extract_bits(cpb_removal_len); + sei_pic_timing.dpb_output_delay = extract_bits(dpb_output_len); + ALOGV("-->cpb_removal_len : %u", cpb_removal_len); + ALOGV("-->dpb_output_len : %u", dpb_output_len); + ALOGV("-->cpb_removal_delay : %u", sei_pic_timing.cpb_removal_delay); + ALOGV("-->dpb_output_delay : %u", sei_pic_timing.dpb_output_delay); + if (vui_param.pic_struct_present_flag) + { + sei_pic_timing.pic_struct = extract_bits(4); + sei_pic_timing.num_clock_ts = 0; + switch (sei_pic_timing.pic_struct) + { + case 0: case 1: case 2: sei_pic_timing.num_clock_ts = 1; break; + case 3: case 4: case 7: sei_pic_timing.num_clock_ts = 2; break; + case 5: case 6: case 8: sei_pic_timing.num_clock_ts = 3; break; + default: + ALOGE("sei_picture_timing: pic_struct invalid!"); + } + ALOGV("-->num_clock_ts : %u", sei_pic_timing.num_clock_ts); + for (int i = 0; i < sei_pic_timing.num_clock_ts && more_bits(); i++) + { + sei_pic_timing.clock_ts_flag = extract_bits(1); + if(sei_pic_timing.clock_ts_flag) + { + ALOGV("-->clock_timestamp present!"); + sei_pic_timing.ct_type = extract_bits(2); + sei_pic_timing.nuit_field_based_flag = extract_bits(1); + sei_pic_timing.counting_type = extract_bits(5); + sei_pic_timing.full_timestamp_flag = extract_bits(1); + sei_pic_timing.discontinuity_flag = extract_bits(1); + sei_pic_timing.cnt_dropped_flag = extract_bits(1); + sei_pic_timing.n_frames = extract_bits(8); + ALOGV("-->f_timestamp_flg : %u", sei_pic_timing.full_timestamp_flag); + ALOGV("-->n_frames : %u", sei_pic_timing.n_frames); + sei_pic_timing.seconds_value = 0; + sei_pic_timing.minutes_value = 0; + sei_pic_timing.hours_value = 0; + if (sei_pic_timing.full_timestamp_flag) + { + sei_pic_timing.seconds_value = extract_bits(6); + sei_pic_timing.minutes_value = extract_bits(6); + sei_pic_timing.hours_value = extract_bits(5); + } + else if (extract_bits(1)) + { + ALOGV("-->seconds_flag enabled!"); + sei_pic_timing.seconds_value = extract_bits(6); + if (extract_bits(1)) + { + ALOGV("-->minutes_flag enabled!"); + sei_pic_timing.minutes_value = extract_bits(6); + if (extract_bits(1)) + { + ALOGV("-->hours_flag enabled!"); + sei_pic_timing.hours_value = extract_bits(5); + } + } + } + sei_pic_timing.time_offset = 0; + if (time_offset_len > 0) + sei_pic_timing.time_offset = iv(time_offset_len); + ALOGV("-->seconds_value : %u", sei_pic_timing.seconds_value); + ALOGV("-->minutes_value : %u", sei_pic_timing.minutes_value); + ALOGV("-->hours_value : %u", sei_pic_timing.hours_value); + ALOGV("-->time_offset : %d", sei_pic_timing.time_offset); + } + } + } + ALOGV("@@sei_picture_timing: OUT"); +} + +void h264_stream_parser::sei_pan_scan() +{ +#ifdef _ANDROID_ + char property_value[PROPERTY_VALUE_MAX] = {0}; + OMX_S32 enable_panscan_log = 0; + property_get("vidc.dec.debug.panframedata", property_value, "0"); + enable_panscan_log = atoi(property_value); +#endif +#ifdef PANSCAN_HDLR + h264_pan_scan *pan_scan_param = panscan_hdl->get_free(); +#else + h264_pan_scan *pan_scan_param = &panscan_param; +#endif + + if (!pan_scan_param) + { + ALOGE("sei_pan_scan: ERROR: Invalid pointer!"); + return; + } + + pan_scan_param->rect_id = uev(); + if (pan_scan_param->rect_id > 0xFF) + { + ALOGE("sei_pan_scan: ERROR: Invalid rect_id[%u]!", pan_scan_param->rect_id); + pan_scan_param->rect_id = NO_PAN_SCAN_BIT; + return; + } + + pan_scan_param->rect_cancel_flag = extract_bits(1); + + if (pan_scan_param->rect_cancel_flag) + pan_scan_param->rect_id = NO_PAN_SCAN_BIT; + else + { + pan_scan_param->cnt = uev() + 1; + if (pan_scan_param->cnt > MAX_PAN_SCAN_RECT) + { + ALOGE("sei_pan_scan: ERROR: Invalid num of rect [%u]!", pan_scan_param->cnt); + pan_scan_param->rect_id = NO_PAN_SCAN_BIT; + return; + } + + for (int i = 0; i < pan_scan_param->cnt; i++) + { + pan_scan_param->rect_left_offset[i] = sev(); + pan_scan_param->rect_right_offset[i] = sev(); + pan_scan_param->rect_top_offset[i] = sev(); + pan_scan_param->rect_bottom_offset[i] = sev(); + + } + pan_scan_param->rect_repetition_period = uev(); +#ifdef PANSCAN_HDLR + if (pan_scan_param->rect_repetition_period > 1) + // Repetition period is decreased by 2 each time panscan data is used + pan_scan_param->rect_repetition_period *= 2; +#endif +#ifdef _ANDROID_ + if (enable_panscan_log) + { + print_pan_data(pan_scan_param); + } +#endif + } +} + +void h264_stream_parser::print_pan_data(h264_pan_scan *pan_scan_param) +{ + ALOGV("@@print_pan_data: IN"); + + ALOGV("-->rect_id : %u", pan_scan_param->rect_id); + ALOGV("-->rect_cancel_flag : %u", pan_scan_param->rect_cancel_flag); + + ALOGV("-->cnt : %u", pan_scan_param->cnt); + + for (int i = 0; i < pan_scan_param->cnt; i++) + { + ALOGV("-->rect_left_offset : %d", pan_scan_param->rect_left_offset[i]); + ALOGV("-->rect_right_offset : %d", pan_scan_param->rect_right_offset[i]); + ALOGV("-->rect_top_offset : %d", pan_scan_param->rect_top_offset[i]); + ALOGV("-->rect_bottom_offset : %d", pan_scan_param->rect_bottom_offset[i]); + } + ALOGV("-->repetition_period : %u", pan_scan_param->rect_repetition_period); + + ALOGV("@@print_pan_data: OUT"); +} + +void h264_stream_parser::parse_sps() +{ + OMX_U32 value = 0, scaling_matrix_limit; + ALOGV("@@parse_sps: IN"); + value = extract_bits(8); //profile_idc + extract_bits(8); //constraint flags and reserved bits + extract_bits(8); //level_idc + uev(); //sps id + if (value == 100 || value == 110 || value == 122 || value == 244 || + value == 44 || value == 83 || value == 86 || value == 118) + { + if (uev() == 3) //chroma_format_idc + { + extract_bits(1); //separate_colour_plane_flag + scaling_matrix_limit = 12; + } + else + scaling_matrix_limit = 12; + uev(); //bit_depth_luma_minus8 + uev(); //bit_depth_chroma_minus8 + extract_bits(1); //qpprime_y_zero_transform_bypass_flag + if (extract_bits(1)) //seq_scaling_matrix_present_flag + for (int i = 0; i < scaling_matrix_limit && more_bits(); i++) + { + if (extract_bits(1)) ////seq_scaling_list_present_flag[ i ] + if (i < 6) + scaling_list(16); + else + scaling_list(64); + } + } + uev(); //log2_max_frame_num_minus4 + value = uev(); //pic_order_cnt_type + if (value == 0) + uev(); //log2_max_pic_order_cnt_lsb_minus4 + else if (value == 1) + { + extract_bits(1); //delta_pic_order_always_zero_flag + sev(); //offset_for_non_ref_pic + sev(); //offset_for_top_to_bottom_field + value = uev(); // num_ref_frames_in_pic_order_cnt_cycle + for (int i = 0; i < value; i++) + sev(); //offset_for_ref_frame[ i ] + } + uev(); //max_num_ref_frames + extract_bits(1); //gaps_in_frame_num_value_allowed_flag + value = uev(); //pic_width_in_mbs_minus1 + value = uev(); //pic_height_in_map_units_minus1 + if (!extract_bits(1)) //frame_mbs_only_flag + mbaff_flag = extract_bits(1); //mb_adaptive_frame_field_flag + extract_bits(1); //direct_8x8_inference_flag + if (extract_bits(1)) //frame_cropping_flag + { + uev(); //frame_crop_left_offset + uev(); //frame_crop_right_offset + uev(); //frame_crop_top_offset + uev(); //frame_crop_bottom_offset + } + if (extract_bits(1)) //vui_parameters_present_flag + parse_vui(false); + ALOGV("@@parse_sps: OUT"); +} + +void h264_stream_parser::scaling_list(OMX_U32 size_of_scaling_list) +{ + OMX_S32 last_scale = 8, next_scale = 8, delta_scale; + for (int j = 0; j < size_of_scaling_list; j++) + { + if (next_scale != 0) + { + delta_scale = sev(); + next_scale = (last_scale + delta_scale + 256) % 256; + } + last_scale = (next_scale == 0)? last_scale : next_scale; + } +} + +OMX_U32 h264_stream_parser::extract_bits(OMX_U32 n) +{ + OMX_U32 value = 0; + if (n > 32) + { + ALOGE("ERROR: extract_bits limit to 32 bits!"); + return value; + } + value = curr_32_bit >> (32 - n); + if (bits_read < n) + { + n -= bits_read; + read_word(); + value |= (curr_32_bit >> (32 - n)); + if (bits_read < n) + { + ALOGV("ERROR: extract_bits underflow!"); + value >>= (n - bits_read); + n = bits_read; + } + } + bits_read -= n; + curr_32_bit <<= n; + return value; +} + +void h264_stream_parser::read_word() +{ + curr_32_bit = 0; + bits_read = 0; + while (bitstream_bytes && bits_read < 32) + { + if (*bitstream == EMULATION_PREVENTION_THREE_BYTE && + zero_cntr >= 2 && emulation_sc_enabled) + { + ALOGV("EMULATION_PREVENTION_THREE_BYTE: Skip 0x03 byte aligned!"); + emulation_code_skip_cntr++; + } + else + { + curr_32_bit <<= 8; + curr_32_bit |= *bitstream; + bits_read += 8; + } + if (*bitstream == 0) + zero_cntr++; + else + zero_cntr = 0; + bitstream++; + bitstream_bytes--; + } + curr_32_bit <<= (32 - bits_read); +} + +OMX_U32 h264_stream_parser::uev() +{ + OMX_U32 lead_zero_bits = 0, code_num = 0; + while(!extract_bits(1) && more_bits()) + lead_zero_bits++; + code_num = lead_zero_bits == 0 ? 0 : + (1 << lead_zero_bits) - 1 + extract_bits(lead_zero_bits); + return code_num; +} + +bool h264_stream_parser::more_bits() +{ + return (bitstream_bytes > 0 || bits_read > 0); +} + +OMX_S32 h264_stream_parser::sev() +{ + OMX_U32 code_num = uev(); + OMX_S32 ret; + ret = (code_num + 1) >> 1; + return ((code_num & 1) ? ret : -ret); +} + +OMX_S32 h264_stream_parser::iv(OMX_U32 n_bits) +{ + OMX_U32 code_num = extract_bits(n_bits); + OMX_S32 ret = (code_num >> (n_bits - 1))? (-1)*(~(code_num & ~(0x1 << (n_bits - 1))) + 1) : code_num; + return ret; +} + +OMX_U32 h264_stream_parser::get_nal_unit_type(OMX_U32 *nal_unit_type) +{ + OMX_U32 value = 0, consumed_bytes = 3; + *nal_unit_type = NALU_TYPE_UNSPECIFIED; + ALOGV("-->get_nal_unit_type: IN"); + value = extract_bits(24); + while (value != 0x00000001 && more_bits()) + { + value <<= 8; + value |= extract_bits(8); + consumed_bytes++; + } + if (value != 0x00000001) + { + ALOGE("ERROR in get_nal_unit_type: Start code not found!"); + } + else + { + if (extract_bits(1)) // forbidden_zero_bit + { + ALOGE("WARNING: forbidden_zero_bit should be zero!"); + } + value = extract_bits(2); + ALOGV("-->nal_ref_idc : %x", value); + *nal_unit_type = extract_bits(5); + ALOGV("-->nal_unit_type : %x", *nal_unit_type); + consumed_bytes++; + if (consumed_bytes > 5) + { + ALOGE("-->WARNING: Startcode was found after the first 4 bytes!"); + } + } + ALOGV("-->get_nal_unit_type: OUT"); + return consumed_bytes; +} + +OMX_S64 h264_stream_parser::calculate_buf_period_ts(OMX_S64 timestamp) +{ + OMX_S64 clock_ts = timestamp; + ALOGV("calculate_ts(): IN"); + if (sei_buf_period.au_cntr == 0) + clock_ts = sei_buf_period.reference_ts = timestamp; + else if (sei_pic_timing.is_valid && VALID_TS(sei_buf_period.reference_ts)) + { + clock_ts = sei_buf_period.reference_ts + sei_pic_timing.cpb_removal_delay * + 1e6 * vui_param.num_units_in_tick / vui_param.time_scale; + } + sei_buf_period.au_cntr++; + ALOGV("calculate_ts(): OUT"); + return clock_ts; +} + +OMX_S64 h264_stream_parser::calculate_fixed_fps_ts(OMX_S64 timestamp, OMX_U32 DeltaTfiDivisor) +{ + if (VALID_TS(timestamp)) + vui_param.fixed_fps_prev_ts = timestamp; + else if (VALID_TS(vui_param.fixed_fps_prev_ts)) + vui_param.fixed_fps_prev_ts += DeltaTfiDivisor * 1e6 * + vui_param.num_units_in_tick / vui_param.time_scale; + return vui_param.fixed_fps_prev_ts; +} + +void h264_stream_parser::parse_frame_pack() +{ +#ifdef _ANDROID_ + char property_value[PROPERTY_VALUE_MAX] = {0}; + OMX_S32 enable_framepack_log = 0; + + property_get("vidc.dec.debug.panframedata", property_value, "0"); + enable_framepack_log = atoi(property_value); +#endif + ALOGV("\n%s:%d parse_frame_pack", __func__, __LINE__); + + frame_packing_arrangement.id = uev(); + + frame_packing_arrangement.cancel_flag = extract_bits(1); + if(!frame_packing_arrangement.cancel_flag) { + frame_packing_arrangement.type = extract_bits(7); + frame_packing_arrangement.quincunx_sampling_flag = extract_bits(1); + frame_packing_arrangement.content_interpretation_type = extract_bits(6); + frame_packing_arrangement.spatial_flipping_flag = extract_bits(1); + frame_packing_arrangement.frame0_flipped_flag = extract_bits(1); + frame_packing_arrangement.field_views_flag = extract_bits(1); + frame_packing_arrangement.current_frame_is_frame0_flag = extract_bits(1); + frame_packing_arrangement.frame0_self_contained_flag = extract_bits(1); + frame_packing_arrangement.frame1_self_contained_flag = extract_bits(1); + + if(!frame_packing_arrangement.quincunx_sampling_flag && + frame_packing_arrangement.type != 5) { + frame_packing_arrangement.frame0_grid_position_x = extract_bits(4); + frame_packing_arrangement.frame0_grid_position_y = extract_bits(4); + frame_packing_arrangement.frame1_grid_position_x = extract_bits(4); + frame_packing_arrangement.frame1_grid_position_y = extract_bits(4); + } + frame_packing_arrangement.reserved_byte = extract_bits(8); + frame_packing_arrangement.repetition_period = uev(); + } + frame_packing_arrangement.extension_flag = extract_bits(1); + +#ifdef _ANDROID_ + if (enable_framepack_log) + { + print_frame_pack(); + } +#endif +} + +void h264_stream_parser::print_frame_pack() +{ + ALOGV("\n ## frame_packing_arrangement.id = %u", frame_packing_arrangement.id); + ALOGV("\n ## frame_packing_arrangement.cancel_flag = %u", + frame_packing_arrangement.cancel_flag); + if(!frame_packing_arrangement.cancel_flag) + { + ALOGV("\n ## frame_packing_arrangement.type = %u", + frame_packing_arrangement.type); + ALOGV("\n ## frame_packing_arrangement.quincunx_sampling_flag = %u", + frame_packing_arrangement.quincunx_sampling_flag); + ALOGV("\n ## frame_packing_arrangement.content_interpretation_type = %u", + frame_packing_arrangement.content_interpretation_type); + ALOGV("\n ## frame_packing_arrangement.spatial_flipping_flag = %u", + frame_packing_arrangement.spatial_flipping_flag); + ALOGV("\n ## frame_packing_arrangement.frame0_flipped_flag = %u", + frame_packing_arrangement.frame0_flipped_flag); + ALOGV("\n ## frame_packing_arrangement.field_views_flag = %u", + frame_packing_arrangement.field_views_flag); + ALOGV("\n ## frame_packing_arrangement.current_frame_is_frame0_flag = %u", + frame_packing_arrangement.current_frame_is_frame0_flag); + ALOGV("\n ## frame_packing_arrangement.frame0_self_contained_flag = %u", + frame_packing_arrangement.frame0_self_contained_flag); + ALOGV("\n ## frame_packing_arrangement.frame1_self_contained_flag = %u", + frame_packing_arrangement.frame1_self_contained_flag); + ALOGV("\n ## frame_packing_arrangement.reserved_byte = %u", + frame_packing_arrangement.reserved_byte); + ALOGV("\n ## frame_packing_arrangement.repetition_period = %u", + frame_packing_arrangement.repetition_period); + ALOGV("\n ## frame_packing_arrangement.extension_flag = %u", + frame_packing_arrangement.extension_flag); + } +} +/* API'S EXPOSED TO OMX COMPONENT */ + +void h264_stream_parser::get_frame_pack_data( + OMX_QCOM_FRAME_PACK_ARRANGEMENT *frame_pack) +{ + ALOGV("\n%s:%d get frame data", __func__, __LINE__); + memcpy(&frame_pack->id,&frame_packing_arrangement.id, + FRAME_PACK_SIZE*sizeof(OMX_U32)); + return; +} + + +bool h264_stream_parser::is_mbaff() +{ + ALOGV("\n%s:%d MBAFF flag=%d", __func__, __LINE__,mbaff_flag); + return mbaff_flag; +} + +void h264_stream_parser::get_frame_rate(OMX_U32 *frame_rate) +{ + if (vui_param.num_units_in_tick != 0) + *frame_rate = vui_param.time_scale / (2 * vui_param.num_units_in_tick); +} + +void h264_stream_parser::parse_nal(OMX_U8* data_ptr, OMX_U32 data_len, OMX_U32 nal_type, bool enable_emu_sc) +{ + OMX_U32 nal_unit_type = NALU_TYPE_UNSPECIFIED, cons_bytes = 0; + ALOGV("parse_nal(): IN nal_type(%lu)", nal_type); + if (!data_len) + return; + init_bitstream(data_ptr, data_len); + emulation_sc_enabled = enable_emu_sc; + if (nal_type != NALU_TYPE_VUI) + { + cons_bytes = get_nal_unit_type(&nal_unit_type); + if (nal_type != nal_unit_type && nal_type != NALU_TYPE_UNSPECIFIED) + { + ALOGV("Unexpected nal_type(%x) expected(%x)", nal_unit_type, nal_type); + return; + } + } + switch (nal_type) + { + case NALU_TYPE_SPS: + if (more_bits()) + parse_sps(); +#ifdef PANSCAN_HDLR + panscan_hdl->get_free(); +#endif + break; + case NALU_TYPE_SEI: + init_bitstream(data_ptr + cons_bytes, data_len - cons_bytes); + parse_sei(); + break; + case NALU_TYPE_VUI: + parse_vui(true); + break; + default: + ALOGV("nal_unit_type received : %lu", nal_type); + } + ALOGV("parse_nal(): OUT"); +} + +#ifdef PANSCAN_HDLR +void h264_stream_parser::update_panscan_data(OMX_S64 timestamp) +{ + panscan_hdl->update_last(timestamp); +} +#endif + +void h264_stream_parser::fill_aspect_ratio_info(OMX_QCOM_ASPECT_RATIO *dest_aspect_ratio) +{ + if(dest_aspect_ratio && vui_param.aspect_ratio_info_present_flag) + { + dest_aspect_ratio->aspectRatioX = vui_param.aspect_ratio_info.aspect_ratio_x; + dest_aspect_ratio->aspectRatioY = vui_param.aspect_ratio_info.aspect_ratio_y; + } +} + +void h264_stream_parser::fill_pan_scan_data(OMX_QCOM_PANSCAN *dest_pan_scan, OMX_S64 timestamp) +{ +#ifdef PANSCAN_HDLR + h264_pan_scan *pan_scan_param = panscan_hdl->get_populated(timestamp); +#else + h264_pan_scan *pan_scan_param = &panscan_param; +#endif + if (pan_scan_param) + if (!(pan_scan_param->rect_id & NO_PAN_SCAN_BIT)) + { + PRINT_PANSCAN_PARAM(*pan_scan_param); + dest_pan_scan->numWindows = pan_scan_param->cnt; + for (int i = 0; i < dest_pan_scan->numWindows; i++) + { + dest_pan_scan->window[i].x = pan_scan_param->rect_left_offset[i]; + dest_pan_scan->window[i].y = pan_scan_param->rect_top_offset[i]; + dest_pan_scan->window[i].dx = pan_scan_param->rect_right_offset[i]; + dest_pan_scan->window[i].dy = pan_scan_param->rect_bottom_offset[i]; + } +#ifndef PANSCAN_HDLR + if (pan_scan_param->rect_repetition_period == 0) + pan_scan_param->rect_id = NO_PAN_SCAN_BIT; + else if (pan_scan_param->rect_repetition_period > 1) + pan_scan_param->rect_repetition_period = + (pan_scan_param->rect_repetition_period == 2)? 0 : + (pan_scan_param->rect_repetition_period - 1); +#endif + } + else + pan_scan_param->rect_repetition_period = 0; +} + +OMX_S64 h264_stream_parser::process_ts_with_sei_vui(OMX_S64 timestamp) +{ + bool clock_ts_flag = false; + OMX_S64 clock_ts = timestamp; + OMX_U32 deltaTfiDivisor = 2; + if (vui_param.timing_info_present_flag) + { + if (vui_param.pic_struct_present_flag) + { + if(sei_pic_timing.clock_ts_flag) + { + clock_ts = ((sei_pic_timing.hours_value * 60 + sei_pic_timing.minutes_value) * 60 + sei_pic_timing.seconds_value) * 1e6 + + (sei_pic_timing.n_frames * (vui_param.num_units_in_tick * (1 + sei_pic_timing.nuit_field_based_flag)) + sei_pic_timing.time_offset) * + 1e6 / vui_param.time_scale; + ALOGV("-->CLOCK TIMESTAMP : %lld", clock_ts); + clock_ts_flag = true; + } + if (vui_param.fixed_frame_rate_flag) + { + switch (sei_pic_timing.pic_struct) + { + case 1: case 2: deltaTfiDivisor = 1; break; + case 0: case 3: case 4: deltaTfiDivisor = 2; break; + case 5: case 6: deltaTfiDivisor = 3; break; + case 7: deltaTfiDivisor = 4; break; + case 8: deltaTfiDivisor = 6; break; + default: + ALOGE("process_ts_with_sei_vui: pic_struct invalid!"); + } + } + } + if (!clock_ts_flag) + { + if (vui_param.fixed_frame_rate_flag) + clock_ts = calculate_fixed_fps_ts(timestamp, deltaTfiDivisor); + else if (sei_buf_period.is_valid) + clock_ts = calculate_buf_period_ts(timestamp); + } + } + else + { + ALOGV("NO TIMING information present in VUI!"); + } + sei_pic_timing.is_valid = false; // SEI data is valid only for current frame + return clock_ts; +} + +#ifdef PANSCAN_HDLR + +panscan_handler::panscan_handler() : panscan_data(NULL) {} + +panscan_handler::~panscan_handler() +{ + if (panscan_data) + { + free(panscan_data); + panscan_data = NULL; + } +} + +bool panscan_handler::initialize(int num_data) +{ + bool ret = false; + if (!panscan_data) + { + panscan_data = (PANSCAN_NODE *) malloc (sizeof(PANSCAN_NODE) * num_data); + if (panscan_data) + { + panscan_free.add_multiple(panscan_data, num_data); + ret = true; + } + } + else + { + ALOGE("ERROR: Old panscan memory must be freed to allocate new"); + } + return ret; +} + +h264_pan_scan *panscan_handler::get_free() +{ + h264_pan_scan *data = NULL; + PANSCAN_NODE *panscan_node = panscan_used.watch_last(); + panscan_node = (!panscan_node || VALID_TS(panscan_node->start_ts))? + panscan_free.remove_first() : + panscan_used.remove_last(); + if (panscan_node) + { + panscan_node->start_ts = LLONG_MAX; + panscan_node->end_ts = LLONG_MAX; + panscan_node->pan_scan_param.rect_id = NO_PAN_SCAN_BIT; + panscan_node->active = false; + panscan_used.add_last(panscan_node); + data = &panscan_node->pan_scan_param; + } + return data; +} + +h264_pan_scan *panscan_handler::get_populated(OMX_S64 frame_ts) +{ + h264_pan_scan *data = NULL; + PANSCAN_NODE *panscan_node = panscan_used.watch_first(); + while (panscan_node && !data) + { + if (VALID_TS(panscan_node->start_ts)) + { + if (panscan_node->active && frame_ts < panscan_node->start_ts) + panscan_node->start_ts = frame_ts; + if (frame_ts >= panscan_node->start_ts) + if (frame_ts < panscan_node->end_ts) + { + data = &panscan_node->pan_scan_param; + panscan_node->active = true; + } + else + { + panscan_free.add_last(panscan_used.remove_first()); + panscan_node = panscan_used.watch_first(); + } + else + // Finish search if current timestamp has not reached + // start timestamp of first panscan data. + panscan_node = NULL; + } + else + { + // Only one panscan data is stored for clips + // with invalid timestamps in every frame + data = &panscan_node->pan_scan_param; + panscan_node->active = true; + } + } + if (data) + if (data->rect_repetition_period == 0) + panscan_free.add_last(panscan_used.remove_first()); + else if (data->rect_repetition_period > 1) + data->rect_repetition_period -= 2; + PRINT_PANSCAN_DATA(panscan_node); + return data; +} + +void panscan_handler::update_last(OMX_S64 frame_ts) +{ + PANSCAN_NODE *panscan_node = panscan_used.watch_last(); + if (panscan_node && !VALID_TS(panscan_node->start_ts)) + { + panscan_node->start_ts = frame_ts; + PRINT_PANSCAN_DATA(panscan_node); + if (panscan_node->prev) + { + if (frame_ts < panscan_node->prev->end_ts) + panscan_node->prev->end_ts = frame_ts; + else if (!VALID_TS(frame_ts)) + panscan_node->prev->pan_scan_param.rect_repetition_period = 0; + PRINT_PANSCAN_DATA(panscan_node->prev); + } + } +} + +template +void omx_dl_list::add_multiple(NODE_STRUCT *data_arr, int data_num) +{ + for (int idx = 0; idx < data_num; idx++) + add_last(&data_arr[idx]); +} + +template +NODE_STRUCT *omx_dl_list::remove_first() +{ + NODE_STRUCT *data = head; + if (head) + { + if (head->next) + { + head = head->next; + head->prev = NULL; + } + else + head = tail = NULL; + data->next = data->prev = NULL; + } + return data; +} + +template +NODE_STRUCT *omx_dl_list::remove_last() +{ + NODE_STRUCT *data = tail; + if (tail) + { + if (tail->prev) + { + tail = tail->prev; + tail->next = NULL; + } + else + head = tail = NULL; + data->next = data->prev = NULL; + } + return data; +} + +template +void omx_dl_list::add_last(NODE_STRUCT* data_ptr) +{ + if (data_ptr) + { + data_ptr->next = NULL; + data_ptr->prev = tail; + if (tail) + { + tail->next = data_ptr; + tail = data_ptr; + } + else + head = tail = data_ptr; + } +} + +template +NODE_STRUCT* omx_dl_list::watch_first() +{ + return head; +} + +template +NODE_STRUCT* omx_dl_list::watch_last() +{ + return tail; +} + +#endif diff --git a/mm-video/vidc/vdec/src/message_queue.c b/mm-video/vidc/vdec/src/message_queue.c new file mode 100755 index 0000000..2bb9a75 --- /dev/null +++ b/mm-video/vidc/vdec/src/message_queue.c @@ -0,0 +1,178 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include "message_queue.h" + +int check_if_queue_empty ( unsigned int queuetocheck, void* queuecontext ) +{ + struct video_queue_context *ptr_q = NULL; + /* + * queuetocheck - 0 command queue + * queuetocheck - 1 data queue + */ + if ( queuecontext == NULL || (queuetocheck > 1 ) ) + { + return 1; + } + ptr_q = (struct video_queue_context *)queuecontext; + + if (queuetocheck == 0) + { + if (ptr_q->read_comq == ptr_q->write_comq) + { + return 1; + } + } + else if (queuetocheck == 1) + { + if (ptr_q->write_dataq == ptr_q->read_dataq) + { + return 1; + } + } + + return 0; +} + + + +struct video_msgq * queue_get_cmd (void* queuecontext ) +{ + struct video_queue_context *ptr_q = NULL; + struct video_msgq *pitem = NULL; + + if( NULL == queuecontext ) + { + printf("\n queue_get_cmd: Invalid Input parameter\n"); + return NULL; + } + + ptr_q = (struct video_queue_context *)queuecontext; + + /* Wait on the semaphore till it is released */ + sem_wait(&ptr_q->sem_message); + + /* Lock the mutex to protect the critical section */ + pthread_mutex_lock(&ptr_q->mutex); + + if (ptr_q->read_comq != ptr_q->write_comq) + { + pitem = &ptr_q->ptr_cmdq [ptr_q->read_comq]; + ptr_q->read_comq = (ptr_q->read_comq + 1) % \ + ptr_q->commandq_size; + } + else if (ptr_q->write_dataq != ptr_q->read_dataq) + { + pitem = &ptr_q->ptr_dataq [ptr_q->read_dataq]; + ptr_q->read_dataq = (ptr_q->read_dataq + 1) % \ + ptr_q->dataq_size; + } + + /* Unlock the mutex to release the critical section */ + pthread_mutex_unlock(&ptr_q->mutex); + + return pitem; +} + + +int queue_post_cmdq ( void* queuecontext, + struct video_msgq *pitem + ) +{ + struct video_queue_context *ptr_q = NULL; + + if (pitem == NULL || queuecontext == NULL) + { + return -1; + } + ptr_q = (struct video_queue_context *)queuecontext; + + /* Lock the mutex to protect the critical section */ + pthread_mutex_lock(&ptr_q->mutex); + + if ((ptr_q->write_comq + 1) % ptr_q->commandq_size == ptr_q->read_comq) + { + printf("\n QUEUE is FULL"); + /* Unlock the mutex to release the critical section */ + pthread_mutex_unlock(&ptr_q->mutex); + return 0; + } + else + { + /* Store the command in the Message Queue & increment write offset */ + memcpy ( &ptr_q->ptr_cmdq [ptr_q->write_comq],pitem, \ + sizeof (struct video_msgq)); + ptr_q->write_comq = (ptr_q->write_comq + 1) % ptr_q->commandq_size; + } + + /* Unlock the mutex to release the critical section */ + pthread_mutex_unlock(&ptr_q->mutex); + + /* Post the semaphore */ + sem_post(&ptr_q->sem_message); + return 1; +} + + +int queue_post_dataq ( void *queuecontext, + struct video_msgq *pitem + ) +{ + struct video_queue_context *ptr_q = NULL; + + if (pitem == NULL || queuecontext == NULL) + { + return -1; + } + ptr_q = (struct video_queue_context *)queuecontext; + + /* Lock the mutex to protect the critical section */ + pthread_mutex_lock(&ptr_q->mutex); + + if ((ptr_q->write_dataq + 1) % ptr_q->dataq_size == ptr_q->read_dataq) + { + printf("\n QUEUE is FULL"); + /* Unlock the mutex to release the critical section */ + pthread_mutex_unlock(&ptr_q->mutex); + return 0; + } + else + { + /* Store the command in the Message Queue & increment write offset */ + memcpy ( &ptr_q->ptr_dataq [ptr_q->write_dataq],pitem, \ + sizeof (struct video_msgq)); + ptr_q->write_dataq = (ptr_q->write_dataq + 1) % ptr_q->dataq_size; + } + + /* Unlock the mutex to release the critical section */ + pthread_mutex_unlock(&ptr_q->mutex); + + /* Post the semaphore */ + sem_post(&ptr_q->sem_message); + return 1; + +} diff --git a/mm-video/vidc/vdec/src/mp4_utils.cpp b/mm-video/vidc/vdec/src/mp4_utils.cpp new file mode 100644 index 0000000..b4568f5 --- /dev/null +++ b/mm-video/vidc/vdec/src/mp4_utils.cpp @@ -0,0 +1,289 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include "mp4_utils.h" +#include "omx_vdec.h" +# include + +MP4_Utils::MP4_Utils() +{ + m_SrcWidth = 0; + m_SrcHeight = 0; + vop_time_resolution = 0; + vop_time_found = false; + +} +MP4_Utils::~MP4_Utils() +{ +} + +uint32 MP4_Utils::read_bit_field(posInfoType * posPtr, uint32 size) { + uint8 *bits = &posPtr->bytePtr[0]; + uint32 bitBuf = + (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3]; + + uint32 value = (bitBuf >> (32 - posPtr->bitPos - size)) & MASK(size); + + /* Update the offset in preparation for next field */ + posPtr->bitPos += size; + + while (posPtr->bitPos >= 8) { + posPtr->bitPos -= 8; + posPtr->bytePtr++; + } + return value; +} +static uint8 *find_code + (uint8 * bytePtr, uint32 size, uint32 codeMask, uint32 referenceCode) { + uint32 code = 0xFFFFFFFF; + for (uint32 i = 0; i < size; i++) { + code <<= 8; + code |= *bytePtr++; + + if ((code & codeMask) == referenceCode) { + return bytePtr; + } + } + + DEBUG_PRINT_LOW("Unable to find code 0x%x\n", referenceCode); + return NULL; +} +bool MP4_Utils::parseHeader(mp4StreamType * psBits) { + uint32 profile_and_level_indication = 0; + uint8 VerID = 1; /* default value */ + long hxw = 0; + + m_posInfo.bitPos = 0; + m_posInfo.bytePtr = psBits->data; + m_dataBeginPtr = psBits->data; + + m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,4, + MASK(32),VOP_START_CODE); + if(m_posInfo.bytePtr) { + return false; + } + + m_posInfo.bitPos = 0; + m_posInfo.bytePtr = psBits->data; + m_dataBeginPtr = psBits->data; + m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,4, + MASK(32),GOV_START_CODE); + if(m_posInfo.bytePtr) { + return false; + } + + m_posInfo.bitPos = 0; + m_posInfo.bytePtr = psBits->data; + m_dataBeginPtr = psBits->data; + /* parsing Visual Object Seqence(VOS) header */ + m_posInfo.bytePtr = find_code(m_posInfo.bytePtr, + psBits->numBytes, + MASK(32), + VISUAL_OBJECT_SEQUENCE_START_CODE); + if ( m_posInfo.bytePtr == NULL ){ + m_posInfo.bitPos = 0; + m_posInfo.bytePtr = psBits->data; + } + else { + uint32 profile_and_level_indication = read_bit_field (&m_posInfo, 8); + } + /* parsing Visual Object(VO) header*/ + /* note: for now, we skip over the user_data */ + m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,psBits->numBytes, + MASK(32),VISUAL_OBJECT_START_CODE); + if(m_posInfo.bytePtr == NULL) { + m_posInfo.bitPos = 0; + m_posInfo.bytePtr = psBits->data; + } + else { + uint32 is_visual_object_identifier = read_bit_field (&m_posInfo, 1); + if ( is_visual_object_identifier ) { + /* visual_object_verid*/ + read_bit_field (&m_posInfo, 4); + /* visual_object_priority*/ + read_bit_field (&m_posInfo, 3); + } + + /* visual_object_type*/ + uint32 visual_object_type = read_bit_field (&m_posInfo, 4); + if ( visual_object_type != VISUAL_OBJECT_TYPE_VIDEO_ID ) { + return false; + } + /* skipping video_signal_type params*/ + /*parsing Video Object header*/ + m_posInfo.bytePtr = find_code(m_posInfo.bytePtr,psBits->numBytes, + VIDEO_OBJECT_START_CODE_MASK,VIDEO_OBJECT_START_CODE); + if ( m_posInfo.bytePtr == NULL ) { + return false; + } + } + + /* parsing Video Object Layer(VOL) header */ + m_posInfo.bitPos = 0; + m_posInfo.bytePtr = find_code(m_posInfo.bytePtr, + psBits->numBytes, + VIDEO_OBJECT_LAYER_START_CODE_MASK, + VIDEO_OBJECT_LAYER_START_CODE); + if ( m_posInfo.bytePtr == NULL ) { + m_posInfo.bitPos = 0; + m_posInfo.bytePtr = psBits->data; + } + + // 1 -> random accessible VOL + read_bit_field(&m_posInfo, 1); + + uint32 video_object_type_indication = read_bit_field (&m_posInfo, 8); + if ( (video_object_type_indication != SIMPLE_OBJECT_TYPE) && + (video_object_type_indication != SIMPLE_SCALABLE_OBJECT_TYPE) && + (video_object_type_indication != CORE_OBJECT_TYPE) && + (video_object_type_indication != ADVANCED_SIMPLE) && + (video_object_type_indication != RESERVED_OBJECT_TYPE) && + (video_object_type_indication != MAIN_OBJECT_TYPE)) { + return false; + } + /* is_object_layer_identifier*/ + uint32 is_object_layer_identifier = read_bit_field (&m_posInfo, 1); + if (is_object_layer_identifier) { + uint32 video_object_layer_verid = read_bit_field (&m_posInfo, 4); + uint32 video_object_layer_priority = read_bit_field (&m_posInfo, 3); + VerID = (unsigned char)video_object_layer_verid; + } + + /* aspect_ratio_info*/ + uint32 aspect_ratio_info = read_bit_field (&m_posInfo, 4); + if ( aspect_ratio_info == EXTENDED_PAR ) { + /* par_width*/ + read_bit_field (&m_posInfo, 8); + /* par_height*/ + read_bit_field (&m_posInfo, 8); + } + /* vol_control_parameters */ + uint32 vol_control_parameters = read_bit_field (&m_posInfo, 1); + if ( vol_control_parameters ) { + /* chroma_format*/ + uint32 chroma_format = read_bit_field (&m_posInfo, 2); + if ( chroma_format != 1 ) { + return false; + } + /* low_delay*/ + uint32 low_delay = read_bit_field (&m_posInfo, 1); + /* vbv_parameters (annex D)*/ + uint32 vbv_parameters = read_bit_field (&m_posInfo, 1); + if ( vbv_parameters ) { + /* first_half_bitrate*/ + uint32 first_half_bitrate = read_bit_field (&m_posInfo, 15); + uint32 marker_bit = read_bit_field (&m_posInfo, 1); + if ( marker_bit != 1) { + return false; + } + /* latter_half_bitrate*/ + uint32 latter_half_bitrate = read_bit_field (&m_posInfo, 15); + marker_bit = read_bit_field (&m_posInfo, 1); + if ( marker_bit != 1) { + return false; + } + uint32 VBVPeakBitRate = (first_half_bitrate << 15) + latter_half_bitrate; + /* first_half_vbv_buffer_size*/ + uint32 first_half_vbv_buffer_size = read_bit_field (&m_posInfo, 15); + marker_bit = read_bit_field (&m_posInfo, 1); + if ( marker_bit != 1) { + return false; + } + /* latter_half_vbv_buffer_size*/ + uint32 latter_half_vbv_buffer_size = read_bit_field (&m_posInfo, 3); + uint32 VBVBufferSize = (first_half_vbv_buffer_size << 3) + latter_half_vbv_buffer_size; + /* first_half_vbv_occupancy*/ + uint32 first_half_vbv_occupancy = read_bit_field (&m_posInfo, 11); + marker_bit = read_bit_field (&m_posInfo, 1); + if ( marker_bit != 1) { + return false; + } + /* latter_half_vbv_occupancy*/ + uint32 latter_half_vbv_occupancy = read_bit_field (&m_posInfo, 15); + marker_bit = read_bit_field (&m_posInfo, 1); + if ( marker_bit != 1) { + return false; + } + }/* vbv_parameters*/ + }/*vol_control_parameters*/ + + /* video_object_layer_shape*/ + uint32 video_object_layer_shape = read_bit_field (&m_posInfo, 2); + uint8 VOLShape = (unsigned char)video_object_layer_shape; + if ( VOLShape != MPEG4_SHAPE_RECTANGULAR ) { + return false; + } + /* marker_bit*/ + uint32 marker_bit = read_bit_field (&m_posInfo, 1); + if ( marker_bit != 1 ) { + return false; + } + /* vop_time_increment_resolution*/ + uint32 vop_time_increment_resolution = read_bit_field (&m_posInfo, 16); + vop_time_resolution = vop_time_increment_resolution; + vop_time_found = true; + return true; +} + +bool MP4_Utils::is_notcodec_vop(unsigned char *pbuffer, unsigned int len) +{ + unsigned int index = 4,vop_bits=0; + unsigned int temp = vop_time_resolution - 1; + unsigned char vop_type=0,modulo_bit=0,not_coded=0; + if (!vop_time_found || !pbuffer || len < 5) { + return false; + } + if((pbuffer[0] == 0) && (pbuffer[1] == 0) && (pbuffer[2] == 1) && (pbuffer[3] == 0xB6)){ + while(temp) { + vop_bits++; + temp >>= 1; + } + vop_type = (pbuffer[index] & 0xc0) >> 6; + unsigned bits_parsed = 2; + do { + modulo_bit = pbuffer[index] & (1 << (7-bits_parsed)); + bits_parsed++; + index += bits_parsed/8; + bits_parsed = bits_parsed %8; + if(index >= len) { + return false; + } + }while(modulo_bit); + bits_parsed++; //skip marker bit + bits_parsed += vop_bits + 1;//Vop bit & Marker bits + index += bits_parsed/8; + if(index >= len) { + return false; + } + bits_parsed = bits_parsed % 8; + not_coded = pbuffer[index] & (1 << (7 - bits_parsed)); + if(!not_coded){ + return true; + } + } + return false; +} diff --git a/mm-video/vidc/vdec/src/omx_vdec.cpp b/mm-video/vidc/vdec/src/omx_vdec.cpp new file mode 100644 index 0000000..c1a5977 --- /dev/null +++ b/mm-video/vidc/vdec/src/omx_vdec.cpp @@ -0,0 +1,8884 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + +*//** @file omx_vdec.cpp + This module contains the implementation of the OpenMAX core & component. + +*//*========================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include "omx_vdec.h" +#include +#include + +#ifndef _ANDROID_ +#include +#include +#endif //_ANDROID_ + +#ifdef _ANDROID_ +#include +#undef USE_EGL_IMAGE_GPU +#endif + +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) +#include +#endif + +#if defined (_ANDROID_ICS_) +#include +#endif + +#ifdef _ANDROID_ +#include "DivXDrmDecrypt.h" +#endif //_ANDROID_ + +#ifdef USE_EGL_IMAGE_GPU +#include +#include +#define EGL_BUFFER_HANDLE_QCOM 0x4F00 +#define EGL_BUFFER_OFFSET_QCOM 0x4F01 +#endif + +#ifdef INPUT_BUFFER_LOG +#define INPUT_BUFFER_FILE_NAME "/data/input-bitstream.\0\0\0\0" +#define INPUT_BUFFER_FILE_NAME_LEN 30 +FILE *inputBufferFile1; +char inputfilename [INPUT_BUFFER_FILE_NAME_LEN] = "\0"; +#endif +#ifdef OUTPUT_BUFFER_LOG +FILE *outputBufferFile1; +char outputfilename [] = "/data/output.yuv"; +#endif +#ifdef OUTPUT_EXTRADATA_LOG +FILE *outputExtradataFile; +char ouputextradatafilename [] = "/data/extradata"; +#endif + +#define DEFAULT_FPS 30 +#define MAX_NUM_SPS 32 +#define MAX_NUM_PPS 256 +#define MAX_INPUT_ERROR (MAX_NUM_SPS + MAX_NUM_PPS) +#define MAX_SUPPORTED_FPS 120 + +#define VC1_SP_MP_START_CODE 0xC5000000 +#define VC1_SP_MP_START_CODE_MASK 0xFF000000 +#define VC1_AP_SEQ_START_CODE 0x0F010000 +#define VC1_STRUCT_C_PROFILE_MASK 0xF0 +#define VC1_STRUCT_B_LEVEL_MASK 0xE0000000 +#define VC1_SIMPLE_PROFILE 0 +#define VC1_MAIN_PROFILE 1 +#define VC1_ADVANCE_PROFILE 3 +#define VC1_SIMPLE_PROFILE_LOW_LEVEL 0 +#define VC1_SIMPLE_PROFILE_MED_LEVEL 2 +#define VC1_STRUCT_C_LEN 4 +#define VC1_STRUCT_C_POS 8 +#define VC1_STRUCT_A_POS 12 +#define VC1_STRUCT_B_POS 24 +#define VC1_SEQ_LAYER_SIZE 36 + +#ifdef USE_ION + #define MEM_DEVICE "/dev/ion" + #ifdef MAX_RES_720P + #define MEM_HEAP_ID ION_CAMERA_HEAP_ID + #else + #define MEM_HEAP_ID ION_CP_MM_HEAP_ID + #endif +#elif MAX_RES_720P +#define MEM_DEVICE "/dev/pmem_adsp" +#elif MAX_RES_1080P_EBI +#define MEM_DEVICE "/dev/pmem_adsp" +#elif MAX_RES_1080P +#define MEM_DEVICE "/dev/pmem_smipool" +#endif + + +#ifdef MAX_RES_720P +#define DEVICE_SCRATCH 0 +#else +#define DEVICE_SCRATCH 64 +#endif + +/* +#ifdef _ANDROID_ + extern "C"{ + #include + } +#endif//_ANDROID_ +*/ + +#ifndef _ANDROID_ +#include +#define strlcpy g_strlcpy +#endif + +#define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } +#define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); } + +void* async_message_thread (void *input) +{ + struct vdec_ioctl_msg ioctl_msg; + struct vdec_msginfo vdec_msg; + omx_vdec *omx = reinterpret_cast(input); + int error_code = 0; + DEBUG_PRINT_HIGH("omx_vdec: Async thread start"); + prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0); + while (1) + { + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&vdec_msg; + /*Wait for a message from the video decoder driver*/ + error_code = ioctl ( omx->drv_ctx.video_driver_fd,VDEC_IOCTL_GET_NEXT_MSG, + (void*)&ioctl_msg); + if (error_code == -512) // ERESTARTSYS + { + DEBUG_PRINT_ERROR("\n ERESTARTSYS received in ioctl read next msg!"); + } + else if (error_code < 0) + { + DEBUG_PRINT_ERROR("\n Error in ioctl read next msg"); + break; + } /*Call Instance specific process function*/ + else if (omx->async_message_process(input,&vdec_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR:Wrong ioctl message"); + } + } + DEBUG_PRINT_HIGH("omx_vdec: Async thread stop"); + return NULL; +} + +void* message_thread(void *input) +{ + omx_vdec* omx = reinterpret_cast(input); + unsigned char id; + int n; + + DEBUG_PRINT_HIGH("omx_vdec: message thread start"); + prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0); + while (1) + { + + n = read(omx->m_pipe_in, &id, 1); + + if(0 == n) + { + break; + } + + if (1 == n) + { + omx->process_event_cb(omx, id); + } + if ((n < 0) && (errno != EINTR)) + { + DEBUG_PRINT_ERROR("\nERROR: read from pipe failed, ret %d errno %d", n, errno); + break; + } + } + DEBUG_PRINT_HIGH("omx_vdec: message thread stop"); + return 0; +} + +void post_message(omx_vdec *omx, unsigned char id) +{ + int ret_value; + DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d", id,omx->m_pipe_out); + ret_value = write(omx->m_pipe_out, &id, 1); + DEBUG_PRINT_LOW("post_message to pipe done %d",ret_value); +} + +// omx_cmd_queue destructor +omx_vdec::omx_cmd_queue::~omx_cmd_queue() +{ + // Nothing to do +} + +// omx cmd queue constructor +omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) +{ + memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); +} + +// omx cmd queue insert +bool omx_vdec::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id) +{ + bool ret = true; + if(m_size < OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_q[m_write].id = id; + m_q[m_write].param1 = p1; + m_q[m_write].param2 = p2; + m_write++; + m_size ++; + if(m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_write = 0; + } + } + else + { + ret = false; + DEBUG_PRINT_ERROR("\n ERROR: %s()::Command Queue Full", __func__); + } + return ret; +} + +// omx cmd queue pop +bool omx_vdec::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id) +{ + bool ret = true; + if (m_size > 0) + { + *id = m_q[m_read].id; + *p1 = m_q[m_read].param1; + *p2 = m_q[m_read].param2; + // Move the read pointer ahead + ++m_read; + --m_size; + if(m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_read = 0; + } + } + else + { + ret = false; + } + return ret; +} + +// Retrieve the first mesg type in the queue +unsigned omx_vdec::omx_cmd_queue::get_q_msg_type() +{ + return m_q[m_read].id; +} + +#ifdef _ANDROID_ +omx_vdec::ts_arr_list::ts_arr_list() +{ + //initialize timestamps array + memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) ); +} +omx_vdec::ts_arr_list::~ts_arr_list() +{ + //free m_ts_arr_list? +} + +bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts) +{ + bool ret = true; + bool duplicate_ts = false; + int idx = 0; + + //insert at the first available empty location + for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) + { + if (!m_ts_arr_list[idx].valid) + { + //found invalid or empty entry, save timestamp + m_ts_arr_list[idx].valid = true; + m_ts_arr_list[idx].timestamp = ts; + DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)", + ts, idx); + break; + } + } + + if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) + { + DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert"); + ret = false; + } + return ret; +} + +bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts) +{ + bool ret = true; + int min_idx = -1; + OMX_TICKS min_ts = 0; + int idx = 0; + + for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) + { + + if (m_ts_arr_list[idx].valid) + { + //found valid entry, save index + if (min_idx < 0) + { + //first valid entry + min_ts = m_ts_arr_list[idx].timestamp; + min_idx = idx; + } + else if (m_ts_arr_list[idx].timestamp < min_ts) + { + min_ts = m_ts_arr_list[idx].timestamp; + min_idx = idx; + } + } + + } + + if (min_idx < 0) + { + //no valid entries found + DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop"); + ts = 0; + ret = false; + } + else + { + ts = m_ts_arr_list[min_idx].timestamp; + m_ts_arr_list[min_idx].valid = false; + DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)", + ts, min_idx); + } + + return ret; + +} + + +bool omx_vdec::ts_arr_list::reset_ts_list() +{ + bool ret = true; + int idx = 0; + + DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list"); + for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) + { + m_ts_arr_list[idx].valid = false; + } + return ret; +} +#endif + +// factory function executed by the core to create instances +void *get_omx_component_factory_fn(void) +{ + return (new omx_vdec); +} + +#ifdef _ANDROID_ +#ifdef USE_ION +VideoHeap::VideoHeap(int devicefd, size_t size, void* base, + struct ion_handle *handle, int ionMapfd) +{ + m_ion_device_fd = devicefd; + m_ion_handle = handle; + MemoryHeapBase::init(ionMapfd, base, size, 0, MEM_DEVICE); + //ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd); +} +#else +VideoHeap::VideoHeap(int fd, size_t size, void* base) +{ + // dup file descriptor, map once, use pmem + init(dup(fd), base, size, 0 , MEM_DEVICE); +} +#endif +#endif // _ANDROID_ +/* ====================================================================== +FUNCTION + omx_vdec::omx_vdec + +DESCRIPTION + Constructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_vdec::omx_vdec(): m_state(OMX_StateInvalid), + m_app_data(NULL), + m_inp_mem_ptr(NULL), + m_out_mem_ptr(NULL), + m_phdr_pmem_ptr(NULL), + pending_input_buffers(0), + pending_output_buffers(0), + m_out_bm_count(0), + m_inp_bm_count(0), + m_inp_bPopulated(OMX_FALSE), + m_out_bPopulated(OMX_FALSE), + m_flags(0), + m_inp_bEnabled(OMX_TRUE), + m_out_bEnabled(OMX_TRUE), + m_platform_list(NULL), + m_platform_entry(NULL), + m_pmem_info(NULL), + output_flush_progress (false), + input_flush_progress (false), + input_use_buffer (false), + output_use_buffer (false), + arbitrary_bytes (true), + psource_frame (NULL), + pdest_frame (NULL), + m_inp_heap_ptr (NULL), + m_heap_inp_bm_count (0), + codec_type_parse ((codec_type)0), + first_frame_meta (true), + frame_count (0), + nal_length(0), + nal_count (0), + look_ahead_nal (false), + first_frame(0), + first_buffer(NULL), + first_frame_size (0), + m_error_propogated(false), + m_device_file_ptr(NULL), + m_vc1_profile((vc1_profile_type)0), + prev_ts(LLONG_MAX), + rst_prev_ts(true), + frm_int(0), + m_in_alloc_cnt(0), + m_display_id(NULL), + ouput_egl_buffers(false), + h264_parser(NULL), + client_extradata(0), + h264_last_au_ts(LLONG_MAX), + h264_last_au_flags(0), + m_inp_err_count(0), +#ifdef _ANDROID_ + m_heap_ptr(NULL), + m_heap_count(0), + m_enable_android_native_buffers(OMX_FALSE), + m_use_android_native_buffers(OMX_FALSE), +#endif + in_reconfig(false), + m_use_output_pmem(OMX_FALSE), + m_out_mem_region_smi(OMX_FALSE), + m_out_pvt_entry_pmem(OMX_FALSE), + secure_mode(false) +#ifdef _ANDROID_ + ,iDivXDrmDecrypt(NULL) +#endif + ,m_desc_buffer_ptr(NULL) + ,m_extradata(NULL) +{ + /* Assumption is that , to begin with , we have all the frames with decoder */ + DEBUG_PRINT_HIGH("In OMX vdec Constructor"); +#ifdef _ANDROID_ + char property_value[PROPERTY_VALUE_MAX] = {0}; + property_get("vidc.dec.debug.perf", property_value, "0"); + perf_flag = atoi(property_value); + if (perf_flag) + { + DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag); + dec_time.start(); + proc_frms = latency = 0; + } + property_value[0] = NULL; + property_get("vidc.dec.debug.ts", property_value, "0"); + m_debug_timestamp = atoi(property_value); + DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp); + if (m_debug_timestamp) + { + time_stamp_dts.set_timestamp_reorder_mode(true); + time_stamp_dts.enable_debug_print(true); + } + + property_value[0] = NULL; + property_get("vidc.dec.debug.concealedmb", property_value, "0"); + m_debug_concealedmb = atoi(property_value); + DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb); + +#endif + memset(&m_cmp,0,sizeof(m_cmp)); + memset(&m_cb,0,sizeof(m_cb)); + memset (&drv_ctx,0,sizeof(drv_ctx)); + memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE)); + memset (m_hwdevice_name,0,sizeof(m_hwdevice_name)); + memset(&op_buf_rcnfg, 0 ,sizeof(vdec_allocatorproperty)); + memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); + m_demux_entries = 0; +#ifdef _ANDROID_ICS_ + memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); +#endif + drv_ctx.timestamp_adjust = false; + drv_ctx.video_driver_fd = -1; + m_vendor_config.pData = NULL; + pthread_mutex_init(&m_lock, NULL); + sem_init(&m_cmd_lock,0,0); +#ifdef _ANDROID_ + char extradata_value[PROPERTY_VALUE_MAX] = {0}; + property_get("vidc.dec.debug.extradata", extradata_value, "0"); + m_debug_extradata = atoi(extradata_value); + DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata); +#endif +} + + +/* ====================================================================== +FUNCTION + omx_vdec::~omx_vdec + +DESCRIPTION + Destructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_vdec::~omx_vdec() +{ + m_pmem_info = NULL; + DEBUG_PRINT_HIGH("In OMX vdec Destructor"); + if(m_pipe_in) close(m_pipe_in); + if(m_pipe_out) close(m_pipe_out); + m_pipe_in = -1; + m_pipe_out = -1; + DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit"); + pthread_join(msg_thread_id,NULL); + DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit"); + pthread_join(async_thread_id,NULL); + pthread_mutex_destroy(&m_lock); + sem_destroy(&m_cmd_lock); +#ifdef _ANDROID_ + if (perf_flag) + { + DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME"); + dec_time.end(); + } +#endif /* _ANDROID_ */ + DEBUG_PRINT_HIGH("Exit OMX vdec Destructor"); +} + +/* ====================================================================== +FUNCTION + omx_vdec::OMXCntrlProcessMsgCb + +DESCRIPTION + IL Client callbacks are generated through this routine. The decoder + provides the thread context for this routine. + +PARAMETERS + ctxt -- Context information related to the self. + id -- Event identifier. This could be any of the following: + 1. Command completion event + 2. Buffer done callback event + 3. Frame done callback event + +RETURN VALUE + None. + +========================================================================== */ +void omx_vdec::process_event_cb(void *ctxt, unsigned char id) +{ + unsigned p1; // Parameter - 1 + unsigned p2; // Parameter - 2 + unsigned ident; + unsigned qsize=0; // qsize + omx_vdec *pThis = (omx_vdec *) ctxt; + + if(!pThis) + { + DEBUG_PRINT_ERROR("\n ERROR: %s()::Context is incorrect, bailing out", + __func__); + return; + } + + // Protect the shared queue data structure + do + { + /*Read the message id's from the queue*/ + pthread_mutex_lock(&pThis->m_lock); + qsize = pThis->m_cmd_q.m_size; + if(qsize) + { + pThis->m_cmd_q.pop_entry(&p1,&p2,&ident); + } + + if (qsize == 0 && pThis->m_state != OMX_StatePause) + { + qsize = pThis->m_ftb_q.m_size; + if (qsize) + { + pThis->m_ftb_q.pop_entry(&p1,&p2,&ident); + } + } + + if (qsize == 0 && pThis->m_state != OMX_StatePause) + { + qsize = pThis->m_etb_q.m_size; + if (qsize) + { + pThis->m_etb_q.pop_entry(&p1,&p2,&ident); + } + } + pthread_mutex_unlock(&pThis->m_lock); + + /*process message if we have one*/ + if(qsize > 0) + { + id = ident; + switch (id) + { + case OMX_COMPONENT_GENERATE_EVENT: + if (pThis->m_cb.EventHandler) + { + switch (p1) + { + case OMX_CommandStateSet: + pThis->m_state = (OMX_STATETYPE) p2; + DEBUG_PRINT_HIGH("OMX_CommandStateSet complete, m_state = %d", + pThis->m_state); + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL); + break; + + case OMX_EventError: + if(p2 == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\n OMX_EventError: p2 is OMX_StateInvalid"); + pThis->m_state = (OMX_STATETYPE) p2; + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, p2, NULL); + } + else if (p2 == OMX_ErrorHardware) + { + pThis->omx_report_error(); + } + else + { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventError, p2, NULL, NULL ); + } + break; + + case OMX_CommandPortDisable: + DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%d]", p2); + if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) + { + BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); + break; + } + if (p2 == OMX_CORE_OUTPUT_PORT_INDEX && pThis->in_reconfig) + { + pThis->in_reconfig = false; + pThis->drv_ctx.op_buf = pThis->op_buf_rcnfg; + OMX_ERRORTYPE eRet = pThis->set_buffer_req(&pThis->drv_ctx.op_buf); + if(eRet != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet); + pThis->omx_report_error(); + break; + } + } + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL ); + break; + case OMX_CommandPortEnable: + DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%d]", p2); + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\ + OMX_EventCmdComplete, p1, p2, NULL ); + break; + + default: + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL ); + break; + + } + } + else + { + DEBUG_PRINT_ERROR("\n ERROR: %s()::EventHandler is NULL", __func__); + } + break; + case OMX_COMPONENT_GENERATE_ETB_ARBITRARY: + if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure"); + pThis->omx_report_error (); + } + break; + case OMX_COMPONENT_GENERATE_ETB: + if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_FTB: + if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n fill_this_buffer_proxy failure"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_COMMAND: + pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\ + (OMX_U32)p2,(OMX_PTR)NULL); + break; + + case OMX_COMPONENT_GENERATE_EBD: + + if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EBD failure"); + pThis->omx_report_error (); + } + else + { + if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) + { + pThis->m_inp_err_count++; + pThis->time_stamp_dts.remove_time_stamp( + ((OMX_BUFFERHEADERTYPE *)p1)->nTimeStamp, + (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) + ?true:false); + } + else + { + pThis->m_inp_err_count = 0; + } + if ( pThis->empty_buffer_done(&pThis->m_cmp, + (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n empty_buffer_done failure"); + pThis->omx_report_error (); + } + if(!pThis->arbitrary_bytes && pThis->m_inp_err_count > MAX_INPUT_ERROR) + { + DEBUG_PRINT_ERROR("\n Input bitstream error for consecutive %d frames.", MAX_INPUT_ERROR); + pThis->omx_report_error (); + } + } + break; + case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: + { + int64_t *timestamp = (int64_t *)p1; + if (p1) + { + pThis->time_stamp_dts.remove_time_stamp(*timestamp, + (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) + ?true:false); + free(timestamp); + } + } + break; + case OMX_COMPONENT_GENERATE_FBD: + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_FBD failure"); + pThis->omx_report_error (); + } + else if ( pThis->fill_buffer_done(&pThis->m_cmp, + (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) + { + DEBUG_PRINT_ERROR("\n fill_buffer_done failure"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH: + DEBUG_PRINT_HIGH("Driver flush i/p Port complete"); + if (!pThis->input_flush_progress) + { + DEBUG_PRINT_ERROR("\n WARNING: Unexpected flush from driver"); + } + else + { + pThis->execute_input_flush(); + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\nOMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure"); + pThis->omx_report_error (); + } + else + { + /*Check if we need generate event for Flush done*/ + if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_INPUT_FLUSH_PENDING)) + { + BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING); + DEBUG_PRINT_LOW("Input Flush completed - Notify Client"); + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandFlush, + OMX_CORE_INPUT_PORT_INDEX,NULL ); + } + if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_IDLE_PENDING)) + { + if (!pThis->output_flush_progress) + { + DEBUG_PRINT_LOW("Output flush done hence issue stop"); + if (ioctl (pThis->drv_ctx.video_driver_fd, + VDEC_IOCTL_CMD_STOP,NULL ) < 0) + { + DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed"); + pThis->omx_report_error (); + } + } + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + } + break; + + case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH: + DEBUG_PRINT_HIGH("Driver flush o/p Port complete"); + if (!pThis->output_flush_progress) + { + DEBUG_PRINT_ERROR("\n WARNING: Unexpected flush from driver"); + } + else + { + pThis->execute_output_flush(); + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed"); + pThis->omx_report_error (); + } + else + { + /*Check if we need generate event for Flush done*/ + if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) + { + DEBUG_PRINT_LOW("Notify Output Flush done"); + BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING); + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandFlush, + OMX_CORE_OUTPUT_PORT_INDEX,NULL ); + } + if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) + { + DEBUG_PRINT_LOW("Internal flush complete"); + BITMASK_CLEAR (&pThis->m_flags, + OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); + if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) + { + pThis->post_event(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + BITMASK_CLEAR (&pThis->m_flags, + OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); + + } + } + + if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) + { + if (!pThis->input_flush_progress) + { + DEBUG_PRINT_LOW("Input flush done hence issue stop"); + if (ioctl (pThis->drv_ctx.video_driver_fd, + VDEC_IOCTL_CMD_STOP,NULL ) < 0) + { + DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed"); + pThis->omx_report_error (); + } + } + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + } + break; + + case OMX_COMPONENT_GENERATE_START_DONE: + DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE"); + + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_START_DONE Failure"); + pThis->omx_report_error (); + } + else + { + DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success"); + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) + { + DEBUG_PRINT_LOW("Move to executing"); + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); + pThis->m_state = OMX_StateExecuting; + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateExecuting, NULL); + } + else if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_PAUSE_PENDING)) + { + if (ioctl (pThis->drv_ctx.video_driver_fd, + VDEC_IOCTL_CMD_PAUSE,NULL ) < 0) + { + DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_PAUSE failed"); + pThis->omx_report_error (); + } + } + } + } + else + { + DEBUG_PRINT_ERROR("\n Event Handler callback is NULL"); + } + break; + + case OMX_COMPONENT_GENERATE_PAUSE_DONE: + DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE"); + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed"); + pThis->omx_report_error (); + } + else + { + pThis->complete_pending_buffer_done_cbs(); + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) + { + DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE nofity"); + //Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING); + pThis->m_state = OMX_StatePause; + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StatePause, NULL); + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + + break; + + case OMX_COMPONENT_GENERATE_RESUME_DONE: + DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE"); + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_RESUME_DONE failed"); + pThis->omx_report_error (); + } + else + { + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) + { + DEBUG_PRINT_LOW("Moving the decoder to execute state"); + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); + pThis->m_state = OMX_StateExecuting; + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateExecuting,NULL); + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + + break; + + case OMX_COMPONENT_GENERATE_STOP_DONE: + DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_STOP_DONE"); + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_STOP_DONE ret failed"); + pThis->omx_report_error (); + } + else + { + pThis->complete_pending_buffer_done_cbs(); + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE Success"); + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING); + pThis->m_state = OMX_StateIdle; + DEBUG_PRINT_LOW("Move to Idle State"); + pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateIdle,NULL); + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + + break; + + case OMX_COMPONENT_GENERATE_PORT_RECONFIG: + DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_PORT_RECONFIG"); + if (pThis->start_port_reconfig() != OMX_ErrorNone) + pThis->omx_report_error(); + else + { + if (pThis->in_reconfig) + { + if (pThis->m_cb.EventHandler) { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventPortSettingsChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL ); + } else { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + } + if (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) + { + OMX_INTERLACETYPE format = (OMX_INTERLACETYPE)-1; + OMX_EVENTTYPE event = (OMX_EVENTTYPE)OMX_EventIndexsettingChanged; + if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst) + format = OMX_InterlaceInterleaveFrameTopFieldFirst; + else if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst) + format = OMX_InterlaceInterleaveFrameBottomFieldFirst; + else //unsupported interlace format; raise a error + event = OMX_EventError; + if (pThis->m_cb.EventHandler) { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + event, format, 0, NULL ); + } else { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + } + } + break; + + case OMX_COMPONENT_GENERATE_EOS_DONE: + DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_EOS_DONE"); + if (pThis->m_cb.EventHandler) { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag, + OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL ); + } else { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + pThis->prev_ts = LLONG_MAX; + pThis->rst_prev_ts = true; + break; + + case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_HARDWARE_ERROR"); + pThis->omx_report_error (); + break; + case OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG: + { + DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG"); + if (pThis->m_cb.EventHandler) { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + (OMX_EVENTTYPE)OMX_EventIndexsettingChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL ); + } else { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + } + default: + break; + } + } + pthread_mutex_lock(&pThis->m_lock); + qsize = pThis->m_cmd_q.m_size; + if (pThis->m_state != OMX_StatePause) + qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size); + pthread_mutex_unlock(&pThis->m_lock); + } + while(qsize>0); + +} + + + +/* ====================================================================== +FUNCTION + omx_vdec::ComponentInit + +DESCRIPTION + Initialize the component. + +PARAMETERS + ctxt -- Context information related to the self. + id -- Event identifier. This could be any of the following: + 1. Command completion event + 2. Buffer done callback event + 3. Frame done callback event + +RETURN VALUE + None. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + unsigned int alignment = 0,buffer_size = 0; + int is_secure = 0; + int i = 0; + int fds[2]; + int r; + OMX_STRING device_name = "/dev/msm_vidc_dec"; + + if(!strncmp(role, "OMX.qcom.video.decoder.avc.secure",OMX_MAX_STRINGNAME_SIZE)){ + secure_mode = true; + arbitrary_bytes = false; + role = "OMX.qcom.video.decoder.avc"; + device_name = "/dev/msm_vidc_dec_sec"; + is_secure = 1; + } + DEBUG_PRINT_HIGH("omx_vdec::component_init(): Start of New Playback : role = %s : DEVICE = %s", + role, device_name); + + drv_ctx.video_driver_fd = open(device_name, O_RDWR | O_NONBLOCK); + + DEBUG_PRINT_HIGH("omx_vdec::component_init(): Open returned fd %d, errno %d", + drv_ctx.video_driver_fd, errno); + + if(drv_ctx.video_driver_fd == 0){ + drv_ctx.video_driver_fd = open(device_name, O_RDWR | O_NONBLOCK); + } + + if(is_secure && drv_ctx.video_driver_fd < 0) { + do { + usleep(100 * 1000); + drv_ctx.video_driver_fd = open(device_name, O_RDWR | O_NONBLOCK); + if (drv_ctx.video_driver_fd > 0) { + break; + } + } while(i++ < 50); + } + if(drv_ctx.video_driver_fd < 0) + { + DEBUG_PRINT_ERROR("\n Omx_vdec::Comp Init Returning failure, errno %d", errno); + return OMX_ErrorInsufficientResources; + } + drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS; + drv_ctx.frame_rate.fps_denominator = 1; + + +#ifdef INPUT_BUFFER_LOG + strcpy(inputfilename, INPUT_BUFFER_FILE_NAME); +#endif +#ifdef OUTPUT_BUFFER_LOG + outputBufferFile1 = fopen (outputfilename, "ab"); +#endif +#ifdef OUTPUT_EXTRADATA_LOG + outputExtradataFile = fopen (ouputextradatafilename, "ab"); +#endif + + // Copy the role information which provides the decoder kind + strlcpy(drv_ctx.kind,role,128); + if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.mpeg4",\ + OMX_MAX_STRINGNAME_SIZE); + drv_ctx.timestamp_adjust = true; + drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4; + eCompressionFormat = OMX_VIDEO_CodingMPEG4; + /*Initialize Start Code for MPEG4*/ + codec_type_parse = CODEC_TYPE_MPEG4; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "m4v"); +#endif + } + else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.mpeg2",\ + OMX_MAX_STRINGNAME_SIZE); + drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2; + eCompressionFormat = OMX_VIDEO_CodingMPEG2; + /*Initialize Start Code for MPEG2*/ + codec_type_parse = CODEC_TYPE_MPEG2; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "mpg"); +#endif + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("H263 Decoder selected"); + drv_ctx.decoder_format = VDEC_CODECTYPE_H263; + eCompressionFormat = OMX_VIDEO_CodingH263; + codec_type_parse = CODEC_TYPE_H263; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "263"); +#endif + } +#ifdef MAX_RES_1080P + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW ("DIVX 311 Decoder selected"); + drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3; + eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; + codec_type_parse = CODEC_TYPE_DIVX; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef _ANDROID_ + OMX_ERRORTYPE err = createDivxDrmContext(); + if( err != OMX_ErrorNone ) { + DEBUG_PRINT_ERROR("createDivxDrmContext Failed"); + return err; + } +#endif //_ANDROID_ + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_ERROR ("DIVX 4 Decoder selected"); + drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4; + eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; + codec_type_parse = CODEC_TYPE_DIVX; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef _ANDROID_ + OMX_ERRORTYPE err = createDivxDrmContext(); + if( err != OMX_ErrorNone ) { + DEBUG_PRINT_ERROR("createDivxDrmContext Failed"); + return err; + } +#endif //_ANDROID_ + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_ERROR ("DIVX 5/6 Decoder selected"); + drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6; + eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; + codec_type_parse = CODEC_TYPE_DIVX; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef _ANDROID_ + OMX_ERRORTYPE err = createDivxDrmContext(); + if( err != OMX_ErrorNone ) { + DEBUG_PRINT_ERROR("createDivxDrmContext Failed"); + return err; + } +#endif //_ANDROID_ + } +#else + else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\ + OMX_MAX_STRINGNAME_SIZE)) || (!strncmp(drv_ctx.kind, \ + "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE))) + { + strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_ERROR ("DIVX Decoder selected"); + drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_5; + eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; + codec_type_parse = CODEC_TYPE_DIVX; + m_frame_parser.init_start_codes (codec_type_parse); + +#ifdef _ANDROID_ + OMX_ERRORTYPE err = createDivxDrmContext(); + if( err != OMX_ErrorNone ) { + DEBUG_PRINT_ERROR("createDivxDrmContext Failed"); + return err; + } +#endif //_ANDROID_ + } +#endif + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); + drv_ctx.decoder_format = VDEC_CODECTYPE_H264; + eCompressionFormat = OMX_VIDEO_CodingAVC; + codec_type_parse = CODEC_TYPE_H264; + m_frame_parser.init_start_codes (codec_type_parse); + m_frame_parser.init_nal_length(nal_length); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "264"); +#endif + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); + drv_ctx.decoder_format = VDEC_CODECTYPE_VC1; + eCompressionFormat = OMX_VIDEO_CodingWMV; + codec_type_parse = CODEC_TYPE_VC1; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "vc1"); +#endif + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); + drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV; + eCompressionFormat = OMX_VIDEO_CodingWMV; + codec_type_parse = CODEC_TYPE_VC1; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "vc1"); +#endif + } + else + { + DEBUG_PRINT_ERROR("\nERROR:Unknown Component\n"); + eRet = OMX_ErrorInvalidComponentName; + } +#ifdef INPUT_BUFFER_LOG + inputBufferFile1 = fopen (inputfilename, "ab"); +#endif + if (eRet == OMX_ErrorNone) + { +#ifdef MAX_RES_720P + drv_ctx.output_format = VDEC_YUV_FORMAT_NV12; + +#endif +#ifdef MAX_RES_1080P + drv_ctx.output_format = VDEC_YUV_FORMAT_TILE_4x2; +#endif + /*Initialize Decoder with codec type and resolution*/ + ioctl_msg.in = &drv_ctx.decoder_format; + ioctl_msg.out = NULL; + + if ( (eRet == OMX_ErrorNone) && + ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_CODEC, + (void*)&ioctl_msg) < 0) + + { + DEBUG_PRINT_ERROR("\n Set codec type failed"); + eRet = OMX_ErrorInsufficientResources; + } + + /*Set the output format*/ + ioctl_msg.in = &drv_ctx.output_format; + ioctl_msg.out = NULL; + + if ( (eRet == OMX_ErrorNone) && + ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_OUTPUT_FORMAT, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n Set output format failed"); + eRet = OMX_ErrorInsufficientResources; + } + +#ifdef MAX_RES_720P + drv_ctx.video_resolution.frame_height = + drv_ctx.video_resolution.scan_lines = 720; + drv_ctx.video_resolution.frame_width = + drv_ctx.video_resolution.stride = 1280; +#endif +#ifdef MAX_RES_1080P + drv_ctx.video_resolution.frame_height = + drv_ctx.video_resolution.scan_lines = 1088; + drv_ctx.video_resolution.frame_width = + drv_ctx.video_resolution.stride = 1920; +#endif + + ioctl_msg.in = &drv_ctx.video_resolution; + ioctl_msg.out = NULL; + + if ( (eRet == OMX_ErrorNone) && + ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_PICRES, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n Set Resolution failed"); + eRet = OMX_ErrorInsufficientResources; + } + + /*Get the Buffer requirements for input and output ports*/ + drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT; + drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + drv_ctx.interlace = VDEC_InterlaceFrameProgressive; + drv_ctx.extradata = 0; + drv_ctx.picture_order = VDEC_ORDER_DISPLAY; + drv_ctx.idr_only_decoding = 0; + + if (eRet == OMX_ErrorNone) + eRet = get_buffer_req(&drv_ctx.ip_buf); + if (eRet == OMX_ErrorNone) + eRet = get_buffer_req(&drv_ctx.op_buf); + m_state = OMX_StateLoaded; +#ifdef DEFAULT_EXTRADATA + if (eRet == OMX_ErrorNone && !secure_mode) + eRet = enable_extradata(DEFAULT_EXTRADATA); +#endif + if ( (codec_type_parse == CODEC_TYPE_VC1) || + (codec_type_parse == CODEC_TYPE_H264)) //add CP check here + { + //Check if dmx can be disabled + struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; + OMX_ERRORTYPE eRet = OMX_ErrorNone; + ioctl_msg.out = &drv_ctx.disable_dmx; + if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_GET_DISABLE_DMX_SUPPORT, &ioctl_msg)) + { + DEBUG_PRINT_ERROR("Error VDEC_IOCTL_GET_DISABLE_DMX_SUPPORT"); + eRet = OMX_ErrorHardware; + } + else + { + if (drv_ctx.disable_dmx && !secure_mode) + { + DEBUG_PRINT_HIGH("DMX disable is supported"); + + int rc = ioctl(drv_ctx.video_driver_fd, + VDEC_IOCTL_SET_DISABLE_DMX); + if(rc < 0) { + DEBUG_PRINT_ERROR("Failed to disable dmx on driver."); + drv_ctx.disable_dmx = false; + eRet = OMX_ErrorHardware; + } + } + else { + drv_ctx.disable_dmx = false; + } + } + } + if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + if (m_frame_parser.mutils == NULL) + { + m_frame_parser.mutils = new H264_Utils(); + + if (m_frame_parser.mutils == NULL) + { + DEBUG_PRINT_ERROR("\n parser utils Allocation failed "); + eRet = OMX_ErrorInsufficientResources; + } + else + { + h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size - DEVICE_SCRATCH; + h264_scratch.pBuffer = (OMX_U8 *)malloc (h264_scratch.nAllocLen); + h264_scratch.nFilledLen = 0; + h264_scratch.nOffset = 0; + + if (h264_scratch.pBuffer == NULL) + { + DEBUG_PRINT_ERROR("\n h264_scratch.pBuffer Allocation failed "); + return OMX_ErrorInsufficientResources; + } + m_frame_parser.mutils->initialize_frame_checking_environment(); + m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size); + } + } + + h264_parser = new h264_stream_parser(); + if (!h264_parser) + { + DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!"); + eRet = OMX_ErrorInsufficientResources; + } + } + + if(pipe(fds)) + { + DEBUG_PRINT_ERROR("\n pipe creation failed."); + eRet = OMX_ErrorInsufficientResources; + } + else + { + int temp1[2]; + if(fds[0] == 0 || fds[1] == 0) + { + if (pipe (temp1)) + { + DEBUG_PRINT_ERROR("\n pipe creation failed.."); + return OMX_ErrorInsufficientResources; + } + //close (fds[0]); + //close (fds[1]); + fds[0] = temp1 [0]; + fds[1] = temp1 [1]; + } + m_pipe_in = fds[0]; + m_pipe_out = fds[1]; + r = pthread_create(&msg_thread_id,0,message_thread,this); + + if(r < 0) + { + DEBUG_PRINT_ERROR("\n component_init(): message_thread creation failed"); + eRet = OMX_ErrorInsufficientResources; + } + else + { + r = pthread_create(&async_thread_id,0,async_message_thread,this); + if(r < 0) + { + DEBUG_PRINT_ERROR("\n component_init(): async_message_thread creation failed"); + eRet = OMX_ErrorInsufficientResources; + } + } + } + } + + if (eRet != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n Component Init Failed"); + DEBUG_PRINT_HIGH("Calling VDEC_IOCTL_STOP_NEXT_MSG"); + (void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG, + NULL); + DEBUG_PRINT_HIGH("Calling close() on Video Driver"); + close (drv_ctx.video_driver_fd); + drv_ctx.video_driver_fd = -1; + } + else + { + DEBUG_PRINT_HIGH("omx_vdec::component_init() success"); + } + + memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer)); + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::GetComponentVersion + +DESCRIPTION + Returns the component version. + +PARAMETERS + TBD. + +RETURN VALUE + OMX_ErrorNone. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::get_component_version + ( + OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STRING componentName, + OMX_OUT OMX_VERSIONTYPE* componentVersion, + OMX_OUT OMX_VERSIONTYPE* specVersion, + OMX_OUT OMX_UUIDTYPE* componentUUID + ) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\n Get Comp Version in Invalid State"); + return OMX_ErrorInvalidState; + } + /* TBD -- Return the proper version */ + if (specVersion) + { + specVersion->nVersion = OMX_SPEC_VERSION; + } + return OMX_ErrorNone; +} +/* ====================================================================== +FUNCTION + omx_vdec::SendCommand + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData + ) +{ + DEBUG_PRINT_HIGH("send_command: Recieved a Command from Client"); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\n ERROR: Send Command in Invalid State"); + return OMX_ErrorInvalidState; + } + if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX + && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) + { + DEBUG_PRINT_ERROR("\n send_command(): ERROR OMX_CommandFlush " + "to invalid port: %d", param1); + return OMX_ErrorBadPortIndex; + } + post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); + sem_wait(&m_cmd_lock); + DEBUG_PRINT_HIGH("send_command: Command Processed"); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::SendCommand + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData + ) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_STATETYPE eState = (OMX_STATETYPE) param1; + int bFlag = 1,sem_posted = 0; + + DEBUG_PRINT_HIGH("send_command_proxy(): cmd = %d, Current State %d, Expected State %d", + cmd, m_state, eState); + + if(cmd == OMX_CommandStateSet) + { + DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued"); + DEBUG_PRINT_HIGH("Current State %d, Expected State %d", m_state, eState); + /***************************/ + /* Current State is Loaded */ + /***************************/ + if(m_state == OMX_StateLoaded) + { + if(eState == OMX_StateIdle) + { + //if all buffers are allocated or all ports disabled + if(allocate_done() || + (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) + { + DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle"); + } + else + { + DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending"); + BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + /* Requesting transition from Loaded to Loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("\n ERROR::send_command_proxy(): Loaded-->Loaded"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Loaded to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources"); + } + /* Requesting transition from Loaded to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Loaded to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Loaded to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)\n",\ + eState); + eRet = OMX_ErrorBadParameter; + } + } + + /***************************/ + /* Current State is IDLE */ + /***************************/ + else if(m_state == OMX_StateIdle) + { + if(eState == OMX_StateLoaded) + { + if(release_done()) + { + /* + Since error is None , we will post an event at the end + of this function definition + */ + DEBUG_PRINT_HIGH("send_command_proxy(): Idle-->Loaded"); + } + else + { + DEBUG_PRINT_HIGH("send_command_proxy(): Idle-->Loaded-Pending"); + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); + // Skip the event notification + bFlag = 0; + } + } + /* Requesting transition from Idle to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_HIGH("send_command_proxy(): Idle-->Executing"); + BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING); + bFlag = 0; + if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START, + NULL) < 0) + { + DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_START FAILED"); + omx_report_error (); + eRet = OMX_ErrorHardware; + } + } + /* Requesting transition from Idle to Idle */ + else if(eState == OMX_StateIdle) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle\n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Idle to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Idle to Pause */ + else if(eState == OMX_StatePause) + { + /*To pause the Video core we need to start the driver*/ + if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START, + NULL) < 0) + { + DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_START FAILED"); + omx_report_error (); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); + DEBUG_PRINT_HIGH("send_command_proxy(): Idle-->Pause"); + bFlag = 0; + } + } + /* Requesting transition from Idle to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /******************************/ + /* Current State is Executing */ + /******************************/ + else if(m_state == OMX_StateExecuting) + { + DEBUG_PRINT_HIGH("Command Recieved in OMX_StateExecuting"); + /* Requesting transition from Executing to Idle */ + if(eState == OMX_StateIdle) + { + /* Since error is None , we will post an event + at the end of this function definition + */ + DEBUG_PRINT_HIGH("send_command_proxy(): Executing --> Idle"); + BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); + if(!sem_posted) + { + sem_posted = 1; + sem_post (&m_cmd_lock); + execute_omx_flush(OMX_ALL); + } + bFlag = 0; + } + /* Requesting transition from Executing to Paused */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_HIGH("PAUSE Command Issued"); + if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_PAUSE, + NULL) < 0) + { + DEBUG_PRINT_ERROR("\n Error In Pause State"); + post_event(OMX_EventError,OMX_ErrorHardware,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); + DEBUG_PRINT_HIGH("send_command_proxy(): Executing-->Pause"); + bFlag = 0; + } + } + /* Requesting transition from Executing to Loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Loaded \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Executing to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> WaitForResources \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Executing to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Executing \n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Executing to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Invalid \n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is Pause */ + /***************************/ + else if(m_state == OMX_StatePause) + { + /* Requesting transition from Pause to Executing */ + if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_HIGH("Pause --> Executing"); + if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_RESUME, + NULL) < 0) + { + DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_RESUME failed"); + post_event(OMX_EventError,OMX_ErrorHardware,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING); + DEBUG_PRINT_HIGH("send_command_proxy(): Idle-->Executing"); + post_event (NULL,VDEC_S_SUCCESS,\ + OMX_COMPONENT_GENERATE_RESUME_DONE); + bFlag = 0; + } + } + /* Requesting transition from Pause to Idle */ + else if(eState == OMX_StateIdle) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_HIGH("Pause --> Idle.."); + BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); + if(!sem_posted) + { + sem_posted = 1; + sem_post (&m_cmd_lock); + execute_omx_flush(OMX_ALL); + } + bFlag = 0; + } + /* Requesting transition from Pause to loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("\n Pause --> loaded \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Pause to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("\n Pause --> WaitForResources \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Pause to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("\n Pause --> Pause \n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Pause to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\n Pause --> Invalid \n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is WaitForResources */ + /***************************/ + else if(m_state == OMX_StateWaitForResources) + { + /* Requesting transition from WaitForResources to Loaded */ + if(eState == OMX_StateLoaded) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_HIGH("send_command_proxy(): WaitForResources-->Loaded"); + } + /* Requesting transition from WaitForResources to WaitForResources */ + else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources\n"); + post_event(OMX_EventError,OMX_ErrorSameState, + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from WaitForResources to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from WaitForResources to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from WaitForResources to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + /* Requesting transition from WaitForResources to Loaded - + is NOT tested by Khronos TS */ + + } + else + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)\n",m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } + /********************************/ + /* Current State is Invalid */ + /*******************************/ + else if(m_state == OMX_StateInvalid) + { + /* State Transition from Inavlid to any state */ + if(eState == (OMX_StateLoaded || OMX_StateWaitForResources + || OMX_StateIdle || OMX_StateExecuting + || OMX_StatePause || OMX_StateInvalid)) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded\n"); + post_event(OMX_EventError,OMX_ErrorInvalidState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + } + else if (cmd == OMX_CommandFlush) + { + DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued " + "with param1: %d", param1); + if(OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); + } + if(OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) + { + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING); + } + if (!sem_posted){ + sem_posted = 1; + DEBUG_PRINT_LOW("Set the Semaphore"); + sem_post (&m_cmd_lock); + execute_omx_flush(param1); + } + bFlag = 0; + } + else if ( cmd == OMX_CommandPortEnable) + { + DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued " + "with param1: %d", param1); + if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) + { + m_inp_bEnabled = OMX_TRUE; + + if( (m_state == OMX_StateLoaded && + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || allocate_input_done()) + { + post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + DEBUG_PRINT_HIGH("send_command_proxy(): Disabled-->Enabled Pending"); + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + DEBUG_PRINT_HIGH("Enable output Port command recieved"); + m_out_bEnabled = OMX_TRUE; + + if( (m_state == OMX_StateLoaded && + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (allocate_output_done())) + { + post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + } + else + { + DEBUG_PRINT_HIGH("send_command_proxy(): Disabled-->Enabled Pending"); + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + } + else if (cmd == OMX_CommandPortDisable) + { + DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued " + "with param1: %d", param1); + if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) + { + m_inp_bEnabled = OMX_FALSE; + if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_input_done()) + { + post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); + if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + if(!sem_posted) + { + sem_posted = 1; + sem_post (&m_cmd_lock); + } + execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX); + } + + // Skip the event notification + bFlag = 0; + } + } + if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + m_out_bEnabled = OMX_FALSE; + DEBUG_PRINT_HIGH("Disable output Port command recieved"); + if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_output_done()) + { + post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\ + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + if (!sem_posted) + { + sem_posted = 1; + sem_post (&m_cmd_lock); + } + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); + execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX); + } + // Skip the event notification + bFlag = 0; + + } + } + } + else + { + DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)\n",cmd); + eRet = OMX_ErrorNotImplemented; + } + if(eRet == OMX_ErrorNone && bFlag) + { + post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); + } + if(!sem_posted) + { + sem_post(&m_cmd_lock); + } + + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::ExecuteOmxFlush + +DESCRIPTION + Executes the OMX flush. + +PARAMETERS + flushtype - input flush(1)/output flush(0)/ both. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_vdec::execute_omx_flush(OMX_U32 flushType) +{ + struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; + enum vdec_bufferflush flush_dir; + bool bRet = false; + switch (flushType) + { + case OMX_CORE_INPUT_PORT_INDEX: + input_flush_progress = true; + flush_dir = VDEC_FLUSH_TYPE_INPUT; + break; + case OMX_CORE_OUTPUT_PORT_INDEX: + output_flush_progress = true; + flush_dir = VDEC_FLUSH_TYPE_OUTPUT; + break; + default: + input_flush_progress = true; + output_flush_progress = true; + flush_dir = VDEC_FLUSH_TYPE_ALL; + } + ioctl_msg.in = &flush_dir; + ioctl_msg.out = NULL; + if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_CMD_FLUSH, &ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n Flush Port (%d) Failed ", (int)flush_dir); + bRet = false; + } + return bRet; +} +/*========================================================================= +FUNCTION : execute_output_flush + +DESCRIPTION + Executes the OMX flush at OUTPUT PORT. + +PARAMETERS + None. + +RETURN VALUE + true/false +==========================================================================*/ +bool omx_vdec::execute_output_flush() +{ + unsigned p1 = 0; // Parameter - 1 + unsigned p2 = 0; // Parameter - 2 + unsigned ident = 0; + bool bRet = true; + + /*Generate FBD for all Buffers in the FTBq*/ + pthread_mutex_lock(&m_lock); + DEBUG_PRINT_HIGH("Initiate Output Flush"); + while (m_ftb_q.m_size) + { + DEBUG_PRINT_HIGH("Buffer queue size %d pending buf cnt %d", + m_ftb_q.m_size,pending_output_buffers); + m_ftb_q.pop_entry(&p1,&p2,&ident); + DEBUG_PRINT_HIGH("ID(%x) P1(%x) P2(%x)", ident, p1, p2); + if(ident == OMX_COMPONENT_GENERATE_FTB ) + { + pending_output_buffers++; + fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); + } + else if (ident == OMX_COMPONENT_GENERATE_FBD) + { + fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); + } + } + pthread_mutex_unlock(&m_lock); + output_flush_progress = false; + + if (arbitrary_bytes) + { + prev_ts = LLONG_MAX; + rst_prev_ts = true; + } + DEBUG_PRINT_HIGH("OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers); + return bRet; +} +/*========================================================================= +FUNCTION : execute_input_flush + +DESCRIPTION + Executes the OMX flush at INPUT PORT. + +PARAMETERS + None. + +RETURN VALUE + true/false +==========================================================================*/ +bool omx_vdec::execute_input_flush() +{ + unsigned i =0; + unsigned p1 = 0; // Parameter - 1 + unsigned p2 = 0; // Parameter - 2 + unsigned ident = 0; + bool bRet = true; + + /*Generate EBD for all Buffers in the ETBq*/ + DEBUG_PRINT_HIGH("Initiate Input Flush"); + + pthread_mutex_lock(&m_lock); + DEBUG_PRINT_LOW("Check if the Queue is empty"); + while (m_etb_q.m_size) + { + m_etb_q.pop_entry(&p1,&p2,&ident); + + if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) + { + DEBUG_PRINT_HIGH("Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2); + m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2); + } + else if(ident == OMX_COMPONENT_GENERATE_ETB) + { + pending_input_buffers++; + DEBUG_PRINT_HIGH("Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d", + (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers); + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); + } + else if (ident == OMX_COMPONENT_GENERATE_EBD) + { + DEBUG_PRINT_HIGH("Flush Input OMX_COMPONENT_GENERATE_EBD %p", + (OMX_BUFFERHEADERTYPE *)p1); + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); + } + } + time_stamp_dts.flush_timestamp(); + /*Check if Heap Buffers are to be flushed*/ + if (arbitrary_bytes && !(codec_config_flag)) + { + DEBUG_PRINT_HIGH("Reset all the variables before flusing"); + h264_scratch.nFilledLen = 0; + nal_count = 0; + look_ahead_nal = false; + frame_count = 0; + h264_last_au_ts = LLONG_MAX; + h264_last_au_flags = 0; + memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); + m_demux_entries = 0; + DEBUG_PRINT_HIGH("Initialize parser"); + if (m_frame_parser.mutils) + { + m_frame_parser.mutils->initialize_frame_checking_environment(); + } + + while (m_input_pending_q.m_size) + { + m_input_pending_q.pop_entry(&p1,&p2,&ident); + m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1); + } + + if (psource_frame) + { + m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame); + psource_frame = NULL; + } + + if (pdest_frame) + { + pdest_frame->nFilledLen = 0; + m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL); + pdest_frame = NULL; + } + m_frame_parser.flush(); + } + else if (codec_config_flag) + { + DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer " + "is not sent to the driver yet"); + } + pthread_mutex_unlock(&m_lock); + input_flush_progress = false; + if (!arbitrary_bytes) + { + prev_ts = LLONG_MAX; + rst_prev_ts = true; + } +#ifdef _ANDROID_ + if (m_debug_timestamp) + { + m_timestamp_list.reset_ts_list(); + } +#endif + DEBUG_PRINT_HIGH("OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers); + return bRet; +} + + +/* ====================================================================== +FUNCTION + omx_vdec::SendCommandEvent + +DESCRIPTION + Send the event to decoder pipe. This is needed to generate the callbacks + in decoder thread context. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_vdec::post_event(unsigned int p1, + unsigned int p2, + unsigned int id) +{ + bool bRet = false; + + + pthread_mutex_lock(&m_lock); + + if (id == OMX_COMPONENT_GENERATE_FTB || + id == OMX_COMPONENT_GENERATE_FBD) + { + m_ftb_q.insert_entry(p1,p2,id); + } + else if (id == OMX_COMPONENT_GENERATE_ETB || + id == OMX_COMPONENT_GENERATE_EBD || + id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) + { + m_etb_q.insert_entry(p1,p2,id); + } + else + { + m_cmd_q.insert_entry(p1,p2,id); + } + + bRet = true; + DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this); + post_message(this, id); + + pthread_mutex_unlock(&m_lock); + + return bRet; +} +#ifdef MAX_RES_720P +OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_720p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(!profileLevelType) + return OMX_ErrorBadParameter; + + if(profileLevelType->nPortIndex == 0) { + if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; + + } + else if (profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; + } + else if(profileLevelType->nProfileIndex == 2) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; + } + else + { + DEBUG_PRINT_HIGH("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d", + profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_H263Level70; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else if(profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n", profileLevelType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + return eRet; +} +#endif +#ifdef MAX_RES_1080P +OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(!profileLevelType) + return OMX_ErrorBadParameter; + + if(profileLevelType->nPortIndex == 0) { + if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + + } + else if (profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + } + else if(profileLevelType->nProfileIndex == 2) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + } + else + { + DEBUG_PRINT_HIGH("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d", + profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_H263Level70; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else if(profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; + } + else if(profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain; + profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n", profileLevelType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + return eRet; +} +#endif + +/* ====================================================================== +FUNCTION + omx_vdec::GetParameter + +DESCRIPTION + OMX Get Parameter method implementation + +PARAMETERS + . + +RETURN VALUE + Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_INOUT OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + DEBUG_PRINT_LOW("get_parameter:"); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(paramData == NULL) + { + DEBUG_PRINT_ERROR("\n Get Param in Invalid paramData"); + return OMX_ErrorBadParameter; + } + switch(paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn = + (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + eRet = update_portdef(portDefn); + if (eRet == OMX_ErrorNone) + m_port_def = *portDefn; + DEBUG_PRINT_LOW("Get_parameter: OMX_IndexParamPortDefinition: " + "nPortIndex (%d), nFrameWidth (%d), nFrameHeight (%d), " + "nStride (%d), nSliceHeight (%d), nBitrate (%d), xFramerate (0x%x), " + "nBufferSize (%d), nBufferCountMin (%d), nBufferCountActual (%d), " + "bBuffersContiguous (%d), nBufferAlignment (%d), " + "bEnabled (%d), bPopulated (%d), eCompressionFormat (0x%x), " + "eColorFormat (0x%x)" , (int)portDefn->nPortIndex, + (int)portDefn->format.video.nFrameWidth, (int)portDefn->format.video.nFrameHeight, + (int)portDefn->format.video.nStride, (int)portDefn->format.video.nSliceHeight, + (int)portDefn->format.video.nBitrate, (int)portDefn->format.video.xFramerate, + (int)portDefn->nBufferSize, (int)portDefn->nBufferCountMin, + (int)portDefn->nBufferCountActual, (int)portDefn->bBuffersContiguous, + (int)portDefn->nBufferAlignment, (int)portDefn->bEnabled, (int)portDefn->bPopulated, + (int)portDefn->format.video.eCompressionFormat, (int)portDefn->format.video.eColorFormat); + break; + } + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n"); + + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = sizeof(portParamType); + portParamType->nPorts = 2; + portParamType->nStartPortNumber = 0; + break; + } + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = + (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; + portFmt->nVersion.nVersion = OMX_SPEC_VERSION; + portFmt->nSize = sizeof(portFmt); + + if (0 == portFmt->nPortIndex) + { + if (0 == portFmt->nIndex) + { + portFmt->eColorFormat = OMX_COLOR_FormatUnused; + portFmt->eCompressionFormat = eCompressionFormat; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\ + " NoMore compression formats\n"); + eRet = OMX_ErrorNoMore; + } + } + else if (1 == portFmt->nPortIndex) + { + portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused; + if(0 == portFmt->nIndex) + portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE) + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; + else + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\ + " NoMore Color formats\n"); + eRet = OMX_ErrorNoMore; + } + } + else + { + DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n", + (int)portFmt->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_LOW("Get_parameter: OMX_IndexParamVideoPortFormat: " + "nPortIndex (%d), nIndex (%d), eCompressionFormat (0x%x), " + "eColorFormat (0x%x), xFramerate (0x%x)", (int)portFmt->nPortIndex, + (int)portFmt->nIndex, (int)portFmt->eCompressionFormat, + (int)portFmt->eColorFormat, (int)portFmt->xFramerate); + break; + } + /*Component should support this port definition*/ + case OMX_IndexParamAudioInit: + { + OMX_PORT_PARAM_TYPE *audioPortParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit\n"); + audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION; + audioPortParamType->nSize = sizeof(audioPortParamType); + audioPortParamType->nPorts = 0; + audioPortParamType->nStartPortNumber = 0; + break; + } + /*Component should support this port definition*/ + case OMX_IndexParamImageInit: + { + OMX_PORT_PARAM_TYPE *imagePortParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit\n"); + imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION; + imagePortParamType->nSize = sizeof(imagePortParamType); + imagePortParamType->nPorts = 0; + imagePortParamType->nStartPortNumber = 0; + break; + + } + /*Component should support this port definition*/ + case OMX_IndexParamOtherInit: + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x\n", + paramIndex); + eRet =OMX_ErrorUnsupportedIndex; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *comp_role; + comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; + comp_role->nVersion.nVersion = OMX_SPEC_VERSION; + comp_role->nSize = sizeof(*comp_role); + + DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d\n", + paramIndex); + strlcpy((char*)comp_role->cRole,(const char*)m_cRole, + OMX_MAX_STRINGNAME_SIZE); + break; + } + /* Added for parameter test */ + case OMX_IndexParamPriorityMgmt: + { + + OMX_PRIORITYMGMTTYPE *priorityMgmType = + (OMX_PRIORITYMGMTTYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n"); + priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION; + priorityMgmType->nSize = sizeof(priorityMgmType); + + break; + } + /* Added for parameter test */ + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = + (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n"); + + bufferSupplierType->nSize = sizeof(bufferSupplierType); + bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; + if(0 == bufferSupplierType->nPortIndex) + bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; + else if (1 == bufferSupplierType->nPortIndex) + bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; + else + eRet = OMX_ErrorBadPortIndex; + + + break; + } + case OMX_IndexParamVideoAvc: + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x\n", + paramIndex); + break; + } + case OMX_IndexParamVideoH263: + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x\n", + paramIndex); + break; + } + case OMX_IndexParamVideoMpeg4: + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x\n", + paramIndex); + break; + } + case OMX_IndexParamVideoMpeg2: + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x\n", + paramIndex); + break; + } + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x\n", paramIndex); + OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType = + (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData; +#ifdef MAX_RES_720P + eRet = get_supported_profile_level_for_720p(profileLevelType); +#endif +#ifdef MAX_RES_1080P + eRet = get_supported_profile_level_for_1080p(profileLevelType); +#endif + break; + } +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) + case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: + { + DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage"); + GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData; + if(nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { +#ifdef USE_ION +#if defined (MAX_RES_720P) + nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_CAMERA_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED); + DEBUG_PRINT_HIGH("ION:720P: nUsage 0x%x",nativeBuffersUsage->nUsage); +#else + if(secure_mode) { + nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED | + GRALLOC_USAGE_PRIVATE_CP_BUFFER | GRALLOC_USAGE_PRIVATE_UNCACHED); + DEBUG_PRINT_HIGH("ION:secure_mode: nUsage 0x%x",nativeBuffersUsage->nUsage); + } else { + nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | + GRALLOC_USAGE_PRIVATE_IOMMU_HEAP); + DEBUG_PRINT_HIGH("ION:non_secure_mode: nUsage 0x%x",nativeBuffersUsage->nUsage); + } +#endif //(MAX_RES_720P) +#else // USE_ION +#if defined (MAX_RES_720P) || defined (MAX_RES_1080P_EBI) + nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_ADSP_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED); + DEBUG_PRINT_HIGH("720P/1080P_EBI: nUsage 0x%x",nativeBuffersUsage->nUsage); +#elif MAX_RES_1080P + nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_SMI_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED); + DEBUG_PRINT_HIGH("1080P: nUsage 0x%x",nativeBuffersUsage->nUsage); +#endif +#endif // USE_ION + } else { + DEBUG_PRINT_ERROR("\n get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!"); + eRet = OMX_ErrorBadParameter; + } + } + break; +#endif + + default: + { + DEBUG_PRINT_ERROR("get_parameter: unknown param %08x\n", paramIndex); + eRet =OMX_ErrorUnsupportedIndex; + } + + } + + DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)", + drv_ctx.video_resolution.frame_width, + drv_ctx.video_resolution.frame_height, + drv_ctx.video_resolution.stride, + drv_ctx.video_resolution.scan_lines); + + return eRet; +} + +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) +OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data) +{ + DEBUG_PRINT_LOW("Inside use_android_native_buffer"); + OMX_ERRORTYPE eRet = OMX_ErrorNone; + UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data; + + if((params == NULL) || + (params->nativeBuffer == NULL) || + (params->nativeBuffer->handle == NULL) || + !m_enable_android_native_buffers) + return OMX_ErrorBadParameter; + m_use_android_native_buffers = OMX_TRUE; + sp nBuf = params->nativeBuffer; + private_handle_t *handle = (private_handle_t *)nBuf->handle; + + if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) { + DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback," + " expected %u, got %lu", + drv_ctx.op_buf.buffer_size, (OMX_U32)handle->size); + return OMX_ErrorBadParameter; + } + + if(OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port + OMX_U8 *buffer = NULL; + if(!secure_mode) { + buffer = (OMX_U8*)mmap(0, handle->size, + PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); + if(buffer == MAP_FAILED) { + DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); + return OMX_ErrorInsufficientResources; + } + } + eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer); + } else { + eRet = OMX_ErrorBadParameter; + } + return eRet; +} +#endif +/* ====================================================================== +FUNCTION + omx_vdec::Setparameter + +DESCRIPTION + OMX Set Parameter method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_IN OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Set Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(paramData == NULL) + { + DEBUG_PRINT_ERROR("Get Param in Invalid paramData \n"); + return OMX_ErrorBadParameter; + } + if((m_state != OMX_StateLoaded) && + BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) && + (m_out_bEnabled == OMX_TRUE) && + BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) && + (m_inp_bEnabled == OMX_TRUE)) { + DEBUG_PRINT_ERROR("Set Param in Invalid State \n"); + return OMX_ErrorIncorrectStateOperation; + } + + switch(paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has + //been called. + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d", + (int)portDefn->format.video.nFrameHeight, + (int)portDefn->format.video.nFrameWidth); + if(OMX_DirOutput == portDefn->eDir) + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port"); + m_display_id = portDefn->format.video.pNativeWindow; + if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount && + portDefn->nBufferSize >= drv_ctx.op_buf.buffer_size ) + { + drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual; + drv_ctx.op_buf.buffer_size = portDefn->nBufferSize; + eRet = set_buffer_req(&drv_ctx.op_buf); + if (eRet == OMX_ErrorNone) + m_port_def = *portDefn; + } + else + { + DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%d: %u)\n", + drv_ctx.op_buf.mincount, drv_ctx.op_buf.buffer_size, + portDefn->nBufferCountActual, portDefn->nBufferSize); + eRet = OMX_ErrorBadParameter; + } + } + else if(OMX_DirInput == portDefn->eDir) + { + if((portDefn->format.video.xFramerate >> 16) > 0 && + (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) + { + // Frame rate only should be set if this is a "known value" or to + // activate ts prediction logic (arbitrary mode only) sending input + // timestamps with max value (LLONG_MAX). + DEBUG_PRINT_LOW("set_parameter: frame rate set by omx client : %d", + portDefn->format.video.xFramerate >> 16); + Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator, + drv_ctx.frame_rate.fps_denominator); + if(!drv_ctx.frame_rate.fps_numerator) + { + DEBUG_PRINT_ERROR("Numerator is zero setting to 30"); + drv_ctx.frame_rate.fps_numerator = 30; + } + if(drv_ctx.frame_rate.fps_denominator) + drv_ctx.frame_rate.fps_numerator = (int) + drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator; + drv_ctx.frame_rate.fps_denominator = 1; + frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 / + drv_ctx.frame_rate.fps_numerator; + ioctl_msg.in = &drv_ctx.frame_rate; + if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_FRAME_RATE, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("Setting frame rate to driver failed"); + } + DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)", + frm_int, drv_ctx.frame_rate.fps_numerator / + (float)drv_ctx.frame_rate.fps_denominator); + } + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port"); + if(drv_ctx.video_resolution.frame_height != + portDefn->format.video.nFrameHeight || + drv_ctx.video_resolution.frame_width != + portDefn->format.video.nFrameWidth) + { + DEBUG_PRINT_LOW("SetParam IP: WxH(%d x %d)", + portDefn->format.video.nFrameWidth, + portDefn->format.video.nFrameHeight); + if (portDefn->format.video.nFrameHeight != 0x0 && + portDefn->format.video.nFrameWidth != 0x0) + { + drv_ctx.video_resolution.frame_height = + drv_ctx.video_resolution.scan_lines = + portDefn->format.video.nFrameHeight; + drv_ctx.video_resolution.frame_width = + drv_ctx.video_resolution.stride = + portDefn->format.video.nFrameWidth; + ioctl_msg.in = &drv_ctx.video_resolution; + ioctl_msg.out = NULL; + if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_PICRES, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n Set Resolution failed"); + eRet = OMX_ErrorUnsupportedSetting; + } + else + eRet = get_buffer_req(&drv_ctx.op_buf); + } + } + else if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount + && portDefn->nBufferSize == (drv_ctx.ip_buf.buffer_size - DEVICE_SCRATCH)) + { + drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual; + drv_ctx.ip_buf.buffer_size = portDefn->nBufferSize + DEVICE_SCRATCH; + eRet = set_buffer_req(&drv_ctx.ip_buf); + } + else + { + DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%d: %u)\n", + drv_ctx.ip_buf.mincount, drv_ctx.ip_buf.buffer_size, + portDefn->nBufferCountActual, portDefn->nBufferSize); + eRet = OMX_ErrorBadParameter; + } + } + else if (portDefn->eDir == OMX_DirMax) + { + DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d", + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_HIGH("Set_parameter: OMX_IndexParamPortDefinition: " + "nPortIndex (%d), nFrameWidth (%d), nFrameHeight (%d), " + "nStride (%d), nSliceHeight (%d), nBitrate (%d), xFramerate (0x%x), " + "nBufferSize (%d), nBufferCountMin (%d), nBufferCountActual (%d), " + "bBuffersContiguous (%d), nBufferAlignment (%d), " + "bEnabled (%d), bPopulated (%d), eCompressionFormat (0x%x), " + "eColorFormat (0x%x)" , (int)portDefn->nPortIndex, + (int)portDefn->format.video.nFrameWidth, (int)portDefn->format.video.nFrameHeight, + (int)portDefn->format.video.nStride, (int)portDefn->format.video.nSliceHeight, + (int)portDefn->format.video.nBitrate, (int)portDefn->format.video.xFramerate, + (int)portDefn->nBufferSize, (int)portDefn->nBufferCountMin, + (int)portDefn->nBufferCountActual, (int)portDefn->bBuffersContiguous, + (int)portDefn->nBufferAlignment, (int)portDefn->bEnabled, (int)portDefn->bPopulated, + (int)portDefn->format.video.eCompressionFormat, (int)portDefn->format.video.eColorFormat); + } + break; + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = + (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; + if(1 == portFmt->nPortIndex) + { + enum vdec_output_fromat op_format; + if(portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) + op_format = VDEC_YUV_FORMAT_NV12; + else if(portFmt->eColorFormat == + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka) + op_format = VDEC_YUV_FORMAT_TILE_4x2; + else + eRet = OMX_ErrorBadParameter; + + if(eRet == OMX_ErrorNone && drv_ctx.output_format != op_format) + { + /*Set the output format*/ + drv_ctx.output_format = op_format; + ioctl_msg.in = &drv_ctx.output_format; + ioctl_msg.out = NULL; + if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_SET_OUTPUT_FORMAT, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n Set output format failed"); + eRet = OMX_ErrorUnsupportedSetting; + } + else + eRet = get_buffer_req(&drv_ctx.op_buf); + } + } + DEBUG_PRINT_HIGH("Set_parameter: OMX_IndexParamVideoPortFormat: " + "nPortIndex (%d), nIndex (%d), eCompressionFormat (0x%x), " + "eColorFormat (0x%x), xFramerate (0x%x)", (int)portFmt->nPortIndex, + (int)portFmt->nIndex, (int)portFmt->eCompressionFormat, + (int)portFmt->eColorFormat, (int)portFmt->xFramerate); + } + break; + + case OMX_QcomIndexPortDefn: + { + OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt = + (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %d", + portFmt->nFramePackingFormat); + + /* Input port */ + if (portFmt->nPortIndex == 0) + { + if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) + { + if(secure_mode) { + arbitrary_bytes = false; + DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode in secure session"); + eRet = OMX_ErrorUnsupportedSetting; + } else { + arbitrary_bytes = true; + DEBUG_PRINT_HIGH("setparameter: arbitrary_bytes enabled"); + } + } + else if (portFmt->nFramePackingFormat == + OMX_QCOM_FramePacking_OnlyOneCompleteFrame) + { + arbitrary_bytes = false; + DEBUG_PRINT_HIGH("setparameter: arbitrary_bytes disabled"); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %d\n", + portFmt->nFramePackingFormat); + eRet = OMX_ErrorUnsupportedSetting; + } + } + else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) + { + DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port"); + if( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid && + portFmt->nMemRegion < OMX_QCOM_MemRegionMax) && + portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) + { + m_out_mem_region_smi = OMX_TRUE; + if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) + { + DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: set use_output_pmem"); + m_use_output_pmem = OMX_TRUE; + } + } + } + } + break; + + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *comp_role; + comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s", + comp_role->cRole); + + if((m_state == OMX_StateLoaded)&& + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + DEBUG_PRINT_LOW("Set Parameter called in valid state"); + } + else + { + DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + + if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((char*)comp_role->cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet =OMX_ErrorUnsupportedSetting; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet = OMX_ErrorUnsupportedSetting; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((const char*)comp_role->cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet =OMX_ErrorUnsupportedSetting; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet = OMX_ErrorUnsupportedSetting; + } + } +#ifdef MAX_RES_1080P + else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) || + (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE)) + ) +#else + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) +#endif + { + if(!strncmp((const char*)comp_role->cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet =OMX_ErrorUnsupportedSetting; + } + } + else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) || + (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE)) + ) + { + if(!strncmp((const char*)comp_role->cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet =OMX_ErrorUnsupportedSetting; + } + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown param %s\n", drv_ctx.kind); + eRet = OMX_ErrorInvalidComponentName; + } + break; + } + + case OMX_IndexParamPriorityMgmt: + { + if(m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %d\n", + priorityMgmtype->nGroupID); + + DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %d\n", + priorityMgmtype->nGroupPriority); + + m_priority_mgm.nGroupID = priorityMgmtype->nGroupID; + m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority; + + break; + } + + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d\n", + bufferSupplierType->eBufferSupplier); + if(bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1) + m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier; + + else + + eRet = OMX_ErrorBadPortIndex; + + break; + + } + case OMX_IndexParamVideoAvc: + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d\n", + paramIndex); + break; + } + case OMX_IndexParamVideoH263: + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d\n", + paramIndex); + break; + } + case OMX_IndexParamVideoMpeg4: + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d\n", + paramIndex); + break; + } + case OMX_IndexParamVideoMpeg2: + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d\n", + paramIndex); + break; + } + case OMX_QcomIndexParamVideoDecoderPictureOrder: + { + QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder = + (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData; + enum vdec_output_order pic_order = VDEC_ORDER_DISPLAY; + DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d\n", + pictureOrder->eOutputPictureOrder); + if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) + pic_order = VDEC_ORDER_DISPLAY; + else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER){ + pic_order = VDEC_ORDER_DECODE; + time_stamp_dts.set_timestamp_reorder_mode(false); + } + else + eRet = OMX_ErrorBadParameter; +#ifdef MAX_RES_720P + if (drv_ctx.idr_only_decoding) + { + if (pictureOrder->eOutputPictureOrder != QOMX_VIDEO_DECODE_ORDER) + { + DEBUG_PRINT_HIGH("only decode order is supported for thumbnail mode"); + eRet = OMX_ErrorBadParameter; + } + } +#endif + if (eRet == OMX_ErrorNone && pic_order != drv_ctx.picture_order) + { + drv_ctx.picture_order = pic_order; + ioctl_msg.in = &drv_ctx.picture_order; + ioctl_msg.out = NULL; + if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_SET_PICTURE_ORDER, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n Set picture order failed"); + eRet = OMX_ErrorUnsupportedSetting; + } + } + break; + } + case OMX_QcomIndexParamConcealMBMapExtraData: + if(!secure_mode) + eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, + ((QOMX_ENABLETYPE *)paramData)->bEnable); + else { + DEBUG_PRINT_ERROR("\n secure mode setting not supported"); + eRet = OMX_ErrorUnsupportedSetting; + } + break; + case OMX_QcomIndexParamFrameInfoExtraData: + { + if(!secure_mode) + eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, + ((QOMX_ENABLETYPE *)paramData)->bEnable); + else { + DEBUG_PRINT_ERROR("\n secure mode setting not supported"); + eRet = OMX_ErrorUnsupportedSetting; + } + break; + } + case OMX_QcomIndexParamInterlaceExtraData: + if(!secure_mode) + eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, + ((QOMX_ENABLETYPE *)paramData)->bEnable); + else { + DEBUG_PRINT_ERROR("\n secure mode setting not supported"); + eRet = OMX_ErrorUnsupportedSetting; + } + break; + case OMX_QcomIndexParamH264TimeInfo: + if(!secure_mode) + eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, + ((QOMX_ENABLETYPE *)paramData)->bEnable); + else { + DEBUG_PRINT_ERROR("\n secure mode setting not supported"); + eRet = OMX_ErrorUnsupportedSetting; + } + break; + case OMX_QcomIndexParamVideoDivx: + { +#ifdef MAX_RES_720P + QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData; + if((divXType) && (divXType->eFormat == QOMX_VIDEO_DIVXFormat311)) { + DEBUG_PRINT_HIGH("set_parameter: DivX 3.11 not supported in 7x30 core."); + eRet = OMX_ErrorUnsupportedSetting; + } +#endif + } + break; + case OMX_QcomIndexPlatformPvt: + { + DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port"); + OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData; + if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) + { + DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type); + eRet = OMX_ErrorUnsupportedSetting; + } + else + { + m_out_pvt_entry_pmem = OMX_TRUE; + if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) + { + DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: use output pmem set"); + m_use_output_pmem = OMX_TRUE; + } + } + + } + break; + case OMX_QcomIndexParamVideoSyncFrameDecodingMode: + { + DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode"); + DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode"); + drv_ctx.idr_only_decoding = 1; + int rc = ioctl(drv_ctx.video_driver_fd, + VDEC_IOCTL_SET_IDR_ONLY_DECODING); + if(rc < 0) { + DEBUG_PRINT_ERROR("Failed to set IDR only decoding on driver."); + eRet = OMX_ErrorHardware; + } +#ifdef MAX_RES_720P + if (eRet == OMX_ErrorNone) + { + DEBUG_PRINT_HIGH("set decode order for thumbnail mode"); + drv_ctx.picture_order = VDEC_ORDER_DECODE; + ioctl_msg.in = &drv_ctx.picture_order; + ioctl_msg.out = NULL; + if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_SET_PICTURE_ORDER, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n Set picture order failed"); + eRet = OMX_ErrorUnsupportedSetting; + } + } +#endif + } + break; +#ifdef MAX_RES_1080P + case OMX_QcomIndexParamIndexExtraDataType: + { + if(!secure_mode) { + QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData; + if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) && + (extradataIndexType->bEnabled == OMX_TRUE) && + (extradataIndexType->nPortIndex == 1)) + { + DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming"); + eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, extradataIndexType->bEnabled); + // Set smooth streaming parameter + int rc = ioctl(drv_ctx.video_driver_fd, + VDEC_IOCTL_SET_CONT_ON_RECONFIG); + if(rc < 0) { + DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver."); + eRet = OMX_ErrorHardware; + } + } + } + } + break; + + case OMX_QcomIndexParamEnableSmoothStreaming: + { + + int rc = ioctl(drv_ctx.video_driver_fd, + VDEC_IOCTL_SET_CONT_ON_RECONFIG); + if(rc < 0) { + DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver."); + eRet = OMX_ErrorHardware; + } + } + break; +#endif +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) + /* Need to allow following two set_parameters even in Idle + * state. This is ANDROID architecture which is not in sync + * with openmax standard. */ + case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: + { + EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData; + if(enableNativeBuffers) { + m_enable_android_native_buffers = enableNativeBuffers->enable; + } + } + break; + case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: + { + eRet = use_android_native_buffer(hComp, paramData); + } + break; +#endif + case OMX_QcomIndexParamEnableTimeStampReorder: + { + QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData; + if (drv_ctx.picture_order == QOMX_VIDEO_DISPLAY_ORDER) { + if (reorder->bEnable == OMX_TRUE) { + frm_int =0; + time_stamp_dts.set_timestamp_reorder_mode(true); + } + else + time_stamp_dts.set_timestamp_reorder_mode(false); + } else { + time_stamp_dts.set_timestamp_reorder_mode(false); + if (reorder->bEnable == OMX_TRUE) + { + eRet = OMX_ErrorUnsupportedSetting; + } + } + } + break; + default: + { + DEBUG_PRINT_ERROR("Setparameter: unknown param %d\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::GetConfig + +DESCRIPTION + OMX Get Config Method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_INOUT OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + switch (configIndex) + { + case OMX_QcomIndexConfigInterlaced: + { + OMX_QCOM_CONFIG_INTERLACETYPE *configFmt = + (OMX_QCOM_CONFIG_INTERLACETYPE *) configData; + if (configFmt->nPortIndex == 1) + { + if (configFmt->nIndex == 0) + { + configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive; + } + else if (configFmt->nIndex == 1) + { + configFmt->eInterlaceType = + OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; + } + else if (configFmt->nIndex == 2) + { + configFmt->eInterlaceType = + OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; + } + else + { + DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:" + " NoMore Interlaced formats\n"); + eRet = OMX_ErrorNoMore; + } + + } + else + { + DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port\n", + (int)configFmt->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_QcomIndexQueryNumberOfVideoDecInstance: + { + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances = + (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData; + ioctl_msg.out = (void*)&decoderinstances->nNumOfInstances; + (void)(ioctl(drv_ctx.video_driver_fd, + VDEC_IOCTL_GET_NUMBER_INSTANCES,&ioctl_msg)); + break; + } + case OMX_QcomIndexConfigVideoFramePackingArrangement: + { + if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt = + (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData; + h264_parser->get_frame_pack_data(configFmt); + } + else + { + DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs"); + } + break; + } + case OMX_QcomIndexParamFrameInfoExtraData: + { + OMX_QCOM_EXTRADATA_FRAMEINFO *extradata = + (OMX_QCOM_EXTRADATA_FRAMEINFO *) configData; + + if(m_extradata == NULL){ + DEBUG_PRINT_LOW("get_config: m_extradata not set. " + "Aspect Ratio information missing!!"); + } + else { + extradata->aspectRatio.aspectRatioX = + m_extradata->aspectRatio.aspectRatioX; + extradata->aspectRatio.aspectRatioY = + m_extradata->aspectRatio.aspectRatioY; + } + break; + } + + default: + { + DEBUG_PRINT_ERROR("get_config: unknown param %d\n",configIndex); + eRet = OMX_ErrorBadParameter; + } + + } + + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::SetConfig + +DESCRIPTION + OMX Set Config method implementation + +PARAMETERS + . + +RETURN VALUE + OMX Error None if successful. +========================================================================== */ +OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_IN OMX_PTR configData) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_VIDEO_CONFIG_NALSIZE *pNal; + + DEBUG_PRINT_LOW("Set Config Called"); + + if (m_state == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("set_config:Ignore in Exe state\n"); + return ret; + } + + if (configIndex == OMX_IndexVendorVideoExtraData) + { + OMX_VENDOR_EXTRADATATYPE *config = (OMX_VENDOR_EXTRADATATYPE *) configData; + DEBUG_PRINT_LOW("Index OMX_IndexVendorVideoExtraData called"); + if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc")) + { + DEBUG_PRINT_LOW("Index OMX_IndexVendorVideoExtraData AVC"); + OMX_U32 extra_size; + // Parsing done here for the AVC atom is definitely not generic + // Currently this piece of code is working, but certainly + // not tested with all .mp4 files. + // Incase of failure, we might need to revisit this + // for a generic piece of code. + + // Retrieve size of NAL length field + // byte #4 contains the size of NAL lenght field + nal_length = (config->pData[4] & 0x03) + 1; + + extra_size = 0; + if (nal_length > 2) + { + /* Presently we assume that only one SPS and one PPS in AvC1 Atom */ + extra_size = (nal_length - 2) * 2; + } + + // SPS starts from byte #6 + OMX_U8 *pSrcBuf = (OMX_U8 *) (&config->pData[6]); + OMX_U8 *pDestBuf; + m_vendor_config.nPortIndex = config->nPortIndex; + + // minus 6 --> SPS starts from byte #6 + // minus 1 --> picture param set byte to be ignored from avcatom + m_vendor_config.nDataSize = config->nDataSize - 6 - 1 + extra_size; + m_vendor_config.pData = (OMX_U8 *) malloc(m_vendor_config.nDataSize); + OMX_U32 len; + OMX_U8 index = 0; + // case where SPS+PPS is sent as part of set_config + pDestBuf = m_vendor_config.pData; + + DEBUG_PRINT_LOW("Rxd SPS+PPS nPortIndex[%d] len[%d] data[0x%x]", + m_vendor_config.nPortIndex, + m_vendor_config.nDataSize, + m_vendor_config.pData); + while (index < 2) + { + uint8 *psize; + len = *pSrcBuf; + len = len << 8; + len |= *(pSrcBuf + 1); + psize = (uint8 *) & len; + memcpy(pDestBuf + nal_length, pSrcBuf + 2,len); + for (int i = 0; i < nal_length; i++) + { + pDestBuf[i] = psize[nal_length - 1 - i]; + } + //memcpy(pDestBuf,pSrcBuf,(len+2)); + pDestBuf += len + nal_length; + pSrcBuf += len + 2; + index++; + pSrcBuf++; // skip picture param set + len = 0; + } + } + else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4") || + !strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2")) + { + m_vendor_config.nPortIndex = config->nPortIndex; + m_vendor_config.nDataSize = config->nDataSize; + m_vendor_config.pData = (OMX_U8 *) malloc((config->nDataSize)); + memcpy(m_vendor_config.pData, config->pData,config->nDataSize); + } + else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1")) + { + if(m_vendor_config.pData) + { + free(m_vendor_config.pData); + m_vendor_config.pData = NULL; + m_vendor_config.nDataSize = 0; + } + + if (((*((OMX_U32 *) config->pData)) & + VC1_SP_MP_START_CODE_MASK) == + VC1_SP_MP_START_CODE) + { + DEBUG_PRINT_LOW("set_config - VC1 simple/main profile\n"); + m_vendor_config.nPortIndex = config->nPortIndex; + m_vendor_config.nDataSize = config->nDataSize; + m_vendor_config.pData = + (OMX_U8 *) malloc(config->nDataSize); + memcpy(m_vendor_config.pData, config->pData, + config->nDataSize); + m_vc1_profile = VC1_SP_MP_RCV; + } + else if (*((OMX_U32 *) config->pData) == VC1_AP_SEQ_START_CODE) + { + DEBUG_PRINT_LOW("set_config - VC1 Advance profile\n"); + m_vendor_config.nPortIndex = config->nPortIndex; + m_vendor_config.nDataSize = config->nDataSize; + m_vendor_config.pData = + (OMX_U8 *) malloc((config->nDataSize)); + memcpy(m_vendor_config.pData, config->pData, + config->nDataSize); + m_vc1_profile = VC1_AP; + } + else if ((config->nDataSize == VC1_STRUCT_C_LEN)) + { + DEBUG_PRINT_LOW("set_config - VC1 Simple/Main profile struct C only\n"); + m_vendor_config.nPortIndex = config->nPortIndex; + m_vendor_config.nDataSize = config->nDataSize; + m_vendor_config.pData = (OMX_U8*)malloc(config->nDataSize); + memcpy(m_vendor_config.pData,config->pData,config->nDataSize); + m_vc1_profile = VC1_SP_MP_RCV; + } + else + { + DEBUG_PRINT_LOW("set_config - Error: Unknown VC1 profile\n"); + } + } + return ret; + } + else if (configIndex == OMX_IndexConfigVideoNalSize) + { + + pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData); + nal_length = pNal->nNaluBytes; + m_frame_parser.init_nal_length(nal_length); + DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d",nal_length); + return ret; + } + + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_vdec::GetExtensionIndex + +DESCRIPTION + OMX GetExtensionIndex method implementaion. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_STRING paramName, + OMX_OUT OMX_INDEXTYPE* indexType) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Extension Index in Invalid State\n"); + return OMX_ErrorInvalidState; + } + else if (!strncmp(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode",sizeof("OMX.QCOM.index.param.video.SyncFrameDecodingMode") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode; + } +#ifdef MAX_RES_1080P + else if (!strncmp(paramName, "OMX.QCOM.index.param.IndexExtraData",sizeof("OMX.QCOM.index.param.IndexExtraData") - 1)) + { + *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType; + } +#endif +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) + else if(!strncmp(paramName,"OMX.google.android.index.enableAndroidNativeBuffers", sizeof("OMX.google.android.index.enableAndroidNativeBuffers") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers; + } + else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer2", sizeof("OMX.google.android.index.enableAndroidNativeBuffer2") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2; + } + else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer", sizeof("OMX.google.android.index.enableAndroidNativeBuffer") - 1)) { + DEBUG_PRINT_ERROR("Extension: %s is supported\n", paramName); + *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer; + } + else if(!strncmp(paramName,"OMX.google.android.index.getAndroidNativeBufferUsage", sizeof("OMX.google.android.index.getAndroidNativeBufferUsage") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage; + } +#endif + else { + DEBUG_PRINT_ERROR("Extension: %s not implemented\n", paramName); + return OMX_ErrorNotImplemented; + } + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::GetState + +DESCRIPTION + Returns the state information back to the caller. + +PARAMETERS + . + +RETURN VALUE + Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STATETYPE* state) +{ + *state = m_state; + DEBUG_PRINT_LOW("get_state: Returning the state %d",*state); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::ComponentTunnelRequest + +DESCRIPTION + OMX Component Tunnel Request method implementation. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_HANDLETYPE peerComponent, + OMX_IN OMX_U32 peerPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) +{ + DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented\n"); + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_vdec::UseOutputBuffer + +DESCRIPTION + Helper function for Use buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::use_output_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header + unsigned i= 0; // Temporary counter + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct vdec_setbuffer_cmd setbuffers; + OMX_PTR privateAppData = NULL; +#if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_) + private_handle_t *handle = NULL; +#endif + OMX_U8 *buff = buffer; + + if (!m_out_mem_ptr) { + DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers"); + eRet = allocate_output_headers(); +#ifdef MAX_RES_1080P + if(drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + //allocate H264_mv_buffer + eRet = vdec_alloc_h264_mv(); + if (eRet) { + DEBUG_PRINT_ERROR("ERROR in allocating MV buffers\n"); + return OMX_ErrorInsufficientResources; + } + } +#endif + + } + + if (eRet == OMX_ErrorNone) { + for(i=0; i< drv_ctx.op_buf.actualcount; i++) { + if(BITMASK_ABSENT(&m_out_bm_count,i)) + { + break; + } + } + } + + if(i >= drv_ctx.op_buf.actualcount) { + eRet = OMX_ErrorInsufficientResources; + } + + if (eRet == OMX_ErrorNone) { +#if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_) + if(m_enable_android_native_buffers) { + if (m_use_android_native_buffers) { + UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData; + sp nBuf = params->nativeBuffer; + handle = (private_handle_t *)nBuf->handle; + privateAppData = params->pAppPrivate; + } else { + handle = (private_handle_t *)buff; + privateAppData = appData; + } + + if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) { + DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback," + " expected %u, got %lu", + drv_ctx.op_buf.buffer_size, (OMX_U32)handle->size); + return OMX_ErrorBadParameter; + } + + if (!m_use_android_native_buffers) { + if (!secure_mode) { + buff = (OMX_U8*)mmap(0, handle->size, + PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); + if (buff == MAP_FAILED) { + DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); + return OMX_ErrorInsufficientResources; + } + } + } + +#if defined(_ANDROID_ICS_) + native_buffer[i].nativehandle = handle; +#endif + if(!handle) { + DEBUG_PRINT_ERROR("Native Buffer handle is NULL"); + return OMX_ErrorBadParameter; + } + drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd; + drv_ctx.ptr_outputbuffer[i].offset = 0; + drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; + drv_ctx.ptr_outputbuffer[i].mmaped_size = + drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; + } else +#endif + + if (!ouput_egl_buffers && !m_use_output_pmem) { +#ifdef USE_ION + drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( + drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment, + &drv_ctx.op_buf_ion_info[i].ion_alloc_data, + &drv_ctx.op_buf_ion_info[i].fd_ion_data,CACHED); + if(drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) { + return OMX_ErrorInsufficientResources; + } + drv_ctx.ptr_outputbuffer[i].pmem_fd = \ + drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; +#else + drv_ctx.ptr_outputbuffer[i].pmem_fd = \ + open (MEM_DEVICE,O_SYNC|O_RDWR); + + if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { + return OMX_ErrorInsufficientResources; + } + + if(drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) + { + drv_ctx.ptr_outputbuffer[i].pmem_fd = \ + open (MEM_DEVICE,O_SYNC|O_RDWR); + if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { + return OMX_ErrorInsufficientResources; + } + } + + if(!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd, + drv_ctx.op_buf.buffer_size, + drv_ctx.op_buf.alignment)) + { + DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed"); + close(drv_ctx.ptr_outputbuffer[i].pmem_fd); + return OMX_ErrorInsufficientResources; + } +#endif + if(!secure_mode) { + drv_ctx.ptr_outputbuffer[i].bufferaddr = + (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size, + PROT_READ|PROT_WRITE, MAP_SHARED, + drv_ctx.ptr_outputbuffer[i].pmem_fd,0); + if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) { + close(drv_ctx.ptr_outputbuffer[i].pmem_fd); +#ifdef USE_ION + free_ion_memory(&drv_ctx.op_buf_ion_info[i]); +#endif + return OMX_ErrorInsufficientResources; + } + } + drv_ctx.ptr_outputbuffer[i].offset = 0; + privateAppData = appData; + } + else { + + DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem); + + if (!appData || !bytes ) + { + DEBUG_PRINT_ERROR("\n Invalid appData or bytes"); + return OMX_ErrorBadParameter; + } + + if(!secure_mode && !buffer) + { + DEBUG_PRINT_ERROR("\n Bad parameters for use buffer in EGL image case"); + return OMX_ErrorBadParameter; + } + + + OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list; + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info; + pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData; + if (!pmem_list->entryList || !pmem_list->entryList->entry || + !pmem_list->nEntries || + pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) { + DEBUG_PRINT_ERROR("\n Pmem info not valid in use buffer"); + return OMX_ErrorBadParameter; + } + pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + pmem_list->entryList->entry; + DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%x", + pmem_info->pmem_fd); + drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd; + drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset; + drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; + drv_ctx.ptr_outputbuffer[i].mmaped_size = + drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; + privateAppData = appData; + } + m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; + m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd; + + *bufferHdr = (m_out_mem_ptr + i ); + if(secure_mode) + drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; + setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i], + sizeof (vdec_bufferpayload)); + + ioctl_msg.in = &setbuffers; + ioctl_msg.out = NULL; + + DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %x, pmem_fd=%0x%x", i, + drv_ctx.ptr_outputbuffer[i],drv_ctx.ptr_outputbuffer[i].pmem_fd ); + if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_BUFFER, + &ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n Set output buffer failed"); + return OMX_ErrorInsufficientResources; + } + // found an empty buffer at i + (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size; + if (m_enable_android_native_buffers) { + DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle); + (*bufferHdr)->pBuffer = (OMX_U8 *)handle; + } else { + (*bufferHdr)->pBuffer = buff; + } + (*bufferHdr)->pAppPrivate = privateAppData; + BITMASK_SET(&m_out_bm_count,i); + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::use_input_heap_buffers + +DESCRIPTION + OMX Use Buffer Heap allocation method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None , if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::use_input_heap_buffers( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer); + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(!m_inp_heap_ptr) + m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) + calloc( (sizeof(OMX_BUFFERHEADERTYPE)), + drv_ctx.ip_buf.actualcount); + if(!m_phdr_pmem_ptr) + m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) + calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), + drv_ctx.ip_buf.actualcount); + if(!m_inp_heap_ptr || !m_phdr_pmem_ptr) + { + DEBUG_PRINT_ERROR("Insufficent memory"); + eRet = OMX_ErrorInsufficientResources; + } + else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) + { + input_use_buffer = true; + memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE)); + m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer; + m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes; + m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData; + m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput; + m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax; + *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt]; + eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes); + DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]); + if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[m_in_alloc_cnt], NULL, NULL)) + { + DEBUG_PRINT_ERROR("\nERROR:Free_q is full"); + return OMX_ErrorInsufficientResources; + } + m_in_alloc_cnt++; + } + else + { + DEBUG_PRINT_ERROR("All i/p buffers have been set!"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::UseBuffer + +DESCRIPTION + OMX Use Buffer method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None , if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::use_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE error = OMX_ErrorNone; + struct vdec_setbuffer_cmd setbuffers; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + + if (bufferHdr == NULL || bytes == 0) + { + DEBUG_PRINT_ERROR("bad param 0x%p %ld",bufferHdr, bytes); + return OMX_ErrorBadParameter; + } + + if(!secure_mode && buffer == NULL) { + DEBUG_PRINT_ERROR("bad param 0x%p",buffer); + return OMX_ErrorBadParameter; + } + + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Use Buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(port == OMX_CORE_INPUT_PORT_INDEX) + error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer); + else if(port == OMX_CORE_OUTPUT_PORT_INDEX) + error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested + else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port); + error = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", port, *bufferHdr, error); + if(error == OMX_ErrorNone) + { + if(allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); + post_event(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated && + BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + else if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated && + BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + return error; +} + +OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex, + OMX_BUFFERHEADERTYPE *pmem_bufferHdr) +{ + if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) + { + if(m_inp_heap_ptr[bufferindex].pBuffer) + free(m_inp_heap_ptr[bufferindex].pBuffer); + m_inp_heap_ptr[bufferindex].pBuffer = NULL; + } + if (pmem_bufferHdr) + free_input_buffer(pmem_bufferHdr); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) +{ + unsigned int index = 0; + if (bufferHdr == NULL || m_inp_mem_ptr == NULL) + { + return OMX_ErrorBadParameter; + } + + index = bufferHdr - m_inp_mem_ptr; + DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); + + if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) + { + DEBUG_PRINT_LOW("Free Input Buffer index = %d",index); + if (drv_ctx.ptr_inputbuffer[index].pmem_fd > 0) + { + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct vdec_setbuffer_cmd setbuffers; + setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT; + memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index], + sizeof (vdec_bufferpayload)); + ioctl_msg.in = &setbuffers; + ioctl_msg.out = NULL; + int ioctl_r = ioctl (drv_ctx.video_driver_fd, + VDEC_IOCTL_FREE_BUFFER, &ioctl_msg); + if (ioctl_r < 0) + { + DEBUG_PRINT_ERROR("\nVDEC_IOCTL_FREE_BUFFER returned error %d", ioctl_r); + } + if (!secure_mode) { + DEBUG_PRINT_LOW("unmap the input buffer fd=%d", + drv_ctx.ptr_inputbuffer[index].pmem_fd); + DEBUG_PRINT_LOW("unmap the input buffer size=%d address = %d", + drv_ctx.ptr_inputbuffer[index].mmaped_size, + drv_ctx.ptr_inputbuffer[index].bufferaddr); + munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr, + drv_ctx.ptr_inputbuffer[index].mmaped_size); + } + close (drv_ctx.ptr_inputbuffer[index].pmem_fd); + drv_ctx.ptr_inputbuffer[index].pmem_fd = -1; + if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) + { + free(m_desc_buffer_ptr[index].buf_addr); + m_desc_buffer_ptr[index].buf_addr = NULL; + m_desc_buffer_ptr[index].desc_data_size = 0; + } +#ifdef USE_ION + free_ion_memory(&drv_ctx.ip_buf_ion_info[index]); +#endif + } + } + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) +{ + unsigned int index = 0; + + if (bufferHdr == NULL || m_out_mem_ptr == NULL) + { + DEBUG_PRINT_ERROR("\nfree_output_buffer ERROR"); + return OMX_ErrorBadParameter; + } + + index = bufferHdr - m_out_mem_ptr; + DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index); + + if (index < drv_ctx.op_buf.actualcount + && drv_ctx.ptr_outputbuffer) + { + DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %x", index, + drv_ctx.ptr_outputbuffer[index].bufferaddr); + + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct vdec_setbuffer_cmd setbuffers; + setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index], + sizeof (vdec_bufferpayload)); + ioctl_msg.in = &setbuffers; + ioctl_msg.out = NULL; + DEBUG_PRINT_LOW("Release the Output Buffer"); + if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_FREE_BUFFER, + &ioctl_msg) < 0) + DEBUG_PRINT_ERROR("\n Release output buffer failed in VCD"); + +#ifdef _ANDROID_ + if(m_enable_android_native_buffers) { + if(drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) { + if(!secure_mode) { + munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr, + drv_ctx.ptr_outputbuffer[index].mmaped_size); + } + } + drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; + } else { +#endif + if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) + { + if(!secure_mode) { + DEBUG_PRINT_LOW("unmap the output buffer fd = %d", + drv_ctx.ptr_outputbuffer[index].pmem_fd); + DEBUG_PRINT_LOW("unmap the ouput buffer size=%d address = %d", + drv_ctx.ptr_outputbuffer[index].mmaped_size, + drv_ctx.ptr_outputbuffer[index].bufferaddr); + munmap (drv_ctx.ptr_outputbuffer[index].bufferaddr, + drv_ctx.ptr_outputbuffer[index].mmaped_size); + } +#ifdef USE_ION + free_ion_memory(&drv_ctx.op_buf_ion_info[index]); +#endif + close (drv_ctx.ptr_outputbuffer[index].pmem_fd); + drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; +#ifdef _ANDROID_ + m_heap_ptr[index].video_heap_ptr = NULL; + m_heap_count = m_heap_count - 1; + if (m_heap_count == 0) + { + free(m_heap_ptr); + m_heap_ptr = NULL; + } +#endif // _ANDROID_ + } +#ifdef _ANDROID_ + } +#endif + } +#ifdef MAX_RES_1080P + if(drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + vdec_dealloc_h264_mv(); + } +#endif + + return OMX_ErrorNone; + +} + +OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes) +{ + OMX_BUFFERHEADERTYPE *input = NULL; + unsigned char *buf_addr = NULL; + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned i = 0; + + /* Sanity Check*/ + if (bufferHdr == NULL) + { + return OMX_ErrorBadParameter; + } + + if (m_inp_heap_ptr == NULL) + { + m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \ + calloc( (sizeof(OMX_BUFFERHEADERTYPE)), + drv_ctx.ip_buf.actualcount); + m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \ + calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), + drv_ctx.ip_buf.actualcount); + + if (m_inp_heap_ptr == NULL) + { + DEBUG_PRINT_ERROR("\n m_inp_heap_ptr Allocation failed "); + return OMX_ErrorInsufficientResources; + } + } + + /*Find a Free index*/ + for(i=0; i< drv_ctx.ip_buf.actualcount; i++) + { + if(BITMASK_ABSENT(&m_heap_inp_bm_count,i)) + { + DEBUG_PRINT_LOW("Free Input Buffer Index %d",i); + break; + } + } + + if (i < drv_ctx.ip_buf.actualcount) + { + buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size); + + if (buf_addr == NULL) + { + return OMX_ErrorInsufficientResources; + } + + *bufferHdr = (m_inp_heap_ptr + i); + input = *bufferHdr; + BITMASK_SET(&m_heap_inp_bm_count,i); + + input->pBuffer = (OMX_U8 *)buf_addr; + input->nSize = sizeof(OMX_BUFFERHEADERTYPE); + input->nVersion.nVersion = OMX_SPEC_VERSION; + input->nAllocLen = drv_ctx.ip_buf.buffer_size - DEVICE_SCRATCH; + input->pAppPrivate = appData; + input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr ); + eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes); + DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr [i] ); + /*Add the Buffers to freeq*/ + if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr [i],NULL,NULL)) + { + DEBUG_PRINT_ERROR("\nERROR:Free_q is full"); + return OMX_ErrorInsufficientResources; + } + } + else + { + return OMX_ErrorBadParameter; + } + + return eRet; + +} + + +/* ====================================================================== +FUNCTION + omx_vdec::AllocateInputBuffer + +DESCRIPTION + Helper function for allocate buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::allocate_input_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct vdec_setbuffer_cmd setbuffers; + OMX_BUFFERHEADERTYPE *input = NULL; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + unsigned i = 0; + unsigned char *buf_addr = NULL; + int pmem_fd = -1; + + if((bytes + DEVICE_SCRATCH) != drv_ctx.ip_buf.buffer_size) + { + DEBUG_PRINT_LOW("Requested Size is wrong %d epected is %d", + bytes, drv_ctx.ip_buf.buffer_size); + //return OMX_ErrorBadParameter; + } + + if(!m_inp_mem_ptr) + { + DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%d)", + drv_ctx.ip_buf.actualcount, + drv_ctx.ip_buf.buffer_size); + + m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ + calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount); + + if (m_inp_mem_ptr == NULL) + { + return OMX_ErrorInsufficientResources; + } + + drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \ + calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount); + + if (drv_ctx.ptr_inputbuffer == NULL) + { + return OMX_ErrorInsufficientResources; + } +#ifdef USE_ION + drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \ + calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount); + + if (drv_ctx.ip_buf_ion_info == NULL) + { + return OMX_ErrorInsufficientResources; + } +#endif + + for (i=0; i < drv_ctx.ip_buf.actualcount; i++) + { + drv_ctx.ptr_inputbuffer [i].pmem_fd = -1; +#ifdef USE_ION + drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1; +#endif + } + } + + for(i=0; i< drv_ctx.ip_buf.actualcount; i++) + { + if(BITMASK_ABSENT(&m_inp_bm_count,i)) + { + DEBUG_PRINT_LOW("Free Input Buffer Index %d",i); + break; + } + } + + if(i < drv_ctx.ip_buf.actualcount) + { + DEBUG_PRINT_LOW("Allocate input Buffer"); + +#ifdef USE_ION + drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( + drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment, + &drv_ctx.ip_buf_ion_info[i].ion_alloc_data, + &drv_ctx.ip_buf_ion_info[i].fd_ion_data,CACHED); + if(drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) { + return OMX_ErrorInsufficientResources; + } + pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd; +#else + pmem_fd = open (MEM_DEVICE,O_SYNC|O_RDWR); + + if (pmem_fd < 0) + { + DEBUG_PRINT_ERROR("\n open failed for pmem/adsp for input buffer"); + return OMX_ErrorInsufficientResources; + } + + if (pmem_fd == 0) + { + pmem_fd = open (MEM_DEVICE,O_SYNC|O_RDWR); + + if (pmem_fd < 0) + { + DEBUG_PRINT_ERROR("\n open failed for pmem/adsp for input buffer"); + return OMX_ErrorInsufficientResources; + } + } + + if(!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size, + drv_ctx.ip_buf.alignment)) + { + DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed"); + close(pmem_fd); + return OMX_ErrorInsufficientResources; + } +#endif + if (!secure_mode) { + buf_addr = (unsigned char *)mmap(NULL, + drv_ctx.ip_buf.buffer_size, + PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0); + + if (buf_addr == MAP_FAILED) + { + close(pmem_fd); +#ifdef USE_ION + free_ion_memory(&drv_ctx.ip_buf_ion_info[i]); +#endif + DEBUG_PRINT_ERROR("\n Map Failed to allocate input buffer"); + return OMX_ErrorInsufficientResources; + } + } + *bufferHdr = (m_inp_mem_ptr + i); + if (secure_mode) + drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr; + else + drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr; + drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd; + drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size; + drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size; + drv_ctx.ptr_inputbuffer [i].offset = 0; + + setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT; + memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer [i], + sizeof (vdec_bufferpayload)); + ioctl_msg.in = &setbuffers; + ioctl_msg.out = NULL; + + if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_BUFFER, + &ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n Set Buffers Failed"); + return OMX_ErrorInsufficientResources; + } + + input = *bufferHdr; + BITMASK_SET(&m_inp_bm_count,i); + DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr); + if (secure_mode) + input->pBuffer = (OMX_U8 *)drv_ctx.ptr_inputbuffer [i].pmem_fd; + else + input->pBuffer = (OMX_U8 *)buf_addr; + input->nSize = sizeof(OMX_BUFFERHEADERTYPE); + input->nVersion.nVersion = OMX_SPEC_VERSION; + input->nAllocLen = drv_ctx.ip_buf.buffer_size - DEVICE_SCRATCH; + input->pAppPrivate = appData; + input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i]; + + if (drv_ctx.disable_dmx) + { + eRet = allocate_desc_buffer(i); + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR:Input Buffer Index not found"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + + +/* ====================================================================== +FUNCTION + omx_vdec::AllocateOutputBuffer + +DESCRIPTION + Helper fn for AllocateBuffer in the output pin + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything went well. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::allocate_output_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header + unsigned i= 0; // Temporary counter + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct vdec_setbuffer_cmd setbuffers; +#ifdef USE_ION + int ion_device_fd =-1; + struct ion_allocation_data ion_alloc_data; + struct ion_fd_data fd_ion_data; +#endif + + int nBufHdrSize = 0; + int nPlatformEntrySize = 0; + int nPlatformListSize = 0; + int nPMEMInfoSize = 0; + int pmem_fd = -1; + unsigned char *pmem_baseaddress = NULL; + + OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; + OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; + + if (!m_out_mem_ptr) + { + DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%d)", + drv_ctx.op_buf.actualcount, + drv_ctx.op_buf.buffer_size); + + DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)", + drv_ctx.op_buf.actualcount); + + nBufHdrSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_BUFFERHEADERTYPE); + + nPMEMInfoSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); + nPlatformListSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); + nPlatformEntrySize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); + + DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d",nBufHdrSize, + sizeof(OMX_BUFFERHEADERTYPE), + nPMEMInfoSize, + nPlatformListSize); + DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize, + drv_ctx.op_buf.actualcount); + + m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); + // Alloc mem for platform specific info + char *pPtr=NULL; + pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + + nPMEMInfoSize,1); + drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\ + calloc (sizeof(struct vdec_bufferpayload), + drv_ctx.op_buf.actualcount); + drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ + calloc (sizeof (struct vdec_output_frameinfo), + drv_ctx.op_buf.actualcount); +#ifdef USE_ION + drv_ctx.op_buf_ion_info = (struct vdec_ion *)\ + calloc (sizeof(struct vdec_ion), + drv_ctx.op_buf.actualcount); +#endif +#ifdef _ANDROID_ + m_heap_ptr = (struct vidc_heap *)\ + calloc (sizeof(struct vidc_heap), + drv_ctx.op_buf.actualcount); +#endif + + if(m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer + && drv_ctx.ptr_respbuffer +#ifdef _ANDROID_ + && m_heap_ptr +#endif + ) + { + drv_ctx.ptr_outputbuffer[0].mmaped_size = + (drv_ctx.op_buf.buffer_size * + drv_ctx.op_buf.actualcount); + bufHdr = m_out_mem_ptr; + m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); + m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) + (((char *) m_platform_list) + nPlatformListSize); + m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + (((char *) m_platform_entry) + nPlatformEntrySize); + pPlatformList = m_platform_list; + pPlatformEntry = m_platform_entry; + pPMEMInfo = m_pmem_info; + + DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr); + + // Settting the entire storage nicely + DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry); + DEBUG_PRINT_LOW("Pmem Info = %p",pPMEMInfo); + for(i=0; i < drv_ctx.op_buf.actualcount ; i++) + { + bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + // Set the values when we determine the right HxW param + bufHdr->nAllocLen = 0; + bufHdr->nFilledLen = 0; + bufHdr->pAppPrivate = NULL; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + // Platform specific PMEM Information + // Initialize the Platform Entry + //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i); + pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; + pPlatformEntry->entry = pPMEMInfo; + // Initialize the Platform List + pPlatformList->nEntries = 1; + pPlatformList->entryList = pPlatformEntry; + // Keep pBuffer NULL till vdec is opened + bufHdr->pBuffer = NULL; + + pPMEMInfo->offset = 0; + pPMEMInfo->pmem_fd = 0; + bufHdr->pPlatformPrivate = pPlatformList; + drv_ctx.ptr_outputbuffer[i].pmem_fd = -1; +#ifdef USE_ION + drv_ctx.op_buf_ion_info[i].ion_device_fd =-1; +#endif + /*Create a mapping between buffers*/ + bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; + drv_ctx.ptr_respbuffer[i].client_data = (void *)\ + &drv_ctx.ptr_outputbuffer[i]; +#ifdef _ANDROID_ + m_heap_ptr[i].video_heap_ptr = NULL; +#endif + // Move the buffer and buffer header pointers + bufHdr++; + pPMEMInfo++; + pPlatformEntry++; + pPlatformList++; + } +#ifdef MAX_RES_1080P + if(eRet == OMX_ErrorNone && drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + //Allocate the h264_mv_buffer + eRet = vdec_alloc_h264_mv(); + if(eRet) { + DEBUG_PRINT_ERROR("ERROR in allocating MV buffers\n"); + return OMX_ErrorInsufficientResources; + } + } +#endif + } + else + { + DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%x][0x%x]\n",\ + m_out_mem_ptr, pPtr); + if(m_out_mem_ptr) + { + free(m_out_mem_ptr); + m_out_mem_ptr = NULL; + } + if(pPtr) + { + free(pPtr); + pPtr = NULL; + } + if(drv_ctx.ptr_outputbuffer) + { + free(drv_ctx.ptr_outputbuffer); + drv_ctx.ptr_outputbuffer = NULL; + } + if(drv_ctx.ptr_respbuffer) + { + free(drv_ctx.ptr_respbuffer); + drv_ctx.ptr_respbuffer = NULL; + } +#ifdef USE_ION + if (drv_ctx.op_buf_ion_info) { + DEBUG_PRINT_LOW("Free o/p ion context"); + free(drv_ctx.op_buf_ion_info); + drv_ctx.op_buf_ion_info = NULL; + } +#endif + eRet = OMX_ErrorInsufficientResources; + } + } + + for (i=0; i< drv_ctx.op_buf.actualcount; i++) + { + if(BITMASK_ABSENT(&m_out_bm_count,i)) + { + DEBUG_PRINT_LOW("Found a Free Output Buffer Index %d",i); + break; + } + } + + if (i < drv_ctx.op_buf.actualcount) + { + DEBUG_PRINT_LOW("Allocate Output Buffer"); + +#ifdef USE_ION + drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( + drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment, + &drv_ctx.op_buf_ion_info[i].ion_alloc_data, + &drv_ctx.op_buf_ion_info[i].fd_ion_data, CACHED); + if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) { + return OMX_ErrorInsufficientResources; + } + pmem_fd = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; +#else + pmem_fd = open (MEM_DEVICE,O_SYNC|O_RDWR); + + if (pmem_fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR:pmem fd for output buffer %d", + drv_ctx.op_buf.buffer_size); + return OMX_ErrorInsufficientResources; + } + + if (pmem_fd == 0) + { + pmem_fd = open (MEM_DEVICE,O_SYNC|O_RDWR); + + if (pmem_fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR:pmem fd for output buffer %d", + drv_ctx.op_buf.buffer_size); + return OMX_ErrorInsufficientResources; + } + } + + if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size, + drv_ctx.op_buf.alignment)) + { + DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed"); + close(pmem_fd); + return OMX_ErrorInsufficientResources; + } +#endif + if (!secure_mode) { + pmem_baseaddress = (unsigned char *)mmap(NULL, + drv_ctx.op_buf.buffer_size, + PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0); + + if (pmem_baseaddress == MAP_FAILED) + { + DEBUG_PRINT_ERROR("\n MMAP failed for Size %d", + drv_ctx.op_buf.buffer_size); + close(pmem_fd); +#ifdef USE_ION + free_ion_memory(&drv_ctx.op_buf_ion_info[i]); +#endif + return OMX_ErrorInsufficientResources; + } + } + + *bufferHdr = (m_out_mem_ptr + i); + if (secure_mode) + drv_ctx.ptr_outputbuffer [i].bufferaddr = *bufferHdr; + else + drv_ctx.ptr_outputbuffer [i].bufferaddr = pmem_baseaddress; + + drv_ctx.ptr_outputbuffer [i].pmem_fd = pmem_fd; + drv_ctx.ptr_outputbuffer [i].buffer_len = drv_ctx.op_buf.buffer_size; + drv_ctx.ptr_outputbuffer [i].mmaped_size = drv_ctx.op_buf.buffer_size; + drv_ctx.ptr_outputbuffer [i].offset = 0; + +#ifdef _ANDROID_ + #ifdef USE_ION + m_heap_ptr[i].video_heap_ptr = new VideoHeap (drv_ctx.op_buf_ion_info[i].ion_device_fd, + drv_ctx.op_buf.buffer_size, + pmem_baseaddress, + ion_alloc_data.handle, + pmem_fd); + m_heap_count = m_heap_count + 1; +#else + m_heap_ptr[i].video_heap_ptr = new VideoHeap (pmem_fd, + drv_ctx.op_buf.buffer_size, + pmem_baseaddress); +#endif +#endif + + m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; +#ifdef _ANDROID_ + m_pmem_info[i].pmem_fd = (OMX_U32) m_heap_ptr[i].video_heap_ptr.get (); +#else + m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd ; +#endif + setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer [i], + sizeof (vdec_bufferpayload)); + ioctl_msg.in = &setbuffers; + ioctl_msg.out = NULL; + + DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_outputbuffer[i]); + if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_BUFFER, + &ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n Set output buffer failed"); + return OMX_ErrorInsufficientResources; + } + + // found an empty buffer at i + (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size; + (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr; + (*bufferHdr)->pAppPrivate = appData; + BITMASK_SET(&m_out_bm_count,i); + + } + else + { + DEBUG_PRINT_ERROR("\nERROR:Output Buffer Index not found"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + + +// AllocateBuffer -- API Call +/* ====================================================================== +FUNCTION + omx_vdec::AllocateBuffer + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + unsigned i = 0; + OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type + + DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Allocate Buf in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if(port == OMX_CORE_INPUT_PORT_INDEX) + { + if (arbitrary_bytes) + { + eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes); + } + else + { + eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); + } + } + else if(port == OMX_CORE_OUTPUT_PORT_INDEX) + { + eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); + } + else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port); + eRet = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done"); + if(eRet == OMX_ErrorNone) + { + if(allocate_done()){ + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); + post_event(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + } + DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet); + return eRet; +} + +// Free Buffer - API call +/* ====================================================================== +FUNCTION + omx_vdec::FreeBuffer + +DESCRIPTION + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned int nPortIndex; + + DEBUG_PRINT_LOW("In for decoder free_buffer"); + + if(m_state == OMX_StateIdle && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + DEBUG_PRINT_LOW(" free buffer while Component in Loading pending"); + } + else if((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)|| + (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) + { + DEBUG_PRINT_LOW("Free Buffer while port %d disabled", port); + } + else if(m_state == OMX_StateExecuting || m_state == OMX_StatePause) + { + DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled\n"); + post_event(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + + return OMX_ErrorIncorrectStateOperation; + } + else if (m_state != OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers\n"); + post_event(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + } + + if(port == OMX_CORE_INPUT_PORT_INDEX) + { + /*Check if arbitrary bytes*/ + if(!arbitrary_bytes && !input_use_buffer) + nPortIndex = buffer - m_inp_mem_ptr; + else + nPortIndex = buffer - m_inp_heap_ptr; + + DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex); + if(nPortIndex < drv_ctx.ip_buf.actualcount) + { + // Clear the bit associated with it. + BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); + BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex); + if (input_use_buffer == true) + { + + DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex); + if(m_phdr_pmem_ptr) + free_input_buffer(m_phdr_pmem_ptr[nPortIndex]); + } + else + { + if (arbitrary_bytes) + { + if(m_phdr_pmem_ptr) + free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]); + else + free_input_buffer(nPortIndex,NULL); + } + else + free_input_buffer(buffer); + } + m_inp_bPopulated = OMX_FALSE; + /*Free the Buffer Header*/ + if (release_input_done()) + { + DEBUG_PRINT_HIGH("ALL input buffers are freed/released"); + free_input_buffer_header(); + } + } + else + { + DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + + if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) + && release_input_done()) + { + DEBUG_PRINT_LOW("MOVING TO DISABLED STATE"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); + post_event(OMX_CommandPortDisable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + else if(port == OMX_CORE_OUTPUT_PORT_INDEX) + { + // check if the buffer is valid + nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr; + if(nPortIndex < drv_ctx.op_buf.actualcount) + { + DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex); + // Clear the bit associated with it. + BITMASK_CLEAR(&m_out_bm_count,nPortIndex); + m_out_bPopulated = OMX_FALSE; + free_output_buffer (buffer); + + if (release_output_done()) + { + free_output_buffer_header(); + } + } + else + { + DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) + && release_output_done()) + { + DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it"); + + DEBUG_PRINT_LOW("MOVING TO DISABLED STATE"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); +#ifdef _ANDROID_ICS_ + if (m_enable_android_native_buffers) + { + DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers"); + memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); + } +#endif + + post_event(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + else + { + eRet = OMX_ErrorBadPortIndex; + } + if((eRet == OMX_ErrorNone) && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + if(release_done()) + { + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); + post_event(OMX_CommandStateSet, OMX_StateLoaded, + OMX_COMPONENT_GENERATE_EVENT); + } + } + return eRet; +} + + +/* ====================================================================== +FUNCTION + omx_vdec::EmptyThisBuffer + +DESCRIPTION + This routine is used to push the encoded video frames to + the video decoder. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything went successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE ret1 = OMX_ErrorNone; + unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount; + + if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) + { + codec_config_flag = true; + DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__); + } + else + { + codec_config_flag = false; + } + + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Empty this buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if (buffer == NULL) + { + DEBUG_PRINT_ERROR("\nERROR:ETB Buffer is NULL"); + return OMX_ErrorBadParameter; + } + + if (!m_inp_bEnabled) + { + DEBUG_PRINT_ERROR("\nERROR:ETB incorrect state operation, input port is disabled."); + return OMX_ErrorIncorrectStateOperation; + } + + if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) + { + DEBUG_PRINT_ERROR("\nERROR:ETB invalid port in header %d", buffer->nInputPortIndex); + return OMX_ErrorBadPortIndex; + } + +#ifdef _ANDROID_ + if(iDivXDrmDecrypt) + { + OMX_ERRORTYPE drmErr = iDivXDrmDecrypt->Decrypt(buffer); + if(drmErr != OMX_ErrorNone) { + // this error can be ignored + DEBUG_PRINT_LOW("\nERROR:iDivXDrmDecrypt->Decrypt %d", drmErr); + } + } + if (perf_flag) + { + if (!latency) + { + dec_time.stop(); + latency = dec_time.processing_time_us(); + dec_time.start(); + } + } +#endif //_ANDROID_ + + if (arbitrary_bytes) + { + nBufferIndex = buffer - m_inp_heap_ptr; + } + else + { + if (input_use_buffer == true) + { + nBufferIndex = buffer - m_inp_heap_ptr; + m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen; + m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp; + m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags; + buffer = &m_inp_mem_ptr[nBufferIndex]; + DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %d", + &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, buffer->nFilledLen); + } + else{ + nBufferIndex = buffer - m_inp_mem_ptr; + } + } + + if (nBufferIndex > drv_ctx.ip_buf.actualcount ) + { + DEBUG_PRINT_ERROR("\nERROR:ETB nBufferIndex is invalid"); + return OMX_ErrorBadParameter; + } + + DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%lu)", + buffer, buffer->pBuffer, buffer->nTimeStamp, buffer->nFilledLen); + if (arbitrary_bytes) + { + post_event ((unsigned)hComp,(unsigned)buffer, + OMX_COMPONENT_GENERATE_ETB_ARBITRARY); + } + else + { + if (!(client_extradata & OMX_TIMEINFO_EXTRADATA)) + set_frame_rate(buffer->nTimeStamp); + post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB); + } + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::empty_this_buffer_proxy + +DESCRIPTION + This routine is used to push the encoded video frames to + the video decoder. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything went successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + int push_cnt = 0,i=0; + unsigned nPortIndex = 0; + OMX_ERRORTYPE ret = OMX_ErrorNone; + struct vdec_input_frameinfo frameinfo; + struct vdec_bufferpayload *temp_buffer; + struct vdec_ioctl_msg ioctl_msg; + struct vdec_seqheader seq_header; + bool port_setting_changed = true; +#ifdef MAX_RES_1080P + bool not_coded_vop = false; +#endif + + /*Should we generate a Aync error event*/ + if (buffer == NULL || buffer->pInputPortPrivate == NULL) + { + DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy is invalid"); + return OMX_ErrorBadParameter; + } + + nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); + + if (nPortIndex > drv_ctx.ip_buf.actualcount) + { + DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy invalid nPortIndex[%u]", + nPortIndex); + return OMX_ErrorBadParameter; + } + + pending_input_buffers++; + + /* return zero length and not an EOS buffer */ + if (!arbitrary_bytes && (buffer->nFilledLen == 0) && + ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) + { + DEBUG_PRINT_HIGH("return zero legth buffer"); + post_event ((unsigned int)buffer,VDEC_S_SUCCESS, + OMX_COMPONENT_GENERATE_EBD); + return OMX_ErrorNone; + } + +#ifdef MAX_RES_1080P + if(codec_type_parse == CODEC_TYPE_MPEG4 || codec_type_parse == CODEC_TYPE_DIVX){ + mp4StreamType psBits; + psBits.data = (unsigned char *)(buffer->pBuffer + buffer->nOffset); + psBits.numBytes = buffer->nFilledLen; + mp4_headerparser.parseHeader(&psBits); + not_coded_vop = mp4_headerparser.is_notcodec_vop( + (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen); + if(not_coded_vop) { + DEBUG_PRINT_HIGH("Found Not coded vop len %d frame number %d", + buffer->nFilledLen,frame_count); + if(buffer->nFlags & OMX_BUFFERFLAG_EOS){ + DEBUG_PRINT_HIGH("Eos and Not coded Vop set len to zero"); + not_coded_vop = false; + buffer->nFilledLen = 0; + } + } + } +#endif + if(input_flush_progress == true +#ifdef MAX_RES_1080P + || not_coded_vop +#endif + ) + { + DEBUG_PRINT_LOW("Flush in progress return buffer "); + post_event ((unsigned int)buffer,VDEC_S_SUCCESS, + OMX_COMPONENT_GENERATE_EBD); + return OMX_ErrorNone; + } + + temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate; + + if ((temp_buffer - drv_ctx.ptr_inputbuffer) > drv_ctx.ip_buf.actualcount) + { + return OMX_ErrorBadParameter; + } + + DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); + /*for use buffer we need to memcpy the data*/ + temp_buffer->buffer_len = buffer->nFilledLen; + + if (input_use_buffer) + { + if (buffer->nFilledLen <= temp_buffer->buffer_len) + { + if(arbitrary_bytes) + { + memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen); + } + else + { + memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset), + buffer->nFilledLen); + } + } + else + { + return OMX_ErrorBadParameter; + } + + } + + frameinfo.bufferaddr = temp_buffer->bufferaddr; + frameinfo.client_data = (void *) buffer; + frameinfo.datalen = temp_buffer->buffer_len; + frameinfo.flags = 0; + frameinfo.offset = buffer->nOffset; + frameinfo.pmem_fd = temp_buffer->pmem_fd; + frameinfo.pmem_offset = temp_buffer->offset; + frameinfo.timestamp = buffer->nTimeStamp; + if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) + { + DEBUG_PRINT_LOW("ETB: dmx enabled"); + if (m_demux_entries == 0) + { + extract_demux_addr_offsets(buffer); + } + + DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%d",m_demux_entries); + handle_demux_data(buffer); + frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr; + frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size; + } + else + { + frameinfo.desc_addr = NULL; + frameinfo.desc_size = 0; + } + if(!arbitrary_bytes) + { + frameinfo.flags |= buffer->nFlags; + } + + +#ifdef _ANDROID_ + if (m_debug_timestamp) + { + if(arbitrary_bytes) + { + DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); + m_timestamp_list.insert_ts(buffer->nTimeStamp); + } + else if(!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) + { + DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); + m_timestamp_list.insert_ts(buffer->nTimeStamp); + } + } +#endif + +#ifdef INPUT_BUFFER_LOG + if (inputBufferFile1) + { + fwrite((const char *)temp_buffer->bufferaddr, + temp_buffer->buffer_len,1,inputBufferFile1); + } +#endif + + if(buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) + { + frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; + buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; + } + + if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) + { + DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached"); + frameinfo.flags |= VDEC_BUFFERFLAG_EOS; + h264_scratch.nFilledLen = 0; + nal_count = 0; + look_ahead_nal = false; + frame_count = 0; + if (m_frame_parser.mutils) + m_frame_parser.mutils->initialize_frame_checking_environment(); + m_frame_parser.flush(); + h264_last_au_ts = LLONG_MAX; + h264_last_au_flags = 0; + memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); + m_demux_entries = 0; + } + DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%d)", + frameinfo.bufferaddr, frameinfo.timestamp, frameinfo.datalen); + ioctl_msg.in = &frameinfo; + ioctl_msg.out = NULL; + if (ioctl(drv_ctx.video_driver_fd,VDEC_IOCTL_DECODE_FRAME, + &ioctl_msg) < 0) + { + /*Generate an async error and move to invalid state*/ + DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy VDEC_IOCTL_DECODE_FRAME failed"); + if (!arbitrary_bytes) + { + DEBUG_PRINT_LOW("Return failed buffer"); + post_event ((unsigned int)buffer,VDEC_S_SUCCESS, + OMX_COMPONENT_GENERATE_EBD); + } + return OMX_ErrorBadParameter; + } else + time_stamp_dts.insert_timestamp(buffer); + + return ret; +} + +/* ====================================================================== +FUNCTION + omx_vdec::FillThisBuffer + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("FTB in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if (!m_out_bEnabled) + { + DEBUG_PRINT_ERROR("\nERROR:FTB incorrect state operation, output port is disabled."); + return OMX_ErrorIncorrectStateOperation; + } + + if (buffer == NULL || ((buffer - m_out_mem_ptr) >= drv_ctx.op_buf.actualcount)) + { + return OMX_ErrorBadParameter; + } + + if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) + { + DEBUG_PRINT_ERROR("\nERROR:FTB invalid port in header %d", buffer->nOutputPortIndex); + return OMX_ErrorBadPortIndex; + } + + DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); + post_event((unsigned) hComp, (unsigned)buffer,OMX_COMPONENT_GENERATE_FTB); + return OMX_ErrorNone; +} +/* ====================================================================== +FUNCTION + omx_vdec::fill_this_buffer_proxy + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd) +{ + OMX_ERRORTYPE nRet = OMX_ErrorNone; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + OMX_BUFFERHEADERTYPE *buffer = bufferAdd; + struct vdec_fillbuffer_cmd fillbuffer; + struct vdec_bufferpayload *ptr_outputbuffer = NULL; + struct vdec_output_frameinfo *ptr_respbuffer = NULL; + + + if (bufferAdd == NULL || ((buffer - m_out_mem_ptr) > + drv_ctx.op_buf.actualcount) ) + return OMX_ErrorBadParameter; + + DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p", + bufferAdd, bufferAdd->pBuffer); + /*Return back the output buffer to client*/ + if(m_out_bEnabled != OMX_TRUE || output_flush_progress == true) + { + DEBUG_PRINT_LOW("Output Buffers return flush/disable condition"); + buffer->nFilledLen = 0; + m_cb.FillBufferDone (hComp,m_app_data,buffer); + return OMX_ErrorNone; + } + pending_output_buffers++; + ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate; + if (ptr_respbuffer) + { + ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data; + } + + if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) + { + DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL"); + buffer->nFilledLen = 0; + m_cb.FillBufferDone (hComp,m_app_data,buffer); + pending_output_buffers--; + return OMX_ErrorBadParameter; + } + + memcpy (&fillbuffer.buffer,ptr_outputbuffer,\ + sizeof(struct vdec_bufferpayload)); + fillbuffer.client_data = bufferAdd; + +#ifdef _ANDROID_ICS_ + if (m_enable_android_native_buffers) + { + // Acquire a write lock on this buffer. + if (GENLOCK_NO_ERROR != genlock_lock_buffer(native_buffer[buffer - m_out_mem_ptr].nativehandle, + GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) { + DEBUG_PRINT_ERROR("Failed to acquire genlock"); + buffer->nFilledLen = 0; + m_cb.FillBufferDone (hComp,m_app_data,buffer); + pending_output_buffers--; + return OMX_ErrorInsufficientResources; + } else { + native_buffer[buffer - m_out_mem_ptr].inuse = true; + } + } +#endif + + ioctl_msg.in = &fillbuffer; + ioctl_msg.out = NULL; + if (ioctl (drv_ctx.video_driver_fd, + VDEC_IOCTL_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n Decoder frame failed"); +#ifdef _ANDROID_ICS_ + if (m_enable_android_native_buffers) + { + // Unlock the buffer + if (GENLOCK_NO_ERROR != genlock_unlock_buffer(native_buffer[buffer - m_out_mem_ptr].nativehandle)) { + DEBUG_PRINT_ERROR("Releasing genlock failed"); + return OMX_ErrorInsufficientResources; + } else { + native_buffer[buffer - m_out_mem_ptr].inuse = false; + } + } +#endif + m_cb.FillBufferDone (hComp,m_app_data,buffer); + pending_output_buffers--; + return OMX_ErrorBadParameter; + } + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::SetCallbacks + +DESCRIPTION + Set the callbacks. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_CALLBACKTYPE* callbacks, + OMX_IN OMX_PTR appData) +{ + + m_cb = *callbacks; + DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\ + m_cb.EventHandler,m_cb.FillBufferDone); + m_app_data = appData; + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_vdec::ComponentDeInit + +DESCRIPTION + Destroys the component and release memory allocated to the heap. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp) +{ +#ifdef _ANDROID_ + if(iDivXDrmDecrypt) + { + delete iDivXDrmDecrypt; + iDivXDrmDecrypt=NULL; + } +#endif //_ANDROID_ + int i = 0; + if (OMX_StateLoaded != m_state) + { + DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d\n",\ + m_state); + DEBUG_PRINT_ERROR("\nPlayback Ended - FAILED"); + } + else + { + DEBUG_PRINT_HIGH("Playback Ended - PASSED"); + } + + /*Check if the output buffers have to be cleaned up*/ + if(m_out_mem_ptr) + { + DEBUG_PRINT_LOW("Freeing the Output Memory"); + for (i=0; i < drv_ctx.op_buf.actualcount; i++ ) + { + free_output_buffer (&m_out_mem_ptr[i]); +#ifdef _ANDROID_ICS_ + if (m_enable_android_native_buffers) + { + if (native_buffer[i].inuse) + { + if (GENLOCK_NO_ERROR != genlock_unlock_buffer(native_buffer[i].nativehandle)) { + DEBUG_PRINT_ERROR("Unlocking genlock failed"); + } + native_buffer[i].inuse = false; + } + } +#endif + } +#ifdef _ANDROID_ICS_ + memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); +#endif + } + + /*Check if the input buffers have to be cleaned up*/ + if(m_inp_mem_ptr || m_inp_heap_ptr) + { + DEBUG_PRINT_LOW("Freeing the Input Memory"); + for (i=0; i. + +PARAMETERS + . + +RETURN VALUE + Not Implemented error. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN void* eglImage) +{ + OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list; + OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry; + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info; + +#ifdef USE_EGL_IMAGE_GPU + PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc; + EGLint fd = -1, offset = 0,pmemPtr = 0; +#else + int fd = -1, offset = 0; +#endif + DEBUG_PRINT_HIGH("use EGL image support for decoder"); + if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) { + DEBUG_PRINT_ERROR("\n "); + } +#ifdef USE_EGL_IMAGE_GPU + if(m_display_id == NULL) { + DEBUG_PRINT_ERROR("Display ID is not set by IL client \n"); + return OMX_ErrorInsufficientResources; + } + egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC) + eglGetProcAddress("eglQueryImageKHR"); + egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE_QCOM,&fd); + egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET_QCOM,&offset); + egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR,&pmemPtr); +#else //with OMX test app + struct temp_egl { + int pmem_fd; + int offset; + }; + struct temp_egl *temp_egl_id = NULL; + void * pmemPtr = (void *) eglImage; + temp_egl_id = (struct temp_egl *)eglImage; + if (temp_egl_id != NULL) + { + fd = temp_egl_id->pmem_fd; + offset = temp_egl_id->offset; + } +#endif + if (fd < 0) { + DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d \n",fd); + return OMX_ErrorInsufficientResources; + } + pmem_info.pmem_fd = (OMX_U32) fd; + pmem_info.offset = (OMX_U32) offset; + pmem_entry.entry = (void *) &pmem_info; + pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; + pmem_list.entryList = &pmem_entry; + pmem_list.nEntries = 1; + ouput_egl_buffers = true; + if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port, + (void *)&pmem_list, drv_ctx.op_buf.buffer_size, + (OMX_U8 *)pmemPtr)) { + DEBUG_PRINT_ERROR("use buffer call failed for egl image\n"); + return OMX_ErrorInsufficientResources; + } + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::ComponentRoleEnum + +DESCRIPTION + OMX Component Role Enum method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_U8* role, + OMX_IN OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s",role); + } + else + { + eRet = OMX_ErrorNoMore; + } + } + if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s",role); + } + else + { + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s",role); + } + else + { + DEBUG_PRINT_LOW("No more roles"); + eRet = OMX_ErrorNoMore; + } + } +#ifdef MAX_RES_1080P + else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) || + (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE)) + ) +#else + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) +#endif + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s",role); + } + else + { + DEBUG_PRINT_LOW("No more roles"); + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s",role); + } + else + { + DEBUG_PRINT_LOW("No more roles"); + eRet = OMX_ErrorNoMore; + } + } + else if( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) || + (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE)) + ) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s",role); + } + else + { + DEBUG_PRINT_LOW("No more roles"); + eRet = OMX_ErrorNoMore; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR:Querying Role on Unknown Component"); + eRet = OMX_ErrorInvalidComponentName; + } + return eRet; +} + + + + +/* ====================================================================== +FUNCTION + omx_vdec::AllocateDone + +DESCRIPTION + Checks if entire buffer pool is allocated by IL Client or not. + Need this to move to IDLE state. + +PARAMETERS + None. + +RETURN VALUE + true/false. + +========================================================================== */ +bool omx_vdec::allocate_done(void) +{ + bool bRet = false; + bool bRet_In = false; + bool bRet_Out = false; + + bRet_In = allocate_input_done(); + bRet_Out = allocate_output_done(); + + if(bRet_In && bRet_Out) + { + bRet = true; + } + + return bRet; +} +/* ====================================================================== +FUNCTION + omx_vdec::AllocateInputDone + +DESCRIPTION + Checks if I/P buffer pool is allocated by IL Client or not. + +PARAMETERS + None. + +RETURN VALUE + true/false. + +========================================================================== */ +bool omx_vdec::allocate_input_done(void) +{ + bool bRet = false; + unsigned i=0; + + if (m_inp_mem_ptr == NULL) + { + return bRet; + } + if(m_inp_mem_ptr ) + { + for(;i= drv_ctx.op_buf.actualcount) + { + DEBUG_PRINT_ERROR("\n [FBD] ERROR in ptr(%p)", buffer); + return OMX_ErrorBadParameter; + } + else if (output_flush_progress) + { + DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer); + buffer->nFilledLen = 0; + buffer->nTimeStamp = 0; + buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; + buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; + buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT; + } + +#ifdef _ANDROID_ + char value[PROPERTY_VALUE_MAX]; + property_get("vidc.dec.debug.panframedata", value, NULL); + + if (atoi(value)) + { + if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) + { + DEBUG_PRINT_HIGH("\n"); + DEBUG_PRINT_HIGH("***************************************************\n"); + DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received\n"); + DEBUG_PRINT_HIGH("***************************************************\n"); + } + + if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) + { + DEBUG_PRINT_HIGH("\n"); + DEBUG_PRINT_HIGH("***************************************************\n"); + DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received\n"); + DEBUG_PRINT_HIGH("***************************************************\n"); + } + } +#endif + + DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p", + buffer, buffer->pBuffer); + pending_output_buffers --; + + if (buffer->nFlags & OMX_BUFFERFLAG_EOS) + { + DEBUG_PRINT_HIGH("Output EOS has been reached"); + if (!output_flush_progress) + post_event(NULL,NULL,OMX_COMPONENT_GENERATE_EOS_DONE); + + if (psource_frame) + { + m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame); + psource_frame = NULL; + } + if (pdest_frame) + { + pdest_frame->nFilledLen = 0; + m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL); + pdest_frame = NULL; + } + } + + DEBUG_PRINT_LOW("In fill Buffer done call address %p ",buffer); +#ifdef OUTPUT_BUFFER_LOG + if (outputBufferFile1) + { + OMX_U32 index = buffer - m_out_mem_ptr; + OMX_U8* pBuffer = (OMX_U8 *)drv_ctx.ptr_outputbuffer[index].bufferaddr; + + fwrite (pBuffer,1,buffer->nFilledLen, + outputBufferFile1); + } +#endif + + /* For use buffer we need to copy the data */ + if (!output_flush_progress) + { + time_stamp_dts.get_next_timestamp(buffer, + (drv_ctx.interlace != VDEC_InterlaceFrameProgressive) + ?true:false); + } + if (m_cb.FillBufferDone) + { + if (buffer->nFilledLen > 0) + { + if (client_extradata) + handle_extradata(buffer); + if (client_extradata & OMX_TIMEINFO_EXTRADATA) + // Keep min timestamp interval to handle corrupted bit stream scenario + set_frame_rate(buffer->nTimeStamp); + else if (arbitrary_bytes) + adjust_timestamp(buffer->nTimeStamp); +#ifdef _ANDROID_ + if (perf_flag) + { + if (!proc_frms) + { + dec_time.stop(); + latency = dec_time.processing_time_us() - latency; + DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3); + dec_time.start(); + fps_metrics.start(); + } + proc_frms++; + if (buffer->nFlags & OMX_BUFFERFLAG_EOS) + { + OMX_U64 proc_time = 0; + fps_metrics.stop(); + proc_time = fps_metrics.processing_time_us(); + DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%lu) proc_time(%.2f)S fps(%.2f)", + proc_frms, (float)proc_time / 1e6, + (float)(1e6 * proc_frms) / proc_time); + proc_frms = 0; + } + } +#endif //_ANDROID_ + +#ifdef OUTPUT_EXTRADATA_LOG + if (outputExtradataFile) + { + + OMX_U32 index = buffer - m_out_mem_ptr; + OMX_U8* pBuffer = (OMX_U8 *)drv_ctx.ptr_outputbuffer[index].bufferaddr; + + OMX_OTHER_EXTRADATATYPE *p_extra = NULL; + p_extra = (OMX_OTHER_EXTRADATATYPE *) + ((unsigned)(pBuffer + buffer->nOffset + + buffer->nFilledLen + 3)&(~3)); + while(p_extra && + (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) + { + DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%d",p_extra->nSize, p_extra->eType); + fwrite (p_extra,1,p_extra->nSize,outputExtradataFile); + if (p_extra->eType == OMX_ExtraDataNone) + { + break; + } + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + } + } +#endif + } + if (buffer->nFlags & OMX_BUFFERFLAG_EOS){ + prev_ts = LLONG_MAX; + rst_prev_ts = true; + } + + pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) + buffer->pPlatformPrivate)->entryList->entry; + DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %d",pPMEMInfo->pmem_fd); +#ifdef _ANDROID_ICS_ + if (m_enable_android_native_buffers) + { + if (native_buffer[buffer - m_out_mem_ptr].inuse) { + if (GENLOCK_NO_ERROR != genlock_unlock_buffer(native_buffer[buffer - m_out_mem_ptr].nativehandle)) { + DEBUG_PRINT_ERROR("Unlocking genlock failed"); + return OMX_ErrorInsufficientResources; + } + else { + native_buffer[buffer - m_out_mem_ptr].inuse = false; + } + } + } +#endif + m_cb.FillBufferDone (hComp,m_app_data,buffer); + DEBUG_PRINT_LOW("After Fill Buffer Done callback %d",pPMEMInfo->pmem_fd); + } + else + { + return OMX_ErrorBadParameter; + } + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + + if (buffer == NULL || ((buffer - m_inp_mem_ptr) > drv_ctx.ip_buf.actualcount)) + { + DEBUG_PRINT_ERROR("\n empty_buffer_done: ERROR bufhdr = %p", buffer); + return OMX_ErrorBadParameter; + } + + DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p", + buffer, buffer->pBuffer); + pending_input_buffers--; + + if (arbitrary_bytes) + { + if (pdest_frame == NULL && input_flush_progress == false) + { + DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer); + pdest_frame = buffer; + buffer->nFilledLen = 0; + buffer->nTimeStamp = LLONG_MAX; + push_input_buffer (hComp); + } + else + { + DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer); + buffer->nFilledLen = 0; + if (!m_input_free_q.insert_entry((unsigned)buffer,NULL,NULL)) + { + DEBUG_PRINT_ERROR("\nERROR:i/p free Queue is FULL Error"); + } + } + } + else if(m_cb.EmptyBufferDone) + { + buffer->nFilledLen = 0; + if (input_use_buffer == true){ + buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr]; + } + m_cb.EmptyBufferDone(hComp ,m_app_data, buffer); + } + return OMX_ErrorNone; +} + + +int omx_vdec::async_message_process (void *context, void* message) +{ + omx_vdec* omx = NULL; + struct vdec_msginfo *vdec_msg = NULL; + OMX_BUFFERHEADERTYPE* omxhdr = NULL; + struct vdec_output_frameinfo *output_respbuf = NULL; + + if (context == NULL || message == NULL) + { + DEBUG_PRINT_ERROR("\n FATAL ERROR in omx_vdec::async_message_process NULL Check"); + return -1; + } + vdec_msg = (struct vdec_msginfo *)message; + + omx = reinterpret_cast(context); + +#ifdef _ANDROID_ + if (omx->m_debug_timestamp) + { + if ( (vdec_msg->msgcode == VDEC_MSG_RESP_OUTPUT_BUFFER_DONE) && + !(omx->output_flush_progress) ) + { + OMX_TICKS expected_ts = 0; + omx->m_timestamp_list.pop_min_ts(expected_ts); + DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list", + vdec_msg->msgdata.output_frame.time_stamp, expected_ts); + + if (vdec_msg->msgdata.output_frame.time_stamp != expected_ts) + { + DEBUG_PRINT_ERROR("\n ERROR in omx_vdec::async_message_process timestamp Check"); + } + } + } +#endif + + switch (vdec_msg->msgcode) + { + + case VDEC_MSG_EVT_HW_ERROR: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_HARDWARE_ERROR); + break; + + case VDEC_MSG_RESP_START_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_START_DONE); + break; + + case VDEC_MSG_RESP_STOP_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_STOP_DONE); + break; + + case VDEC_MSG_RESP_RESUME_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_RESUME_DONE); + break; + + case VDEC_MSG_RESP_PAUSE_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_PAUSE_DONE); + break; + + case VDEC_MSG_RESP_FLUSH_INPUT_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH); + break; + case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH); + break; + case VDEC_MSG_RESP_INPUT_FLUSHED: + case VDEC_MSG_RESP_INPUT_BUFFER_DONE: + + omxhdr = (OMX_BUFFERHEADERTYPE* )\ + vdec_msg->msgdata.input_frame_clientdata; + + + if (omxhdr == NULL || + ((omxhdr - omx->m_inp_mem_ptr) > omx->drv_ctx.ip_buf.actualcount) ) + { + omxhdr = NULL; + vdec_msg->status_code = VDEC_S_EFATAL; + } + + omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code, + OMX_COMPONENT_GENERATE_EBD); + break; + case VDEC_MSG_EVT_INFO_FIELD_DROPPED: + int64_t *timestamp; + timestamp = (int64_t *) malloc(sizeof(int64_t)); + if (timestamp) { + *timestamp = vdec_msg->msgdata.output_frame.time_stamp; + omx->post_event ((unsigned int)timestamp, vdec_msg->status_code, + OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED); + DEBUG_PRINT_HIGH("Field dropped time stamp is %lld", + vdec_msg->msgdata.output_frame.time_stamp); + } + break; + case VDEC_MSG_RESP_OUTPUT_FLUSHED: + case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: + omxhdr = (OMX_BUFFERHEADERTYPE*)vdec_msg->msgdata.output_frame.client_data; + DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) Pic_type(%u)", + omxhdr, vdec_msg->msgdata.output_frame.time_stamp, + vdec_msg->msgdata.output_frame.pic_type); + + /* update SYNCFRAME flag */ + if (omx->eCompressionFormat == OMX_VIDEO_CodingAVC) + { + /* set SYNCFRAME flag if picture type is IDR for h264 */ + if (vdec_msg->msgdata.output_frame.pic_type == PICTURE_TYPE_IDR) + vdec_msg->msgdata.output_frame.flags |= OMX_BUFFERFLAG_SYNCFRAME; + else + vdec_msg->msgdata.output_frame.flags &= ~OMX_BUFFERFLAG_SYNCFRAME; + } + else + { + /* set SYNCFRAME flag if picture type is I_TYPE */ + if (vdec_msg->msgdata.output_frame.pic_type == PICTURE_TYPE_I) + vdec_msg->msgdata.output_frame.flags |= OMX_BUFFERFLAG_SYNCFRAME; + else + vdec_msg->msgdata.output_frame.flags &= ~OMX_BUFFERFLAG_SYNCFRAME; + } + + if (omxhdr && omxhdr->pOutputPortPrivate && + ((omxhdr - omx->m_out_mem_ptr) < omx->drv_ctx.op_buf.actualcount) && + (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate + - omx->drv_ctx.ptr_respbuffer) < omx->drv_ctx.op_buf.actualcount)) + { + if (vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) + { + omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len; + omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset; + omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp; + omxhdr->nFlags = (vdec_msg->msgdata.output_frame.flags); + + output_respbuf = (struct vdec_output_frameinfo *)\ + omxhdr->pOutputPortPrivate; + output_respbuf->framesize.bottom = + vdec_msg->msgdata.output_frame.framesize.bottom; + output_respbuf->framesize.left = + vdec_msg->msgdata.output_frame.framesize.left; + output_respbuf->framesize.right = + vdec_msg->msgdata.output_frame.framesize.right; + output_respbuf->framesize.top = + vdec_msg->msgdata.output_frame.framesize.top; + output_respbuf->len = vdec_msg->msgdata.output_frame.len; + output_respbuf->offset = vdec_msg->msgdata.output_frame.offset; + output_respbuf->time_stamp = vdec_msg->msgdata.output_frame.time_stamp; + output_respbuf->flags = vdec_msg->msgdata.output_frame.flags; + output_respbuf->pic_type = vdec_msg->msgdata.output_frame.pic_type; + output_respbuf->interlaced_format = vdec_msg->msgdata.output_frame.interlaced_format; + output_respbuf->aspect_ratio_info = + vdec_msg->msgdata.output_frame.aspect_ratio_info; + + + if (omx->output_use_buffer) + memcpy ( omxhdr->pBuffer, + (vdec_msg->msgdata.output_frame.bufferaddr + + vdec_msg->msgdata.output_frame.offset), + vdec_msg->msgdata.output_frame.len ); + } + else + omxhdr->nFilledLen = 0; + omx->post_event ((unsigned int)omxhdr, vdec_msg->status_code, + OMX_COMPONENT_GENERATE_FBD); + } + else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) + omx->post_event (NULL, vdec_msg->status_code, + OMX_COMPONENT_GENERATE_EOS_DONE); + else + omx->post_event (NULL, vdec_msg->status_code, + OMX_COMPONENT_GENERATE_HARDWARE_ERROR); + break; + case VDEC_MSG_EVT_CONFIG_CHANGED: + DEBUG_PRINT_HIGH("Port settings changed"); + omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code, + OMX_COMPONENT_GENERATE_PORT_RECONFIG); + break; + case VDEC_MSG_EVT_INFO_CONFIG_CHANGED: + { + DEBUG_PRINT_HIGH("Port settings changed info"); + // get_buffer_req and populate port defn structure + OMX_ERRORTYPE eRet = OMX_ErrorNone; + omx->m_port_def.nPortIndex = 1; + eRet = omx->update_portdef(&(omx->m_port_def)); + omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code, + OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG); + break; + } + default: + break; + } + return 1; +} + +OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary ( + OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer + ) +{ + unsigned address,p2,id; + DEBUG_PRINT_LOW("Empty this arbitrary"); + + if (buffer == NULL) + { + return OMX_ErrorBadParameter; + } + DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); + DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %d, timestamp %u", + buffer->nFilledLen, buffer->nFlags, (unsigned)buffer->nTimeStamp); + + /* return zero length and not an EOS buffer */ + /* return buffer if input flush in progress */ + if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) && + ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) + { + DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress"); + m_cb.EmptyBufferDone (hComp,m_app_data,buffer); + return OMX_ErrorNone; + } + + if (psource_frame == NULL) + { + DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %d",buffer,buffer->nTimeStamp); + psource_frame = buffer; + DEBUG_PRINT_LOW("Try to Push One Input Buffer "); + push_input_buffer (hComp); + } + else + { + DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer); + if (!m_input_pending_q.insert_entry((unsigned)buffer,NULL,NULL)) + { + return OMX_ErrorBadParameter; + } + } + + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp) +{ + unsigned address,p2,id; + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pdest_frame == NULL || psource_frame == NULL) + { + /*Check if we have a destination buffer*/ + if (pdest_frame == NULL) + { + DEBUG_PRINT_LOW("Get a Destination buffer from the queue"); + if (m_input_free_q.m_size) + { + m_input_free_q.pop_entry(&address,&p2,&id); + pdest_frame = (OMX_BUFFERHEADERTYPE *)address; + pdest_frame->nFilledLen = 0; + pdest_frame->nTimeStamp = LLONG_MAX; + DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame); + } + } + + /*Check if we have a destination buffer*/ + if (psource_frame == NULL) + { + DEBUG_PRINT_LOW("Get a source buffer from the queue"); + if (m_input_pending_q.m_size) + { + m_input_pending_q.pop_entry(&address,&p2,&id); + psource_frame = (OMX_BUFFERHEADERTYPE *)address; + DEBUG_PRINT_LOW("Next source Buffer %p time stamp %d",psource_frame, + psource_frame->nTimeStamp); + DEBUG_PRINT_LOW("Next source Buffer flag %d length %d", + psource_frame->nFlags,psource_frame->nFilledLen); + + } + } + + } + + while ((pdest_frame != NULL) && (psource_frame != NULL)) + { + switch (codec_type_parse) + { + case CODEC_TYPE_MPEG4: + case CODEC_TYPE_H263: + case CODEC_TYPE_MPEG2: + ret = push_input_sc_codec(hComp); + break; + case CODEC_TYPE_H264: + ret = push_input_h264(hComp); + break; + case CODEC_TYPE_VC1: + ret = push_input_vc1(hComp); + break; + } + if (ret != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n Pushing input Buffer Failed"); + omx_report_error (); + break; + } + } + + return ret; +} + +OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp) +{ + OMX_U32 partial_frame = 1; + OMX_BOOL generate_ebd = OMX_TRUE; + unsigned address,p2,id; + + DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %d", + psource_frame,psource_frame->nTimeStamp); + if (m_frame_parser.parse_sc_frame(psource_frame, + pdest_frame,&partial_frame) == -1) + { + DEBUG_PRINT_ERROR("\n Error In Parsing Return Error"); + return OMX_ErrorBadParameter; + } + + if (partial_frame == 0) + { + DEBUG_PRINT_LOW("Frame size %d source %p frame count %d", + pdest_frame->nFilledLen,psource_frame,frame_count); + + + DEBUG_PRINT_LOW("TimeStamp updated %d",pdest_frame->nTimeStamp); + /*First Parsed buffer will have only header Hence skip*/ + if (frame_count == 0) + { + DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame "); +#ifdef MAX_RES_1080P + if(codec_type_parse == CODEC_TYPE_MPEG4 || + codec_type_parse == CODEC_TYPE_DIVX) { + mp4StreamType psBits; + psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset; + psBits.numBytes = pdest_frame->nFilledLen; + mp4_headerparser.parseHeader(&psBits); + } +#endif + frame_count++; + } + else + { + pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; + if(pdest_frame->nFilledLen) + { + /*Push the frame to the Decoder*/ + if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) + { + return OMX_ErrorBadParameter; + } + frame_count++; + pdest_frame = NULL; + + if (m_input_free_q.m_size) + { + m_input_free_q.pop_entry(&address,&p2,&id); + pdest_frame = (OMX_BUFFERHEADERTYPE *) address; + pdest_frame->nFilledLen = 0; + } + } + else if(!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) + { + DEBUG_PRINT_ERROR("\nZero len buffer return back to POOL"); + m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL); + pdest_frame = NULL; + } + } + } + else + { + DEBUG_PRINT_LOW("Not a Complete Frame %d",pdest_frame->nFilledLen); + /*Check if Destination Buffer is full*/ + if (pdest_frame->nAllocLen == + pdest_frame->nFilledLen + pdest_frame->nOffset) + { + DEBUG_PRINT_ERROR("\nERROR:Frame Not found though Destination Filled"); + return OMX_ErrorStreamCorrupt; + } + } + + if (psource_frame->nFilledLen == 0) + { + if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) + { + if (pdest_frame) + { + pdest_frame->nFlags |= psource_frame->nFlags; + DEBUG_PRINT_LOW("Frame Found start Decoding Size =%d TimeStamp = %x", + pdest_frame->nFilledLen,pdest_frame->nTimeStamp); + DEBUG_PRINT_LOW("Found a frame size = %d number = %d", + pdest_frame->nFilledLen,frame_count++); + /*Push the frame to the Decoder*/ + if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) + { + return OMX_ErrorBadParameter; + } + frame_count++; + pdest_frame = NULL; + } + else + { + DEBUG_PRINT_LOW("Last frame in else dest addr") ; + generate_ebd = OMX_FALSE; + } + } + if(generate_ebd) + { + DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame); + m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame); + psource_frame = NULL; + + if (m_input_pending_q.m_size) + { + DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame); + m_input_pending_q.pop_entry(&address,&p2,&id); + psource_frame = (OMX_BUFFERHEADERTYPE *) address; + DEBUG_PRINT_LOW("Next source Buffer %p time stamp %d",psource_frame, + psource_frame->nTimeStamp); + DEBUG_PRINT_LOW("Next source Buffer flag %d length %d", + psource_frame->nFlags,psource_frame->nFilledLen); + } + } + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp) +{ + OMX_U32 partial_frame = 1; + unsigned address,p2,id; + OMX_BOOL isNewFrame = OMX_FALSE; + OMX_BOOL generate_ebd = OMX_TRUE; + + if (h264_scratch.pBuffer == NULL) + { + DEBUG_PRINT_ERROR("\nERROR:H.264 Scratch Buffer not allocated"); + return OMX_ErrorBadParameter; + } + DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %d " + "look_ahead_nal %d", h264_scratch.nFilledLen, look_ahead_nal); + DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %d",pdest_frame->nFilledLen); + if (h264_scratch.nFilledLen && look_ahead_nal) + { + look_ahead_nal = false; + if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= + h264_scratch.nFilledLen) + { + memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), + h264_scratch.pBuffer,h264_scratch.nFilledLen); + pdest_frame->nFilledLen += h264_scratch.nFilledLen; + DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame"); + h264_scratch.nFilledLen = 0; + } + else + { + DEBUG_PRINT_ERROR("\n Error:1: Destination buffer overflow for H264"); + return OMX_ErrorBadParameter; + } + } + if (nal_length == 0) + { + DEBUG_PRINT_LOW("Zero NAL, hence parse using start code"); + if (m_frame_parser.parse_sc_frame(psource_frame, + &h264_scratch,&partial_frame) == -1) + { + DEBUG_PRINT_ERROR("\n Error In Parsing Return Error"); + return OMX_ErrorBadParameter; + } + } + else + { + DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length); + if (m_frame_parser.parse_h264_nallength(psource_frame, + &h264_scratch,&partial_frame) == -1) + { + DEBUG_PRINT_ERROR("\n Error In Parsing NAL size, Return Error"); + return OMX_ErrorBadParameter; + } + } + + if (partial_frame == 0) + { + if (nal_count == 0 && h264_scratch.nFilledLen == 0) + { + DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip"); + nal_count++; + h264_scratch.nTimeStamp = psource_frame->nTimeStamp; + h264_scratch.nFlags = psource_frame->nFlags; + } + else + { + DEBUG_PRINT_LOW("Parsed New NAL Length = %d",h264_scratch.nFilledLen); + if(h264_scratch.nFilledLen) + { + h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen, + NALU_TYPE_SPS); +#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT + if (client_extradata & OMX_TIMEINFO_EXTRADATA) + h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, + h264_scratch.nFilledLen, NALU_TYPE_SEI); + else if (client_extradata & OMX_FRAMEINFO_EXTRADATA) + // If timeinfo is present frame info from SEI is already processed + h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, + h264_scratch.nFilledLen, NALU_TYPE_SEI); +#endif + m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame); + nal_count++; + if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) { + pdest_frame->nTimeStamp = h264_last_au_ts; + pdest_frame->nFlags = h264_last_au_flags; +#ifdef PANSCAN_HDLR + if (client_extradata & OMX_FRAMEINFO_EXTRADATA) + h264_parser->update_panscan_data(h264_last_au_ts); +#endif + } + if(m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR || + m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) { + h264_last_au_ts = h264_scratch.nTimeStamp; + h264_last_au_flags = h264_scratch.nFlags; +#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT + if (client_extradata & OMX_TIMEINFO_EXTRADATA) + { + OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts); + if (!VALID_TS(h264_last_au_ts)) + h264_last_au_ts = ts_in_sei; + } +#endif + } else + h264_last_au_ts = LLONG_MAX; + } + + if (!isNewFrame) + { + if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= + h264_scratch.nFilledLen) + { + DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %d", + h264_scratch.nFilledLen); + memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), + h264_scratch.pBuffer,h264_scratch.nFilledLen); + pdest_frame->nFilledLen += h264_scratch.nFilledLen; + if(m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ) + pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; + h264_scratch.nFilledLen = 0; + } + else + { + DEBUG_PRINT_ERROR("\n Error:2: Destination buffer overflow for H264"); + return OMX_ErrorBadParameter; + } + } + else + { + look_ahead_nal = true; + DEBUG_PRINT_LOW("Frame Found start Decoding Size =%d TimeStamp = %x", + pdest_frame->nFilledLen,pdest_frame->nTimeStamp); + DEBUG_PRINT_LOW("Found a frame size = %d number = %d", + pdest_frame->nFilledLen,frame_count++); + + if (pdest_frame->nFilledLen == 0) + { + DEBUG_PRINT_LOW("Copy the Current Frame since and push it"); + look_ahead_nal = false; + if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= + h264_scratch.nFilledLen) + { + memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), + h264_scratch.pBuffer,h264_scratch.nFilledLen); + pdest_frame->nFilledLen += h264_scratch.nFilledLen; + h264_scratch.nFilledLen = 0; + } + else + { + DEBUG_PRINT_ERROR("\n Error:3: Destination buffer overflow for H264"); + return OMX_ErrorBadParameter; + } + } + else + { + if(psource_frame->nFilledLen || h264_scratch.nFilledLen) + { + DEBUG_PRINT_LOW("Reset the EOS Flag"); + pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; + } + /*Push the frame to the Decoder*/ + if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) + { + return OMX_ErrorBadParameter; + } + //frame_count++; + pdest_frame = NULL; + if (m_input_free_q.m_size) + { + m_input_free_q.pop_entry(&address,&p2,&id); + pdest_frame = (OMX_BUFFERHEADERTYPE *) address; + DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame); + pdest_frame->nFilledLen = 0; + pdest_frame->nFlags = 0; + pdest_frame->nTimeStamp = LLONG_MAX; + } + } + } + } + } + else + { + DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %d",pdest_frame->nFilledLen); + /*Check if Destination Buffer is full*/ + if (h264_scratch.nAllocLen == + h264_scratch.nFilledLen + h264_scratch.nOffset) + { + DEBUG_PRINT_ERROR("\nERROR: Frame Not found though Destination Filled"); + return OMX_ErrorStreamCorrupt; + } + } + + if (!psource_frame->nFilledLen) + { + DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame); + + if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) + { + if (pdest_frame) + { + DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer"); + if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= + h264_scratch.nFilledLen) + { + memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), + h264_scratch.pBuffer,h264_scratch.nFilledLen); + pdest_frame->nFilledLen += h264_scratch.nFilledLen; + h264_scratch.nFilledLen = 0; + } + else + { + DEBUG_PRINT_ERROR("\nERROR:4: Destination buffer overflow for H264"); + return OMX_ErrorBadParameter; + } + pdest_frame->nTimeStamp = h264_scratch.nTimeStamp; + pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags; +#ifdef MAX_RES_720P + if (frame_count == 0) + { + DEBUG_PRINT_HIGH("No frames sent to driver yet, " + "So send zero length EOS buffer"); + pdest_frame->nFilledLen = 0; + } +#endif + DEBUG_PRINT_LOW("pdest_frame->nFilledLen = %d, nFlags = 0x%x, TimeStamp = %x", + pdest_frame->nFilledLen, pdest_frame->nFlags, pdest_frame->nTimeStamp); + DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++); +#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT + if (client_extradata & OMX_TIMEINFO_EXTRADATA) + { + OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp); + if (!VALID_TS(pdest_frame->nTimeStamp)) + pdest_frame->nTimeStamp = ts_in_sei; + } +#endif + /*Push the frame to the Decoder*/ + if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) + { + return OMX_ErrorBadParameter; + } + frame_count++; + pdest_frame = NULL; + } + else + { + DEBUG_PRINT_LOW("Last frame in else dest addr %p size %d", + pdest_frame,h264_scratch.nFilledLen); + generate_ebd = OMX_FALSE; + } + } + } + if(generate_ebd && !psource_frame->nFilledLen) + { + m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame); + psource_frame = NULL; + if (m_input_pending_q.m_size) + { + DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame); + m_input_pending_q.pop_entry(&address,&p2,&id); + psource_frame = (OMX_BUFFERHEADERTYPE *) address; + DEBUG_PRINT_LOW("Next source Buffer flag %d src length %d", + psource_frame->nFlags,psource_frame->nFilledLen); + } + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::push_input_vc1 (OMX_HANDLETYPE hComp) +{ + OMX_U8 *buf, *pdest; + OMX_U32 partial_frame = 1; + OMX_U32 buf_len, dest_len; + + if(first_frame == 0) + { + first_frame = 1; + DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes"); + if(!m_vendor_config.pData) + { + DEBUG_PRINT_LOW("Check profile type in 1st source buffer"); + buf = psource_frame->pBuffer; + buf_len = psource_frame->nFilledLen; + + if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) == + VC1_SP_MP_START_CODE) + { + m_vc1_profile = VC1_SP_MP_RCV; + } + else if(*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) + { + m_vc1_profile = VC1_AP; + } + else + { + DEBUG_PRINT_ERROR("\nInvalid sequence layer in first buffer"); + return OMX_ErrorStreamCorrupt; + } + } + else + { + pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen + + pdest_frame->nOffset; + dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen + + pdest_frame->nOffset); + + if(dest_len < m_vendor_config.nDataSize) + { + DEBUG_PRINT_ERROR("\nDestination buffer full"); + return OMX_ErrorBadParameter; + } + else + { + memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize); + pdest_frame->nFilledLen += m_vendor_config.nDataSize; + } + } + } + + switch(m_vc1_profile) + { + case VC1_AP: + DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code"); + if (push_input_sc_codec(hComp) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n Error In Parsing VC1 AP start code"); + return OMX_ErrorBadParameter; + } + break; + + case VC1_SP_MP_RCV: + default: + DEBUG_PRINT_ERROR("\n Unsupported VC1 profile in ArbitraryBytes Mode"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNone; +} + +#ifndef USE_ION +bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size, + OMX_U32 alignment) +{ + struct pmem_allocation allocation; + allocation.size = buffer_size; + allocation.align = clip2(alignment); + if (allocation.align < 4096) + { + allocation.align = 4096; + } + if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) + { + DEBUG_PRINT_ERROR("\n Aligment(%u) failed with pmem driver Sz(%lu)", + allocation.align, allocation.size); + return false; + } + return true; +} +#endif + +#ifdef USE_ION +int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size, + OMX_U32 alignment, struct ion_allocation_data *alloc_data, + struct ion_fd_data *fd_data,int flag) +{ + int fd = -EINVAL; + int rc = -EINVAL; + int ion_dev_flag; + struct vdec_ion ion_buf_info; + if (!alloc_data || buffer_size <= 0 || !fd_data) { + DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory\n"); + return -EINVAL; + } + if(!secure_mode && flag == CACHED) + { + ion_dev_flag = O_RDONLY; + } else { + ion_dev_flag = (O_RDONLY | O_DSYNC); + } + fd = open (MEM_DEVICE, ion_dev_flag); + if (fd < 0) { + DEBUG_PRINT_ERROR("opening ion device failed with fd = %d\n", fd); + return fd; + } + alloc_data->len = buffer_size; + alloc_data->align = clip2(alignment); + if (alloc_data->align < 4096) + { + alloc_data->align = 4096; + } + if(secure_mode) { + alloc_data->flags = (ION_HEAP(MEM_HEAP_ID) | ION_SECURE); + } else { +#ifdef MAX_RES_720P + alloc_data->len = (buffer_size + (alloc_data->align - 1)) & ~(alloc_data->align - 1); + alloc_data->flags = ION_HEAP(MEM_HEAP_ID); +#else + alloc_data->flags = (ION_HEAP(MEM_HEAP_ID) | ION_HEAP(ION_IOMMU_HEAP_ID)); +#endif + } + rc = ioctl(fd,ION_IOC_ALLOC,alloc_data); + if (rc || !alloc_data->handle) { + DEBUG_PRINT_ERROR("\n ION ALLOC memory failed "); + alloc_data->handle = NULL; + close(fd); + fd = -ENOMEM; + return fd; + } + fd_data->handle = alloc_data->handle; + rc = ioctl(fd,ION_IOC_MAP,fd_data); + if (rc) { + DEBUG_PRINT_ERROR("\n ION MAP failed "); + ion_buf_info.ion_alloc_data = *alloc_data; + ion_buf_info.ion_device_fd = fd; + ion_buf_info.fd_ion_data = *fd_data; + free_ion_memory(&ion_buf_info); + fd_data->fd =-1; + close(fd); + fd = -ENOMEM; + } + DEBUG_PRINT_HIGH("ION: alloc_data: handle(0x%X), len(%u), align(%u), " + "flags(0x%x), fd_data: handle(0x%x), fd(0x%x)", + alloc_data->handle, alloc_data->len, alloc_data->align, + alloc_data->flags, fd_data->handle, fd_data->fd); + return fd; +} + +void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info) { + + if(!buf_ion_info) { + DEBUG_PRINT_ERROR("\n ION: free called with invalid fd/allocdata"); + return; + } + DEBUG_PRINT_HIGH("ION: free: handle(0x%X), len(%u), fd(0x%x)", + buf_ion_info->ion_alloc_data.handle, + buf_ion_info->ion_alloc_data.len, + buf_ion_info->fd_ion_data.fd); + if(ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE, + &buf_ion_info->ion_alloc_data.handle)) { + DEBUG_PRINT_ERROR("\n ION: free failed" ); + } + close(buf_ion_info->ion_device_fd); + buf_ion_info->ion_device_fd = -1; + buf_ion_info->ion_alloc_data.handle = NULL; + buf_ion_info->fd_ion_data.fd = -1; +} +#endif +void omx_vdec::free_output_buffer_header() +{ + DEBUG_PRINT_HIGH("ALL output buffers are freed/released"); + output_use_buffer = false; + ouput_egl_buffers = false; + + if (m_out_mem_ptr) + { + free (m_out_mem_ptr); + m_out_mem_ptr = NULL; + } + + if(m_platform_list) + { + free(m_platform_list); + m_platform_list = NULL; + } + + if (drv_ctx.ptr_respbuffer) + { + free (drv_ctx.ptr_respbuffer); + drv_ctx.ptr_respbuffer = NULL; + } + if (drv_ctx.ptr_outputbuffer) + { + free (drv_ctx.ptr_outputbuffer); + drv_ctx.ptr_outputbuffer = NULL; + } +#ifdef USE_ION + if (drv_ctx.op_buf_ion_info) { + DEBUG_PRINT_LOW("Free o/p ion context"); + free(drv_ctx.op_buf_ion_info); + drv_ctx.op_buf_ion_info = NULL; + } +#endif +} + +void omx_vdec::free_input_buffer_header() +{ + input_use_buffer = false; + if (arbitrary_bytes) + { + if (m_frame_parser.mutils) + { + DEBUG_PRINT_LOW("Free utils parser"); + delete (m_frame_parser.mutils); + m_frame_parser.mutils = NULL; + } + + if (m_inp_heap_ptr) + { + DEBUG_PRINT_LOW("Free input Heap Pointer"); + free (m_inp_heap_ptr); + m_inp_heap_ptr = NULL; + } + + if (m_phdr_pmem_ptr) + { + DEBUG_PRINT_LOW("Free input pmem header Pointer"); + free (m_phdr_pmem_ptr); + m_phdr_pmem_ptr = NULL; + } + } + if (m_inp_mem_ptr) + { + DEBUG_PRINT_LOW("Free input pmem Pointer area"); + free (m_inp_mem_ptr); + m_inp_mem_ptr = NULL; + } + if (drv_ctx.ptr_inputbuffer) + { + DEBUG_PRINT_LOW("Free Driver Context pointer"); + free (drv_ctx.ptr_inputbuffer); + drv_ctx.ptr_inputbuffer = NULL; + } +#ifdef USE_ION + if (drv_ctx.ip_buf_ion_info) { + DEBUG_PRINT_LOW("Free ion context"); + free(drv_ctx.ip_buf_ion_info); + drv_ctx.ip_buf_ion_info = NULL; + } +#endif +} + +OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop) +{ + struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned int buf_size = 0, extra_data_size = 0; + DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%d)", + buffer_prop->actualcount, buffer_prop->buffer_size); + ioctl_msg.in = NULL; + ioctl_msg.out = buffer_prop; + if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_GET_BUFFER_REQ, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("Requesting buffer requirements failed"); + eRet = OMX_ErrorInsufficientResources; + } + else + { + buf_size = buffer_prop->buffer_size; + if (client_extradata & OMX_FRAMEINFO_EXTRADATA) + { + DEBUG_PRINT_HIGH("Frame info extra data enabled!"); + extra_data_size += OMX_FRAMEINFO_EXTRADATA_SIZE; + } + if (client_extradata & OMX_INTERLACE_EXTRADATA) + { + DEBUG_PRINT_HIGH("Interlace extra data enabled!"); + extra_data_size += OMX_INTERLACE_EXTRADATA_SIZE; + } + if (client_extradata & OMX_PORTDEF_EXTRADATA) + { + extra_data_size += OMX_PORTDEF_EXTRADATA_SIZE; + DEBUG_PRINT_HIGH("Smooth streaming enabled extra_data_size=%d", + extra_data_size); + } + if (extra_data_size) + { + extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator + buf_size = ((buf_size + 3)&(~3)); //Align extradata start address to 64Bit + } + buf_size += extra_data_size; + buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); + DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%d) BufSize(%d)", + buffer_prop->actualcount, buffer_prop->buffer_size, buf_size); + if (in_reconfig) // BufReq will be set to driver when port is disabled + buffer_prop->buffer_size = buf_size; + else if (buf_size != buffer_prop->buffer_size) + { + buffer_prop->buffer_size = buf_size; + eRet = set_buffer_req(buffer_prop); + } + } + DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%d)", + buffer_prop->actualcount, buffer_prop->buffer_size); + return eRet; +} + +OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop) +{ + struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned buf_size = 0; + DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%d)", + buffer_prop->actualcount, buffer_prop->buffer_size); + buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); + if (buf_size != buffer_prop->buffer_size) + { + DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%d) Required(%d)", + buffer_prop->buffer_size, buf_size); + eRet = OMX_ErrorBadParameter; + } + else + { + ioctl_msg.in = buffer_prop; + ioctl_msg.out = NULL; + if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_BUFFER_REQ, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("Setting buffer requirements failed"); + eRet = OMX_ErrorInsufficientResources; + } + } + return eRet; +} + +OMX_ERRORTYPE omx_vdec::start_port_reconfig() +{ + struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; + OMX_ERRORTYPE eRet = OMX_ErrorNone; + eRet = update_picture_resolution(); + if (eRet == OMX_ErrorNone) + { + ioctl_msg.out = &drv_ctx.interlace; + if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_GET_INTERLACE_FORMAT, &ioctl_msg)) + { + DEBUG_PRINT_ERROR("Error VDEC_IOCTL_GET_INTERLACE_FORMAT"); + eRet = OMX_ErrorHardware; + } + else + { + if (drv_ctx.interlace != VDEC_InterlaceFrameProgressive) + { + DEBUG_PRINT_HIGH("Interlace format detected (%x)!", drv_ctx.interlace); + if(!secure_mode) + client_extradata |= OMX_INTERLACE_EXTRADATA; + else { + DEBUG_PRINT_ERROR("secure mode interlaced format not supported"); + eRet = OMX_ErrorUnsupportedSetting; + } + } + in_reconfig = true; + op_buf_rcnfg.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + eRet = get_buffer_req(&op_buf_rcnfg); + } + } + return eRet; +} + +OMX_ERRORTYPE omx_vdec::update_picture_resolution() +{ + struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; + OMX_ERRORTYPE eRet = OMX_ErrorNone; + ioctl_msg.in = NULL; + ioctl_msg.out = &drv_ctx.video_resolution; + if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_GET_PICRES, &ioctl_msg)) + { + DEBUG_PRINT_ERROR("Error VDEC_IOCTL_GET_PICRES"); + eRet = OMX_ErrorHardware; + } + return eRet; +} + +OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if (!portDefn) + { + return OMX_ErrorBadParameter; + } + DEBUG_PRINT_LOW("omx_vdec::update_portdef"); + portDefn->nVersion.nVersion = OMX_SPEC_VERSION; + portDefn->nSize = sizeof(portDefn); + portDefn->eDomain = OMX_PortDomainVideo; + if (drv_ctx.frame_rate.fps_denominator > 0) + portDefn->format.video.xFramerate = drv_ctx.frame_rate.fps_numerator / + drv_ctx.frame_rate.fps_denominator; + else { + DEBUG_PRINT_ERROR("Error: Divide by zero \n"); + return OMX_ErrorBadParameter; + } + if (0 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirInput; + portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount; + portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount; + portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size - DEVICE_SCRATCH; + portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused; + portDefn->format.video.eCompressionFormat = eCompressionFormat; + portDefn->bEnabled = m_inp_bEnabled; + portDefn->bPopulated = m_inp_bPopulated; + } + else if (1 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirOutput; + if (update_picture_resolution() != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("update_picture_resolution failed \n"); + return OMX_ErrorHardware; + } + if (in_reconfig) + { + portDefn->nBufferCountActual = op_buf_rcnfg.actualcount; + portDefn->nBufferCountMin = op_buf_rcnfg.mincount; + portDefn->nBufferSize = op_buf_rcnfg.buffer_size; + } + else + { + portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount; + portDefn->nBufferCountMin = drv_ctx.op_buf.mincount; + portDefn->nBufferSize = drv_ctx.op_buf.buffer_size; + } + portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + portDefn->bEnabled = m_out_bEnabled; + portDefn->bPopulated = m_out_bPopulated; + if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) + portDefn->format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + else if (drv_ctx.output_format == VDEC_YUV_FORMAT_TILE_4x2) + portDefn->format.video.eColorFormat = (OMX_COLOR_FORMATTYPE) + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; + else + { + DEBUG_PRINT_ERROR("ERROR: Color format unknown: %x\n", drv_ctx.output_format); + } + } + else + { + portDefn->eDir = OMX_DirMax; + DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d", + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height; + portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width; + portDefn->format.video.nStride = drv_ctx.video_resolution.stride; + portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines; + DEBUG_PRINT_LOW("update_portdef: PortIndex = %u, Width = %d Height = %d " + "Stride = %u SliceHeight = %u output format = 0x%x, eColorFormat = 0x%x", + portDefn->nPortIndex, + portDefn->format.video.nFrameHeight, + portDefn->format.video.nFrameWidth, + portDefn->format.video.nStride, + portDefn->format.video.nSliceHeight, + drv_ctx.output_format, + portDefn->format.video.eColorFormat); + return eRet; +} + +OMX_ERRORTYPE omx_vdec::allocate_output_headers() +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr = NULL; + unsigned i= 0; + + if(!m_out_mem_ptr) { + DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation"); + int nBufHdrSize = 0; + int nPlatformEntrySize = 0; + int nPlatformListSize = 0; + int nPMEMInfoSize = 0; + OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; + OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; + + DEBUG_PRINT_LOW("Setting First Output Buffer(%d)", + drv_ctx.op_buf.actualcount); + nBufHdrSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_BUFFERHEADERTYPE); + + nPMEMInfoSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); + nPlatformListSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); + nPlatformEntrySize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); + + DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d",nBufHdrSize, + sizeof(OMX_BUFFERHEADERTYPE), + nPMEMInfoSize, + nPlatformListSize); + DEBUG_PRINT_LOW("PE %d bmSize %d ",nPlatformEntrySize, + m_out_bm_count); + m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); + // Alloc mem for platform specific info + char *pPtr=NULL; + pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + + nPMEMInfoSize,1); + drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \ + calloc (sizeof(struct vdec_bufferpayload), + drv_ctx.op_buf.actualcount); + drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ + calloc (sizeof (struct vdec_output_frameinfo), + drv_ctx.op_buf.actualcount); +#ifdef USE_ION + drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \ + calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount); +#endif + + if(m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer + && drv_ctx.ptr_respbuffer) + { + bufHdr = m_out_mem_ptr; + m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); + m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) + (((char *) m_platform_list) + nPlatformListSize); + m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + (((char *) m_platform_entry) + nPlatformEntrySize); + pPlatformList = m_platform_list; + pPlatformEntry = m_platform_entry; + pPMEMInfo = m_pmem_info; + + DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr); + + // Settting the entire storage nicely + DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, + m_out_mem_ptr,pPlatformEntry); + DEBUG_PRINT_LOW(" Pmem Info = %p ",pPMEMInfo); + for(i=0; i < drv_ctx.op_buf.actualcount ; i++) + { + bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + // Set the values when we determine the right HxW param + bufHdr->nAllocLen = 0; + bufHdr->nFilledLen = 0; + bufHdr->pAppPrivate = NULL; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; + pPlatformEntry->entry = pPMEMInfo; + // Initialize the Platform List + pPlatformList->nEntries = 1; + pPlatformList->entryList = pPlatformEntry; + // Keep pBuffer NULL till vdec is opened + bufHdr->pBuffer = NULL; + pPMEMInfo->offset = 0; + pPMEMInfo->pmem_fd = 0; + bufHdr->pPlatformPrivate = pPlatformList; + drv_ctx.ptr_outputbuffer[i].pmem_fd = -1; +#ifdef USE_ION + drv_ctx.op_buf_ion_info[i].ion_device_fd =-1; +#endif + /*Create a mapping between buffers*/ + bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; + drv_ctx.ptr_respbuffer[i].client_data = (void *) \ + &drv_ctx.ptr_outputbuffer[i]; + // Move the buffer and buffer header pointers + bufHdr++; + pPMEMInfo++; + pPlatformEntry++; + pPlatformList++; + } + } + else + { + DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%x][0x%x]\n",\ + m_out_mem_ptr, pPtr); + if(m_out_mem_ptr) + { + free(m_out_mem_ptr); + m_out_mem_ptr = NULL; + } + if(pPtr) + { + free(pPtr); + pPtr = NULL; + } + if(drv_ctx.ptr_outputbuffer) + { + free(drv_ctx.ptr_outputbuffer); + drv_ctx.ptr_outputbuffer = NULL; + } + if(drv_ctx.ptr_respbuffer) + { + free(drv_ctx.ptr_respbuffer); + drv_ctx.ptr_respbuffer = NULL; + } +#ifdef USE_ION + if (drv_ctx.op_buf_ion_info) { + DEBUG_PRINT_LOW("Free o/p ion context"); + free(drv_ctx.op_buf_ion_info); + drv_ctx.op_buf_ion_info = NULL; + } +#endif + eRet = OMX_ErrorInsufficientResources; + } + } else { + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +void omx_vdec::complete_pending_buffer_done_cbs() +{ + unsigned p1; + unsigned p2; + unsigned ident; + omx_cmd_queue tmp_q, pending_bd_q; + pthread_mutex_lock(&m_lock); + // pop all pending GENERATE FDB from ftb queue + while (m_ftb_q.m_size) + { + m_ftb_q.pop_entry(&p1,&p2,&ident); + if(ident == OMX_COMPONENT_GENERATE_FBD) + { + pending_bd_q.insert_entry(p1,p2,ident); + } + else + { + tmp_q.insert_entry(p1,p2,ident); + } + } + //return all non GENERATE FDB to ftb queue + while(tmp_q.m_size) + { + tmp_q.pop_entry(&p1,&p2,&ident); + m_ftb_q.insert_entry(p1,p2,ident); + } + // pop all pending GENERATE EDB from etb queue + while (m_etb_q.m_size) + { + m_etb_q.pop_entry(&p1,&p2,&ident); + if(ident == OMX_COMPONENT_GENERATE_EBD) + { + pending_bd_q.insert_entry(p1,p2,ident); + } + else + { + tmp_q.insert_entry(p1,p2,ident); + } + } + //return all non GENERATE FDB to etb queue + while(tmp_q.m_size) + { + tmp_q.pop_entry(&p1,&p2,&ident); + m_etb_q.insert_entry(p1,p2,ident); + } + pthread_mutex_unlock(&m_lock); + // process all pending buffer dones + while(pending_bd_q.m_size) + { + pending_bd_q.pop_entry(&p1,&p2,&ident); + switch(ident) + { + case OMX_COMPONENT_GENERATE_EBD: + if(empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\nERROR: empty_buffer_done() failed!\n"); + omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_FBD: + if(fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) + { + DEBUG_PRINT_ERROR("\nERROR: fill_buffer_done() failed!\n"); + omx_report_error (); + } + break; + } + } +} + +void omx_vdec::set_frame_rate(OMX_S64 act_timestamp) +{ + OMX_U32 new_frame_interval = 0; + struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; + if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts + && (((act_timestamp > prev_ts )? act_timestamp - prev_ts: prev_ts-act_timestamp)>2000)) + { + new_frame_interval = (act_timestamp > prev_ts)? + act_timestamp - prev_ts : + prev_ts - act_timestamp; + if (new_frame_interval < frm_int || frm_int == 0) + { + frm_int = new_frame_interval; + if(frm_int) + { + drv_ctx.frame_rate.fps_numerator = 1e6; + drv_ctx.frame_rate.fps_denominator = frm_int; + DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)", + frm_int, drv_ctx.frame_rate.fps_numerator / + (float)drv_ctx.frame_rate.fps_denominator); + ioctl_msg.in = &drv_ctx.frame_rate; + if (ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_FRAME_RATE, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("Setting frame rate failed"); + } + } + } + } + prev_ts = act_timestamp; +} + +void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp) +{ + if (rst_prev_ts && VALID_TS(act_timestamp)) + { + prev_ts = act_timestamp; + rst_prev_ts = false; + } + else if (VALID_TS(prev_ts)) + { + bool codec_cond = (drv_ctx.timestamp_adjust)? + (!VALID_TS(act_timestamp) || (((act_timestamp > prev_ts)? + (act_timestamp - prev_ts):(prev_ts - act_timestamp)) <= 2000)): + (!VALID_TS(act_timestamp) || act_timestamp == prev_ts); + if(frm_int > 0 && codec_cond) + { + DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp); + act_timestamp = prev_ts + frm_int; + DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp); + prev_ts = act_timestamp; + } + else + set_frame_rate(act_timestamp); + } + else if (frm_int > 0) // In this case the frame rate was set along + { // with the port definition, start ts with 0 + act_timestamp = prev_ts = 0; // and correct if a valid ts is received. + rst_prev_ts = true; + } +} + +void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) +{ + OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL; + OMX_U32 num_conceal_MB = 0; + OMX_S64 ts_in_sei = 0; + OMX_U32 frame_rate = 0; + + OMX_U32 index = p_buf_hdr - m_out_mem_ptr; + OMX_U8* pBuffer = (OMX_U8 *)drv_ctx.ptr_outputbuffer[index].bufferaddr; + + p_extra = (OMX_OTHER_EXTRADATATYPE *) + ((unsigned)(pBuffer + p_buf_hdr->nOffset + + p_buf_hdr->nFilledLen + 3)&(~3)); + if ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen)) + p_extra = NULL; + if (drv_ctx.extradata && (p_buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA)) + { + // Process driver extradata + while(p_extra && p_extra->eType != VDEC_EXTRADATA_NONE) + { + DEBUG_PRINT_LOW("handle_extradata : pBuf(%p) BufTS(%lld) Type(%x) DataSz(%u)", + p_buf_hdr, p_buf_hdr->nTimeStamp, p_extra->eType, p_extra->nDataSize); + if (p_extra->nSize < p_extra->nDataSize) + { + DEBUG_PRINT_ERROR(" \n Corrupt metadata Buffer size %d payload size %d", + p_extra->nSize, p_extra->nDataSize); + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + if ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen) || + p_extra->nDataSize == 0 || p_extra->nSize == 0) + p_extra = NULL; + continue; + } + if (p_extra->eType == VDEC_EXTRADATA_MB_ERROR_MAP) + { + if (client_extradata & OMX_FRAMEINFO_EXTRADATA) + num_conceal_MB = count_MB_in_extradata(p_extra); + if (client_extradata & VDEC_EXTRADATA_MB_ERROR_MAP) + // Map driver extradata to corresponding OMX type + p_extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataConcealMB; + else + p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client +#ifdef _ANDROID_ + if (m_debug_concealedmb) { + DEBUG_PRINT_HIGH("Concealed MB percentage is %u", num_conceal_MB); + } +#endif /* _ANDROID_ */ + } + else if (p_extra->eType == VDEC_EXTRADATA_SEI) + { + p_sei = p_extra; +#ifdef MAX_RES_1080P + h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI); +#endif + p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client + } + else if (p_extra->eType == VDEC_EXTRADATA_VUI) + { + p_vui = p_extra; +#ifdef MAX_RES_1080P + h264_parser->parse_nal((OMX_U8*)p_vui->data, p_vui->nDataSize, NALU_TYPE_VUI, false); +#endif + p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client + } + print_debug_extradata(p_extra); + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + if ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen) || + p_extra->nDataSize == 0 || p_extra->nSize == 0) + p_extra = NULL; + } + if (!(client_extradata & VDEC_EXTRADATA_MB_ERROR_MAP)) + { + // Driver extradata is only exposed if MB map is requested by client, + // otherwise can be overwritten by omx extradata. + p_extra = (OMX_OTHER_EXTRADATATYPE *) + ((unsigned)(pBuffer + p_buf_hdr->nOffset + + p_buf_hdr->nFilledLen + 3)&(~3)); + p_buf_hdr->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; + } + } + +#ifdef PROCESS_EXTRADATA_IN_OUTPUT_PORT + if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + if (client_extradata & OMX_TIMEINFO_EXTRADATA) + { + if (p_vui) + h264_parser->parse_nal((OMX_U8*)p_vui->data, p_vui->nDataSize, NALU_TYPE_VUI, false); + if (p_sei) + h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI); + ts_in_sei = h264_parser->process_ts_with_sei_vui(p_buf_hdr->nTimeStamp); + if (!VALID_TS(p_buf_hdr->nTimeStamp)) + p_buf_hdr->nTimeStamp = ts_in_sei; + } + else if ((client_extradata & OMX_FRAMEINFO_EXTRADATA) && p_sei) + // If timeinfo is present frame info from SEI is already processed + h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI); + } +#endif + if ((client_extradata & OMX_INTERLACE_EXTRADATA) && p_extra && + ((OMX_U8*)p_extra + OMX_INTERLACE_EXTRADATA_SIZE) < + (pBuffer + p_buf_hdr->nAllocLen)) + { + p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; + append_interlace_extradata(p_extra, + ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->interlaced_format); + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + } + if (client_extradata & OMX_FRAMEINFO_EXTRADATA && p_extra && + ((OMX_U8*)p_extra + OMX_FRAMEINFO_EXTRADATA_SIZE) < + (pBuffer + p_buf_hdr->nAllocLen)) + { + p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; + /* vui extra data (frame_rate) information */ + if (h264_parser) + h264_parser->get_frame_rate(&frame_rate); + append_frame_info_extradata(p_extra, num_conceal_MB, + ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, + p_buf_hdr->nTimeStamp, frame_rate, + &((struct vdec_output_frameinfo *) + p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info); + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + } + if ((client_extradata & OMX_PORTDEF_EXTRADATA) && + p_extra != NULL && + ((OMX_U8*)p_extra + OMX_PORTDEF_EXTRADATA_SIZE) < + (pBuffer + p_buf_hdr->nAllocLen)) + { + p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; + append_portdef_extradata(p_extra); + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + } + if (p_buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA) + if (p_extra && + ((OMX_U8*)p_extra + OMX_FRAMEINFO_EXTRADATA_SIZE) < + (pBuffer + p_buf_hdr->nAllocLen)) + append_terminator_extradata(p_extra); + else + { + DEBUG_PRINT_ERROR("ERROR: Terminator extradata cannot be added"); + p_buf_hdr->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; + } +} + +OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata, bool enable) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_U32 driver_extradata = 0, extradata_size = 0; + struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; + if(m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only"); + return OMX_ErrorIncorrectStateOperation; + } + if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) + extradata_size += OMX_FRAMEINFO_EXTRADATA_SIZE; + if (requested_extradata & OMX_INTERLACE_EXTRADATA) + extradata_size += OMX_INTERLACE_EXTRADATA_SIZE; + if (requested_extradata & OMX_PORTDEF_EXTRADATA) + { + extradata_size += OMX_PORTDEF_EXTRADATA_SIZE; + } + DEBUG_PRINT_ERROR("enable_extradata: actual[%x] requested[%x] enable[%d]", + client_extradata, requested_extradata, enable); + + if (enable) + requested_extradata |= client_extradata; + else + { + requested_extradata = client_extradata & ~requested_extradata; + extradata_size *= -1; + } + + driver_extradata = requested_extradata & DRIVER_EXTRADATA_MASK; + if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) + driver_extradata |= VDEC_EXTRADATA_MB_ERROR_MAP; // Required for conceal MB frame info +#ifdef PROCESS_EXTRADATA_IN_OUTPUT_PORT + if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + driver_extradata |= ((requested_extradata & OMX_FRAMEINFO_EXTRADATA)? + VDEC_EXTRADATA_SEI : 0); // Required for pan scan frame info + driver_extradata |= ((requested_extradata & OMX_TIMEINFO_EXTRADATA)? + VDEC_EXTRADATA_VUI | VDEC_EXTRADATA_SEI : 0); //Required for time info + } + +#endif + if (driver_extradata != drv_ctx.extradata) + { + client_extradata = requested_extradata; + drv_ctx.extradata = driver_extradata; + ioctl_msg.in = &drv_ctx.extradata; + ioctl_msg.out = NULL; + if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_SET_EXTRADATA, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nSet extradata failed"); + ret = OMX_ErrorUnsupportedSetting; + } + else + ret = get_buffer_req(&drv_ctx.op_buf); + } + else if ((client_extradata & ~DRIVER_EXTRADATA_MASK) != (requested_extradata & ~DRIVER_EXTRADATA_MASK)) + { + client_extradata = requested_extradata; + drv_ctx.op_buf.buffer_size += extradata_size; + // align the buffer size + drv_ctx.op_buf.buffer_size = (drv_ctx.op_buf.buffer_size + drv_ctx.op_buf.alignment - 1)&(~(drv_ctx.op_buf.alignment - 1)); + DEBUG_PRINT_LOW("Aligned buffer size with exreadata = %d", drv_ctx.op_buf.buffer_size); + if (!(client_extradata & ~DRIVER_EXTRADATA_MASK)) // If no omx extradata is required remove space for terminator + drv_ctx.op_buf.buffer_size -= sizeof(OMX_OTHER_EXTRADATATYPE); + ret = set_buffer_req(&drv_ctx.op_buf); + } + return ret; +} + +OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra) +{ + OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0; + OMX_U8 *data_ptr = extra->data, data = 0; + while (byte_count < extra->nDataSize) + { + data = *data_ptr; + while (data) + { + num_MB += (data&0x01); + data >>= 1; + } + data_ptr++; + byte_count++; + } + num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) * + (drv_ctx.video_resolution.frame_height + 15)) >> 8; + return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0); +} + +void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra) +{ +#ifdef _ANDROID_ + if (!m_debug_extradata) + return; + + DEBUG_PRINT_HIGH( + "============== Extra Data ==============\n" + " Size: %u \n" + " Version: %u \n" + " PortIndex: %u \n" + " Type: %x \n" + " DataSize: %u \n", + extra->nSize, extra->nVersion.nVersion, + extra->nPortIndex, extra->eType, extra->nDataSize); + + if (extra->eType == OMX_ExtraDataInterlaceFormat) + { + OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)extra->data; + DEBUG_PRINT_HIGH( + "------ Interlace Format ------\n" + " Size: %u \n" + " Version: %u \n" + " PortIndex: %u \n" + " Is Interlace Format: %u \n" + " Interlace Formats: %u \n" + "=========== End of Interlace ===========\n", + intfmt->nSize, intfmt->nVersion.nVersion, intfmt->nPortIndex, + intfmt->bInterlaceFormat, intfmt->nInterlaceFormats); + } + else if (extra->eType == OMX_ExtraDataFrameInfo) + { + OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data; + + DEBUG_PRINT_HIGH( + "-------- Frame Format --------\n" + " Picture Type: %u \n" + " Interlace Type: %u \n" + " Pan Scan Total Frame Num: %u \n" + " Concealed Macro Blocks: %u \n" + " frame rate: %u \n" + " Aspect Ratio X: %u \n" + " Aspect Ratio Y: %u \n", + fminfo->ePicType, + fminfo->interlaceType, + fminfo->panScan.numWindows, + fminfo->nConcealedMacroblocks, + fminfo->nFrameRate, + fminfo->aspectRatio.aspectRatioX, + fminfo->aspectRatio.aspectRatioY); + + for (int i = 0; i < fminfo->panScan.numWindows; i++) + { + DEBUG_PRINT_HIGH( + "------------------------------\n" + " Pan Scan Frame Num: %d \n" + " Rectangle x: %d \n" + " Rectangle y: %d \n" + " Rectangle dx: %d \n" + " Rectangle dy: %d \n", + i, fminfo->panScan.window[i].x, fminfo->panScan.window[i].y, + fminfo->panScan.window[i].dx, fminfo->panScan.window[i].dy); + } + + DEBUG_PRINT_HIGH("========= End of Frame Format =========="); + } + else if (extra->eType == OMX_ExtraDataNone) + { + DEBUG_PRINT_HIGH("========== End of Terminator ==========="); + } + else + { + DEBUG_PRINT_HIGH("======= End of Driver Extradata ========"); + } +#endif /* _ANDROID_ */ +} + +void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra, + OMX_U32 interlaced_format_type) +{ + OMX_STREAMINTERLACEFORMAT *interlace_format; + OMX_U32 mbaff = 0; + extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE; + extra->nVersion.nVersion = OMX_SPEC_VERSION; + extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat; + extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT); + interlace_format = (OMX_STREAMINTERLACEFORMAT *)extra->data; + interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT); + interlace_format->nVersion.nVersion = OMX_SPEC_VERSION; + interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + mbaff = (h264_parser)? (h264_parser->is_mbaff()): false; + if ((interlaced_format_type == VDEC_InterlaceFrameProgressive) && !mbaff) + { + interlace_format->bInterlaceFormat = OMX_FALSE; + interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive; + drv_ctx.interlace = VDEC_InterlaceFrameProgressive; + } + else + { + interlace_format->bInterlaceFormat = OMX_TRUE; + interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst; + drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; + } + print_debug_extradata(extra); +} + +void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra, + OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_S64 timestamp, + OMX_U32 frame_rate, struct vdec_aspectratioinfo *aspect_ratio_info) +{ + OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL; + extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE; + extra->nVersion.nVersion = OMX_SPEC_VERSION; + extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo; + extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO); + frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data; + + switch (picture_type) + { + case PICTURE_TYPE_I: + frame_info->ePicType = OMX_VIDEO_PictureTypeI; + break; + case PICTURE_TYPE_P: + frame_info->ePicType = OMX_VIDEO_PictureTypeP; + break; + case PICTURE_TYPE_B: + frame_info->ePicType = OMX_VIDEO_PictureTypeB; + break; + default: + frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0; + } + if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst) + frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; + else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst) + frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; + else + frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive; + memset(&frame_info->panScan,0,sizeof(frame_info->panScan)); + memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio)); + if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + h264_parser->fill_pan_scan_data(&frame_info->panScan, timestamp); + } + + fill_aspect_ratio_info(aspect_ratio_info, frame_info); + frame_info->nConcealedMacroblocks = num_conceal_mb; + frame_info->nFrameRate = frame_rate; + print_debug_extradata(extra); +} + +void omx_vdec::fill_aspect_ratio_info( + struct vdec_aspectratioinfo *aspect_ratio_info, + OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info) +{ + m_extradata = frame_info; + m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width; + m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height; +} + +void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra) +{ + OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL; + extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE; + extra->nVersion.nVersion = OMX_SPEC_VERSION; + extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef; + extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)extra->data; + *portDefn = m_port_def; + DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u stride = %u" + "sliceheight = %u",portDefn->format.video.nFrameHeight, + portDefn->format.video.nFrameWidth, + portDefn->format.video.nStride, + portDefn->format.video.nSliceHeight); +} + +void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra) +{ + extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE); + extra->nVersion.nVersion = OMX_SPEC_VERSION; + extra->eType = OMX_ExtraDataNone; + extra->nDataSize = 0; + extra->data[0] = 0; + + print_debug_extradata(extra); +} + +OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if (index >= drv_ctx.ip_buf.actualcount) + { + DEBUG_PRINT_ERROR("\nERROR:Desc Buffer Index not found"); + return OMX_ErrorInsufficientResources; + } + if (m_desc_buffer_ptr == NULL) + { + m_desc_buffer_ptr = (desc_buffer_hdr*) \ + calloc( (sizeof(desc_buffer_hdr)), + drv_ctx.ip_buf.actualcount); + if (m_desc_buffer_ptr == NULL) + { + DEBUG_PRINT_ERROR("\n m_desc_buffer_ptr Allocation failed "); + return OMX_ErrorInsufficientResources; + } + } + + m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8)); + if (m_desc_buffer_ptr[index].buf_addr == NULL) + { + DEBUG_PRINT_ERROR("\ndesc buffer Allocation failed "); + return OMX_ErrorInsufficientResources; + } + + return eRet; +} + +void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset) +{ + DEBUG_PRINT_LOW("Inserting address offset (%d) at idx (%d)", address_offset,m_demux_entries); + if (m_demux_entries < 8192) + { + m_demux_offsets[m_demux_entries++] = address_offset; + } + return; +} + +void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr) +{ + OMX_U32 bytes_to_parse = buf_hdr->nFilledLen; + OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset; + OMX_U32 index = 0; + OMX_U32 prev_sc_index = 0; + + m_demux_entries = 0; + + while (index < bytes_to_parse) + { + if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) && + (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) || + ((buf[index] == 0x00) && (buf[index+1] == 0x00) && + (buf[index+2] == 0x01)) ) + { + if ((((index+3) - prev_sc_index) <= 4) && m_demux_entries) + { + DEBUG_PRINT_ERROR("FOUND Consecutive start Code, Hence skip one"); + m_demux_entries--; + } + //Found start code, insert address offset + insert_demux_addr_offset(index); + if (buf[index+2] == 0x01) // 3 byte start code + index += 3; + else //4 byte start code + index += 4; + prev_sc_index = index; + } + else + index++; + } + DEBUG_PRINT_LOW("Extracted (%d) demux entry offsets",m_demux_entries); + return; +} + +OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr) +{ + //fix this, handle 3 byte start code, vc1 terminator entry + OMX_U8 *p_demux_data = NULL; + OMX_U32 desc_data = 0; + OMX_U32 start_addr = 0; + OMX_U32 nal_size = 0; + OMX_U32 suffix_byte = 0; + OMX_U32 demux_index = 0; + OMX_U32 buffer_index = 0; + + if (m_desc_buffer_ptr == NULL) + { + DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries."); + return OMX_ErrorBadParameter; + } + + buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); + if (buffer_index > drv_ctx.ip_buf.actualcount) + { + DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%d)", buffer_index); + return OMX_ErrorBadParameter; + } + + p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr; + + if ( ((OMX_U8*)p_demux_data == NULL) || + ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) + { + DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries."); + return OMX_ErrorBadParameter; + } + else + { + for (; demux_index < m_demux_entries; demux_index++) + { + desc_data = 0; + start_addr = m_demux_offsets[demux_index]; + if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) + { + suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3]; + } + else + { + suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4]; + } + if (demux_index < (m_demux_entries - 1)) + { + nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2; + } + else + { + nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2; + } + DEBUG_PRINT_LOW("Start_addr(%p), suffix_byte(0x%x),nal_size(%d),demux_index(%d)", + start_addr, + suffix_byte, + nal_size, + demux_index); + desc_data = (start_addr >> 3) << 1; + desc_data |= (start_addr & 7) << 21; + desc_data |= suffix_byte << 24; + + memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); + memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32)); + memset(p_demux_data + 8, 0, sizeof(OMX_U32)); + memset(p_demux_data + 12, 0, sizeof(OMX_U32)); + + p_demux_data += 16; + } + if (codec_type_parse == CODEC_TYPE_VC1) + { + DEBUG_PRINT_LOW("VC1 terminator entry"); + desc_data = 0; + desc_data = 0x82 << 24; + memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); + memset(p_demux_data + 4, 0, sizeof(OMX_U32)); + memset(p_demux_data + 8, 0, sizeof(OMX_U32)); + memset(p_demux_data + 12, 0, sizeof(OMX_U32)); + p_demux_data += 16; + m_demux_entries++; + } + //Add zero word to indicate end of descriptors + memset(p_demux_data, 0, sizeof(OMX_U32)); + + m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32); + DEBUG_PRINT_LOW("desc table data size=%d", m_desc_buffer_ptr[buffer_index].desc_data_size); + } + memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); + m_demux_entries = 0; + DEBUG_PRINT_LOW("Demux table complete!"); + return OMX_ErrorNone; +} + +#ifdef MAX_RES_1080P +OMX_ERRORTYPE omx_vdec::vdec_alloc_h264_mv() +{ + OMX_U32 pmem_fd = -1; + OMX_U32 width, height, size, alignment; + void *buf_addr = NULL; + struct vdec_ioctl_msg ioctl_msg; +#ifndef USE_ION + struct pmem_allocation allocation; +#endif + struct vdec_h264_mv h264_mv; + struct vdec_mv_buff_size mv_buff_size; + + mv_buff_size.width = drv_ctx.video_resolution.stride; + mv_buff_size.height = drv_ctx.video_resolution.scan_lines>>2; + + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&mv_buff_size; + + if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_GET_MV_BUFFER_SIZE, (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n GET_MV_BUFFER_SIZE Failed for width: %d, Height %d" , + mv_buff_size.width, mv_buff_size.height); + return OMX_ErrorInsufficientResources; + } + + DEBUG_PRINT_ERROR("GET_MV_BUFFER_SIZE returned: Size: %d and alignment: %d", + mv_buff_size.size, mv_buff_size.alignment); + + size = mv_buff_size.size * drv_ctx.op_buf.actualcount; + alignment = mv_buff_size.alignment; + + DEBUG_PRINT_LOW("Entered vdec_alloc_h264_mv act_width: %d, act_height: %d, size: %d, alignment %d", + drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height,size,alignment); + + +#ifdef USE_ION + drv_ctx.h264_mv.ion_device_fd = alloc_map_ion_memory( + size, 8192, + &drv_ctx.h264_mv.ion_alloc_data, + &drv_ctx.h264_mv.fd_ion_data,CACHED); + if (drv_ctx.h264_mv.ion_device_fd < 0) { + return OMX_ErrorInsufficientResources; + } + pmem_fd = drv_ctx.h264_mv.fd_ion_data.fd; +#else + allocation.size = size; + allocation.align = clip2(alignment); + if (allocation.align != 8192) + allocation.align = 8192; + + pmem_fd = open(MEM_DEVICE, O_RDWR); + + if ((int)(pmem_fd) < 0) + return OMX_ErrorInsufficientResources; + + if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) + { + DEBUG_PRINT_ERROR("\n Aligment(%u) failed with pmem driver Sz(%lu)", + allocation.align, allocation.size); + return OMX_ErrorInsufficientResources; + } +#endif + if(!secure_mode) { + buf_addr = mmap(NULL, size, + PROT_READ | PROT_WRITE, + MAP_SHARED, pmem_fd, 0); + + if (buf_addr == (void*) MAP_FAILED) + { + close(pmem_fd); +#ifdef USE_ION + free_ion_memory(&drv_ctx.h264_mv); +#endif + pmem_fd = -1; + DEBUG_PRINT_ERROR("Error returned in allocating recon buffers buf_addr: %p\n",buf_addr); + return OMX_ErrorInsufficientResources; + } + } else + buf_addr =(unsigned char *) (pmem_fd + 1234); + DEBUG_PRINT_LOW("Allocated virt:%p, FD: %d of size %d count: %d", buf_addr, + pmem_fd, size, drv_ctx.op_buf.actualcount); + + h264_mv.size = size; + h264_mv.count = drv_ctx.op_buf.actualcount; + h264_mv.pmem_fd = pmem_fd; + h264_mv.offset = 0; + + ioctl_msg.in = (void*)&h264_mv; + ioctl_msg.out = NULL; + + if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_H264_MV_BUFFER, (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("Failed to set the H264_mv_buffers\n"); + return OMX_ErrorInsufficientResources; + } + + h264_mv_buff.buffer = (unsigned char *) buf_addr; + h264_mv_buff.size = size; + h264_mv_buff.count = drv_ctx.op_buf.actualcount; + h264_mv_buff.offset = 0; + h264_mv_buff.pmem_fd = pmem_fd; + DEBUG_PRINT_LOW("Saving virt:%p, FD: %d of size %d count: %d", h264_mv_buff.buffer, + h264_mv_buff.pmem_fd, h264_mv_buff.size, drv_ctx.op_buf.actualcount); + return OMX_ErrorNone; +} + +void omx_vdec::vdec_dealloc_h264_mv() +{ + if(h264_mv_buff.pmem_fd > 0) + { + if(ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_FREE_H264_MV_BUFFER,NULL) < 0) + DEBUG_PRINT_ERROR("VDEC_IOCTL_FREE_H264_MV_BUFFER failed"); + if(!secure_mode) + munmap(h264_mv_buff.buffer, h264_mv_buff.size); + close(h264_mv_buff.pmem_fd); +#ifdef USE_ION + free_ion_memory(&drv_ctx.h264_mv); +#endif + DEBUG_PRINT_LOW("Cleaning H264_MV buffer of size %d",h264_mv_buff.size); + h264_mv_buff.pmem_fd = -1; + h264_mv_buff.offset = 0; + h264_mv_buff.size = 0; + h264_mv_buff.count = 0; + h264_mv_buff.buffer = NULL; + } +} + +#endif + +#ifdef _ANDROID_ +OMX_ERRORTYPE omx_vdec::createDivxDrmContext() +{ + OMX_ERRORTYPE err = OMX_ErrorNone; + iDivXDrmDecrypt = DivXDrmDecrypt::Create(); + if (iDivXDrmDecrypt) { + OMX_ERRORTYPE err = iDivXDrmDecrypt->Init(); + if(err!=OMX_ErrorNone) { + DEBUG_PRINT_ERROR("\nERROR :iDivXDrmDecrypt->Init %d", err); + delete iDivXDrmDecrypt; + iDivXDrmDecrypt = NULL; + } + } + else { + DEBUG_PRINT_ERROR("\nUnable to Create DIVX DRM"); + err = OMX_ErrorUndefined; + } + return err; +} +#endif //_ANDROID_ + diff --git a/mm-video/vidc/vdec/src/omx_vdec_msm8974.cpp b/mm-video/vidc/vdec/src/omx_vdec_msm8974.cpp new file mode 100644 index 0000000..05e49c4 --- /dev/null +++ b/mm-video/vidc/vdec/src/omx_vdec_msm8974.cpp @@ -0,0 +1,8540 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + +*//** @file omx_vdec.cpp + This module contains the implementation of the OpenMAX core & component. + +*//*========================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include "omx_vdec.h" +#include +#include + +#ifndef _ANDROID_ +#include +#include +#endif //_ANDROID_ + +#ifdef _ANDROID_ +#include +#undef USE_EGL_IMAGE_GPU +#endif + +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) +#include +#endif + +#if defined (_ANDROID_ICS_) +#include +#endif + +#ifdef _ANDROID_ +#include "DivXDrmDecrypt.h" +#endif //_ANDROID_ + +#ifdef USE_EGL_IMAGE_GPU +#include +#include +#define EGL_BUFFER_HANDLE_QCOM 0x4F00 +#define EGL_BUFFER_OFFSET_QCOM 0x4F01 +#endif + +#ifdef INPUT_BUFFER_LOG +#define INPUT_BUFFER_FILE_NAME "/data/input-bitstream.\0\0\0\0" +#define INPUT_BUFFER_FILE_NAME_LEN 30 +FILE *inputBufferFile1; +char inputfilename [INPUT_BUFFER_FILE_NAME_LEN] = "\0"; +#endif +#ifdef OUTPUT_BUFFER_LOG +FILE *outputBufferFile1; +char outputfilename [] = "/data/output.yuv"; +#endif +#ifdef OUTPUT_EXTRADATA_LOG +FILE *outputExtradataFile; +char ouputextradatafilename [] = "/data/extradata"; +#endif + +#define DEFAULT_FPS 30 +#define MAX_INPUT_ERROR DEFAULT_FPS +#define MAX_SUPPORTED_FPS 120 + +#define VC1_SP_MP_START_CODE 0xC5000000 +#define VC1_SP_MP_START_CODE_MASK 0xFF000000 +#define VC1_AP_SEQ_START_CODE 0x0F010000 +#define VC1_STRUCT_C_PROFILE_MASK 0xF0 +#define VC1_STRUCT_B_LEVEL_MASK 0xE0000000 +#define VC1_SIMPLE_PROFILE 0 +#define VC1_MAIN_PROFILE 1 +#define VC1_ADVANCE_PROFILE 3 +#define VC1_SIMPLE_PROFILE_LOW_LEVEL 0 +#define VC1_SIMPLE_PROFILE_MED_LEVEL 2 +#define VC1_STRUCT_C_LEN 4 +#define VC1_STRUCT_C_POS 8 +#define VC1_STRUCT_A_POS 12 +#define VC1_STRUCT_B_POS 24 +#define VC1_SEQ_LAYER_SIZE 36 + +#define MEM_DEVICE "/dev/ion" +#define MEM_HEAP_ID ION_CP_MM_HEAP_ID + +#ifdef _ANDROID_ + extern "C"{ + #include + } +#endif//_ANDROID_ + +#define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } +#define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); } + +void* async_message_thread (void *input) +{ + struct vdec_ioctl_msg ioctl_msg; + OMX_BUFFERHEADERTYPE *buffer; + struct v4l2_plane plane; + struct pollfd pfd; + struct v4l2_buffer v4l2_buf ={0}; + struct v4l2_event dqevent; + pfd.events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI; + omx_vdec *omx = reinterpret_cast(input); + pfd.fd = omx->drv_ctx.video_driver_fd; + int error_code = 0,rc=0; + DEBUG_PRINT_HIGH("omx_vdec: Async thread start\n"); + prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0); + while (1) + { + rc = poll(&pfd, 1, TIMEOUT); + if (!rc) { + DEBUG_PRINT_ERROR("Poll timedout\n"); + break; + } else if (rc < 0) { + DEBUG_PRINT_ERROR("Error while polling: %d\n", rc); + break; + } + if (pfd.revents & POLLERR){ + printf("\n async_message_thread Exited \n"); + break; + } + if (pfd.revents & POLLPRI){ + rc = ioctl(pfd.fd, VIDIOC_DQEVENT, &dqevent); + if(dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT) { + DEBUG_PRINT_HIGH("\n VIDC Sufficinet resources recieved \n"); + continue; + } else if(dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT) { + struct vdec_msginfo vdec_msg; + vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED; + vdec_msg.status_code=VDEC_S_SUCCESS; + printf("\n VIDC Port Reconfig recieved \n"); + if (omx->async_message_process(input,&vdec_msg) < 0) { + DEBUG_PRINT_HIGH("\n async_message_thread Exited \n"); + break; + } + } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) { + struct vdec_msginfo vdec_msg; + vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE; + vdec_msg.status_code=VDEC_S_SUCCESS; + DEBUG_PRINT_HIGH("\n VIDC Flush Done Recieved \n"); + if (omx->async_message_process(input,&vdec_msg) < 0) { + DEBUG_PRINT_HIGH("\n async_message_thread Exited \n"); + break; + } + } else { + DEBUG_PRINT_HIGH("\n VIDC Some Event recieved \n"); + continue; + } + } + if ((pfd.revents & POLLIN) || (pfd.revents & POLLRDNORM)) { + struct vdec_msginfo vdec_msg; + v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + v4l2_buf.memory = V4L2_MEMORY_USERPTR; + v4l2_buf.length = 1; + v4l2_buf.m.planes = &plane; + rc = ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf); + if (rc) { + /*TODO: How to handle this case */ + DEBUG_PRINT_ERROR("Failed to dequeue buf: %d from capture capability\n", rc); + break; + } + vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE; + vdec_msg.status_code=VDEC_S_SUCCESS; + vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf; + vdec_msg.msgdata.output_frame.len=plane.bytesused; + vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane.m.userptr; + if (omx->async_message_process(input,&vdec_msg) < 0) { + DEBUG_PRINT_HIGH("\n async_message_thread Exited \n"); + break; + } + } + if((pfd.revents & POLLOUT) || (pfd.revents & POLLWRNORM)) { + struct vdec_msginfo vdec_msg; + v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + v4l2_buf.memory = V4L2_MEMORY_USERPTR; + v4l2_buf.m.planes = &plane; + rc = ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf); + if (rc) { + /*TODO: How to handle this case */ + DEBUG_PRINT_ERROR("Failed to dequeue buf: %d from output capability\n", rc); + break; + } + vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE; + vdec_msg.status_code=VDEC_S_SUCCESS; + vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf; + if (omx->async_message_process(input,&vdec_msg) < 0) { + DEBUG_PRINT_HIGH("\n async_message_thread Exited \n"); + break; + } + } + } + DEBUG_PRINT_HIGH("omx_vdec: Async thread stop\n"); + return NULL; +} + +void* message_thread(void *input) +{ + omx_vdec* omx = reinterpret_cast(input); + unsigned char id; + int n; + + DEBUG_PRINT_HIGH("omx_vdec: message thread start\n"); + prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0); + while (1) + { + + n = read(omx->m_pipe_in, &id, 1); + + if(0 == n) + { + break; + } + + if (1 == n) + { + omx->process_event_cb(omx, id); + } + if ((n < 0) && (errno != EINTR)) + { + DEBUG_PRINT_ERROR("\nERROR: read from pipe failed, ret %d errno %d", n, errno); + break; + } + } + DEBUG_PRINT_HIGH("omx_vdec: message thread stop\n"); + return 0; +} + +void post_message(omx_vdec *omx, unsigned char id) +{ + int ret_value; + DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d\n", id,omx->m_pipe_out); + ret_value = write(omx->m_pipe_out, &id, 1); + DEBUG_PRINT_LOW("post_message to pipe done %d\n",ret_value); +} + +// omx_cmd_queue destructor +omx_vdec::omx_cmd_queue::~omx_cmd_queue() +{ + // Nothing to do +} + +// omx cmd queue constructor +omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) +{ + memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); +} + +// omx cmd queue insert +bool omx_vdec::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id) +{ + bool ret = true; + if(m_size < OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_q[m_write].id = id; + m_q[m_write].param1 = p1; + m_q[m_write].param2 = p2; + m_write++; + m_size ++; + if(m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_write = 0; + } + } + else + { + ret = false; + DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full\n", __func__); + } + return ret; +} + +// omx cmd queue pop +bool omx_vdec::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id) +{ + bool ret = true; + if (m_size > 0) + { + *id = m_q[m_read].id; + *p1 = m_q[m_read].param1; + *p2 = m_q[m_read].param2; + // Move the read pointer ahead + ++m_read; + --m_size; + if(m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_read = 0; + } + } + else + { + ret = false; + } + return ret; +} + +// Retrieve the first mesg type in the queue +unsigned omx_vdec::omx_cmd_queue::get_q_msg_type() +{ + return m_q[m_read].id; +} + +#ifdef _ANDROID_ +omx_vdec::ts_arr_list::ts_arr_list() +{ + //initialize timestamps array + memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) ); +} +omx_vdec::ts_arr_list::~ts_arr_list() +{ + //free m_ts_arr_list? +} + +bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts) +{ + bool ret = true; + bool duplicate_ts = false; + int idx = 0; + + //insert at the first available empty location + for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) + { + if (!m_ts_arr_list[idx].valid) + { + //found invalid or empty entry, save timestamp + m_ts_arr_list[idx].valid = true; + m_ts_arr_list[idx].timestamp = ts; + DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)", + ts, idx); + break; + } + } + + if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) + { + DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert"); + ret = false; + } + return ret; +} + +bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts) +{ + bool ret = true; + int min_idx = -1; + OMX_TICKS min_ts = 0; + int idx = 0; + + for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) + { + + if (m_ts_arr_list[idx].valid) + { + //found valid entry, save index + if (min_idx < 0) + { + //first valid entry + min_ts = m_ts_arr_list[idx].timestamp; + min_idx = idx; + } + else if (m_ts_arr_list[idx].timestamp < min_ts) + { + min_ts = m_ts_arr_list[idx].timestamp; + min_idx = idx; + } + } + + } + + if (min_idx < 0) + { + //no valid entries found + DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop"); + ts = 0; + ret = false; + } + else + { + ts = m_ts_arr_list[min_idx].timestamp; + m_ts_arr_list[min_idx].valid = false; + DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)", + ts, min_idx); + } + + return ret; + +} + + +bool omx_vdec::ts_arr_list::reset_ts_list() +{ + bool ret = true; + int idx = 0; + + DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list"); + for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) + { + m_ts_arr_list[idx].valid = false; + } + return ret; +} +#endif + +// factory function executed by the core to create instances +void *get_omx_component_factory_fn(void) +{ + return (new omx_vdec); +} + +#ifdef _ANDROID_ +#ifdef USE_ION +VideoHeap::VideoHeap(int devicefd, size_t size, void* base, + struct ion_handle *handle, int ionMapfd) +{ +// ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd); +} +#else +VideoHeap::VideoHeap(int fd, size_t size, void* base) +{ + // dup file descriptor, map once, use pmem + init(dup(fd), base, size, 0 , MEM_DEVICE); +} +#endif +#endif // _ANDROID_ +/* ====================================================================== +FUNCTION + omx_vdec::omx_vdec + +DESCRIPTION + Constructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_vdec::omx_vdec(): m_state(OMX_StateInvalid), + m_app_data(NULL), + m_inp_mem_ptr(NULL), + m_out_mem_ptr(NULL), + m_phdr_pmem_ptr(NULL), + pending_input_buffers(0), + pending_output_buffers(0), + m_out_bm_count(0), + m_inp_bm_count(0), + m_inp_bPopulated(OMX_FALSE), + m_out_bPopulated(OMX_FALSE), + m_flags(0), + m_inp_bEnabled(OMX_TRUE), + m_out_bEnabled(OMX_TRUE), + m_platform_list(NULL), + m_platform_entry(NULL), + m_pmem_info(NULL), + output_flush_progress (false), + input_flush_progress (false), + input_use_buffer (false), + output_use_buffer (false), + arbitrary_bytes (true), + psource_frame (NULL), + pdest_frame (NULL), + m_inp_heap_ptr (NULL), + m_heap_inp_bm_count (0), + codec_type_parse ((codec_type)0), + first_frame_meta (true), + frame_count (0), + nal_length(0), + nal_count (0), + look_ahead_nal (false), + first_frame(0), + first_buffer(NULL), + first_frame_size (0), + m_error_propogated(false), + m_device_file_ptr(NULL), + m_vc1_profile((vc1_profile_type)0), + prev_ts(LLONG_MAX), + rst_prev_ts(true), + frm_int(0), + m_in_alloc_cnt(0), + m_display_id(NULL), + ouput_egl_buffers(false), + h264_parser(NULL), + client_extradata(0), + h264_last_au_ts(LLONG_MAX), + h264_last_au_flags(0), + m_inp_err_count(0), +#ifdef _ANDROID_ + m_heap_ptr(NULL), + m_enable_android_native_buffers(OMX_FALSE), + m_use_android_native_buffers(OMX_FALSE), +#endif + in_reconfig(false), + m_use_output_pmem(OMX_FALSE), + m_out_mem_region_smi(OMX_FALSE), + m_out_pvt_entry_pmem(OMX_FALSE), + secure_mode(false) +#ifdef _ANDROID_ + ,iDivXDrmDecrypt(NULL) +#endif + ,m_desc_buffer_ptr(NULL) + ,streaming({false, false}) +{ + /* Assumption is that , to begin with , we have all the frames with decoder */ + DEBUG_PRINT_HIGH("In OMX vdec Constructor"); +#ifdef _ANDROID_ + char property_value[PROPERTY_VALUE_MAX] = {0}; + property_get("vidc.dec.debug.perf", property_value, "0"); + perf_flag = atoi(property_value); + if (perf_flag) + { + DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag); + dec_time.start(); + proc_frms = latency = 0; + } + property_value[0] = NULL; + property_get("vidc.dec.debug.ts", property_value, "0"); + m_debug_timestamp = atoi(property_value); + DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp); + if (m_debug_timestamp) + { + time_stamp_dts.set_timestamp_reorder_mode(true); + } + + property_value[0] = NULL; + property_get("vidc.dec.debug.concealedmb", property_value, "0"); + m_debug_concealedmb = atoi(property_value); + DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb); + +#endif + memset(&m_cmp,0,sizeof(m_cmp)); + memset(&m_cb,0,sizeof(m_cb)); + memset (&drv_ctx,0,sizeof(drv_ctx)); + memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE)); + memset (m_hwdevice_name,0,sizeof(m_hwdevice_name)); + memset(&op_buf_rcnfg, 0 ,sizeof(vdec_allocatorproperty)); + memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); + m_demux_entries = 0; +#ifdef _ANDROID_ICS_ + memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); +#endif + drv_ctx.timestamp_adjust = false; + drv_ctx.video_driver_fd = -1; + m_vendor_config.pData = NULL; + pthread_mutex_init(&m_lock, NULL); + sem_init(&m_cmd_lock,0,0); +#ifdef _ANDROID_ + char extradata_value[PROPERTY_VALUE_MAX] = {0}; + property_get("vidc.dec.debug.extradata", extradata_value, "0"); + m_debug_extradata = atoi(extradata_value); + DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata); +#endif + +} + +static const int event_type[] = { + V4L2_EVENT_MSM_VIDC_FLUSH_DONE, + V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT, + V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT, +}; + +static OMX_ERRORTYPE subscribe_to_events(int fd) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct v4l2_event_subscription sub; + int array_sz = sizeof(event_type)/sizeof(int); + int i,rc; + if (fd < 0) { + printf("Invalid input: %d\n", fd); + return OMX_ErrorBadParameter; + } + + for (i = 0; i < array_sz; ++i) { + memset(&sub, 0, sizeof(sub)); + sub.type = event_type[i]; + rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub); + if (rc) { + printf("Failed to subscribe event: 0x%x\n", sub.type); + break; + } + } + if (i < array_sz) { + for (--i; i >=0 ; i--) { + memset(&sub, 0, sizeof(sub)); + sub.type = event_type[i]; + rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); + if (rc) + printf("Failed to unsubscribe event: 0x%x\n", sub.type); + } + eRet = OMX_ErrorNotImplemented; + } + return eRet; +} + + +static OMX_ERRORTYPE unsubscribe_to_events(int fd) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct v4l2_event_subscription sub; + int array_sz = sizeof(event_type)/sizeof(int); + int i,rc; + if (fd < 0) { + printf("Invalid input: %d\n", fd); + return OMX_ErrorBadParameter; + } + + for (i = 0; i < array_sz; ++i) { + memset(&sub, 0, sizeof(sub)); + sub.type = event_type[i]; + rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); + if (rc) { + printf("Failed to unsubscribe event: 0x%x\n", sub.type); + break; + } + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::~omx_vdec + +DESCRIPTION + Destructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_vdec::~omx_vdec() +{ + m_pmem_info = NULL; + DEBUG_PRINT_HIGH("In OMX vdec Destructor"); + if(m_pipe_in) close(m_pipe_in); + if(m_pipe_out) close(m_pipe_out); + m_pipe_in = -1; + m_pipe_out = -1; + DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit"); + pthread_join(msg_thread_id,NULL); + DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit"); + pthread_join(async_thread_id,NULL); + unsubscribe_to_events(drv_ctx.video_driver_fd); + close(drv_ctx.video_driver_fd); + pthread_mutex_destroy(&m_lock); + sem_destroy(&m_cmd_lock); + if (perf_flag) + { + DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME"); + dec_time.end(); + } + DEBUG_PRINT_HIGH("Exit OMX vdec Destructor"); +} + +/* ====================================================================== +FUNCTION + omx_vdec::OMXCntrlProcessMsgCb + +DESCRIPTION + IL Client callbacks are generated through this routine. The decoder + provides the thread context for this routine. + +PARAMETERS + ctxt -- Context information related to the self. + id -- Event identifier. This could be any of the following: + 1. Command completion event + 2. Buffer done callback event + 3. Frame done callback event + +RETURN VALUE + None. + +========================================================================== */ +void omx_vdec::process_event_cb(void *ctxt, unsigned char id) +{ + unsigned p1; // Parameter - 1 + unsigned p2; // Parameter - 2 + unsigned ident; + unsigned qsize=0; // qsize + omx_vdec *pThis = (omx_vdec *) ctxt; + + if(!pThis) + { + DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out\n", + __func__); + return; + } + + // Protect the shared queue data structure + do + { + /*Read the message id's from the queue*/ + pthread_mutex_lock(&pThis->m_lock); + qsize = pThis->m_cmd_q.m_size; + if(qsize) + { + pThis->m_cmd_q.pop_entry(&p1,&p2,&ident); + } + + if (qsize == 0 && pThis->m_state != OMX_StatePause) + { + qsize = pThis->m_ftb_q.m_size; + if (qsize) + { + pThis->m_ftb_q.pop_entry(&p1,&p2,&ident); + } + } + + if (qsize == 0 && pThis->m_state != OMX_StatePause) + { + qsize = pThis->m_etb_q.m_size; + if (qsize) + { + pThis->m_etb_q.pop_entry(&p1,&p2,&ident); + } + } + pthread_mutex_unlock(&pThis->m_lock); + + /*process message if we have one*/ + if(qsize > 0) + { + id = ident; + switch (id) + { + case OMX_COMPONENT_GENERATE_EVENT: + if (pThis->m_cb.EventHandler) + { + switch (p1) + { + case OMX_CommandStateSet: + pThis->m_state = (OMX_STATETYPE) p2; + DEBUG_PRINT_HIGH("\n OMX_CommandStateSet complete, m_state = %d", + pThis->m_state); + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL); + break; + + case OMX_EventError: + if(p2 == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\n OMX_EventError: p2 is OMX_StateInvalid"); + pThis->m_state = (OMX_STATETYPE) p2; + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventError, OMX_ErrorInvalidState, p2, NULL); + } + else if (p2 == OMX_ErrorHardware) + { + pThis->omx_report_error(); + } + else + { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventError, p2, NULL, NULL ); + } + break; + + case OMX_CommandPortDisable: + DEBUG_PRINT_HIGH("\n OMX_CommandPortDisable complete for port [%d]", p2); + if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) + { + BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); + break; + } + if (p2 == OMX_CORE_OUTPUT_PORT_INDEX && pThis->in_reconfig) + { + pThis->op_buf_rcnfg.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + OMX_ERRORTYPE eRet = OMX_ErrorNone; + pThis->stream_off(); + OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->op_buf_rcnfg); + pThis->in_reconfig = false; + if(eRet != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet); + pThis->omx_report_error(); + break; + } + } + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL ); + break; + case OMX_CommandPortEnable: + DEBUG_PRINT_HIGH("\n OMX_CommandPortEnable complete for port [%d]", p2); + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\ + OMX_EventCmdComplete, p1, p2, NULL ); + break; + + default: + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL ); + break; + + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL\n", __func__); + } + break; + case OMX_COMPONENT_GENERATE_ETB_ARBITRARY: + if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure"); + pThis->omx_report_error (); + } + break; + case OMX_COMPONENT_GENERATE_ETB: + if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_FTB: + if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n fill_this_buffer_proxy failure"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_COMMAND: + pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\ + (OMX_U32)p2,(OMX_PTR)NULL); + break; + + case OMX_COMPONENT_GENERATE_EBD: + + if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EBD failure"); + pThis->omx_report_error (); + } + else + { + if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) + { + pThis->m_inp_err_count++; + pThis->time_stamp_dts.remove_time_stamp( + ((OMX_BUFFERHEADERTYPE *)p1)->nTimeStamp, + (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) + ?true:false); + } + else + { + pThis->m_inp_err_count = 0; + } + if ( pThis->empty_buffer_done(&pThis->m_cmp, + (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n empty_buffer_done failure"); + pThis->omx_report_error (); + } + if(pThis->m_inp_err_count >= MAX_INPUT_ERROR) + { + DEBUG_PRINT_ERROR("\n Input bitstream error for consecutive %d frames.", MAX_INPUT_ERROR); + pThis->omx_report_error (); + } + } + break; + case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: + { + int64_t *timestamp = (int64_t *)p1; + if (p1) + { + pThis->time_stamp_dts.remove_time_stamp(*timestamp, + (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) + ?true:false); + free(timestamp); + } + } + break; + case OMX_COMPONENT_GENERATE_FBD: + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_FBD failure"); + pThis->omx_report_error (); + } + else if ( pThis->fill_buffer_done(&pThis->m_cmp, + (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) + { + DEBUG_PRINT_ERROR("\n fill_buffer_done failure"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH: + DEBUG_PRINT_HIGH("\n Driver flush i/p Port complete"); + if (!pThis->input_flush_progress) + { + DEBUG_PRINT_ERROR("\n WARNING: Unexpected flush from driver"); + } + else + { + pThis->execute_input_flush(); + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\nOMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure"); + pThis->omx_report_error (); + } + else + { + /*Check if we need generate event for Flush done*/ + if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_INPUT_FLUSH_PENDING)) + { + BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING); + DEBUG_PRINT_LOW("\n Input Flush completed - Notify Client"); + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandFlush, + OMX_CORE_INPUT_PORT_INDEX,NULL ); + } + if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_IDLE_PENDING)) + { + if (!pThis->output_flush_progress) + { + DEBUG_PRINT_LOW("\n Output flush done hence issue stop"); + if (/*ioctl (pThis->drv_ctx.video_driver_fd, + VDEC_IOCTL_CMD_STOP,NULL ) < 0*/0) + { + DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed"); + pThis->omx_report_error (); + } + } + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + } + break; + + case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH: + DEBUG_PRINT_HIGH("\n Driver flush o/p Port complete"); + if (!pThis->output_flush_progress) + { + DEBUG_PRINT_ERROR("\n WARNING: Unexpected flush from driver"); + } + else + { + pThis->execute_output_flush(); + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed"); + pThis->omx_report_error (); + } + else + { + /*Check if we need generate event for Flush done*/ + if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) + { + DEBUG_PRINT_LOW("\n Notify Output Flush done"); + BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING); + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandFlush, + OMX_CORE_OUTPUT_PORT_INDEX,NULL ); + } + if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) + { + DEBUG_PRINT_LOW("\n Internal flush complete"); + BITMASK_CLEAR (&pThis->m_flags, + OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); + if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) + { + pThis->post_event(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + BITMASK_CLEAR (&pThis->m_flags, + OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); + + } + } + + if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) + { + if (!pThis->input_flush_progress) + { + DEBUG_PRINT_LOW("\n Input flush done hence issue stop"); + if (/*ioctl (pThis->drv_ctx.video_driver_fd, + VDEC_IOCTL_CMD_STOP,NULL ) < */0) + { + DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed"); + pThis->omx_report_error (); + } + } + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + } + break; + + case OMX_COMPONENT_GENERATE_START_DONE: + DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_START_DONE"); + + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_START_DONE Failure"); + pThis->omx_report_error (); + } + else + { + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Success"); + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) + { + DEBUG_PRINT_LOW("\n Move to executing"); + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); + pThis->m_state = OMX_StateExecuting; + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateExecuting, NULL); + } + else if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_PAUSE_PENDING)) + { + if (/*ioctl (pThis->drv_ctx.video_driver_fd, + VDEC_IOCTL_CMD_PAUSE,NULL ) < */0) + { + DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_PAUSE failed"); + pThis->omx_report_error (); + } + } + } + } + else + { + DEBUG_PRINT_LOW("\n Event Handler callback is NULL"); + } + break; + + case OMX_COMPONENT_GENERATE_PAUSE_DONE: + DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE"); + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed"); + pThis->omx_report_error (); + } + else + { + pThis->complete_pending_buffer_done_cbs(); + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) + { + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_PAUSE_DONE nofity"); + //Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING); + pThis->m_state = OMX_StatePause; + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StatePause, NULL); + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + + break; + + case OMX_COMPONENT_GENERATE_RESUME_DONE: + DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_RESUME_DONE"); + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_RESUME_DONE failed"); + pThis->omx_report_error (); + } + else + { + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) + { + DEBUG_PRINT_LOW("\n Moving the decoder to execute state"); + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); + pThis->m_state = OMX_StateExecuting; + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateExecuting,NULL); + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + + break; + + case OMX_COMPONENT_GENERATE_STOP_DONE: + DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_STOP_DONE"); + if (pThis->m_cb.EventHandler) + { + if (p2 != VDEC_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_STOP_DONE ret failed"); + pThis->omx_report_error (); + } + else + { + pThis->complete_pending_buffer_done_cbs(); + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_STOP_DONE Success"); + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING); + pThis->m_state = OMX_StateIdle; + DEBUG_PRINT_LOW("\n Move to Idle State"); + pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateIdle,NULL); + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + + break; + + case OMX_COMPONENT_GENERATE_PORT_RECONFIG: + DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_PORT_RECONFIG"); + pThis->in_reconfig = true; + + if (pThis->m_cb.EventHandler) { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventPortSettingsChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL ); + } else { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + + if (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) + { + OMX_INTERLACETYPE format = (OMX_INTERLACETYPE)-1; + OMX_EVENTTYPE event = (OMX_EVENTTYPE)OMX_EventIndexsettingChanged; + if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst) + format = OMX_InterlaceInterleaveFrameTopFieldFirst; + else if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst) + format = OMX_InterlaceInterleaveFrameBottomFieldFirst; + else //unsupported interlace format; raise a error + event = OMX_EventError; + if (pThis->m_cb.EventHandler) { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + event, format, 0, NULL ); + } else { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + } + break; + + case OMX_COMPONENT_GENERATE_EOS_DONE: + DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_EOS_DONE"); + if (pThis->m_cb.EventHandler) { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag, + OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL ); + } else { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + pThis->prev_ts = LLONG_MAX; + pThis->rst_prev_ts = true; + break; + + case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: + DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_HARDWARE_ERROR"); + pThis->omx_report_error (); + break; + case OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG: + { + DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG"); + if (pThis->m_cb.EventHandler) { + pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, + (OMX_EVENTTYPE)OMX_EventIndexsettingChanged, OMX_CORE_OUTPUT_PORT_INDEX, 0, NULL ); + } else { + DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); + } + } + default: + break; + } + } + pthread_mutex_lock(&pThis->m_lock); + qsize = pThis->m_cmd_q.m_size; + if (pThis->m_state != OMX_StatePause) + qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size); + pthread_mutex_unlock(&pThis->m_lock); + } + while(qsize>0); + +} + +/* ====================================================================== +FUNCTION + omx_vdec::ComponentInit + +DESCRIPTION + Initialize the component. + +PARAMETERS + ctxt -- Context information related to the self. + id -- Event identifier. This could be any of the following: + 1. Command completion event + 2. Buffer done callback event + 3. Frame done callback event + +RETURN VALUE + None. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct v4l2_fmtdesc fdesc; + struct v4l2_format fmt; + struct v4l2_requestbuffers bufreq; + unsigned int alignment = 0,buffer_size = 0; + int fds[2]; + int r,ret=0; + bool codec_ambiguous = false; + OMX_STRING device_name = "/dev/video32"; + + drv_ctx.video_driver_fd = open("/dev/video32", O_RDWR); + + DEBUG_PRINT_HIGH("\n omx_vdec::component_init(): Open returned fd %d, errno %d", + drv_ctx.video_driver_fd, errno); + + if(drv_ctx.video_driver_fd == 0){ + drv_ctx.video_driver_fd = open(device_name, O_RDWR); + } + + if(drv_ctx.video_driver_fd < 0) + { + DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d\n", errno); + return OMX_ErrorInsufficientResources; + } + drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS; + drv_ctx.frame_rate.fps_denominator = 1; + + +#ifdef INPUT_BUFFER_LOG + strcpy(inputfilename, INPUT_BUFFER_FILE_NAME); +#endif +#ifdef OUTPUT_BUFFER_LOG + outputBufferFile1 = fopen (outputfilename, "ab"); +#endif +#ifdef OUTPUT_EXTRADATA_LOG + outputExtradataFile = fopen (ouputextradatafilename, "ab"); +#endif + + // Copy the role information which provides the decoder kind + strlcpy(drv_ctx.kind,role,128); + if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.mpeg4",\ + OMX_MAX_STRINGNAME_SIZE); + drv_ctx.timestamp_adjust = true; + drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4; + eCompressionFormat = OMX_VIDEO_CodingMPEG4; + output_capability=V4L2_PIX_FMT_MPEG4; + /*Initialize Start Code for MPEG4*/ + codec_type_parse = CODEC_TYPE_MPEG4; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "m4v"); +#endif + } + else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.mpeg2",\ + OMX_MAX_STRINGNAME_SIZE); + drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2; + output_capability = V4L2_PIX_FMT_MPEG2; + eCompressionFormat = OMX_VIDEO_CodingMPEG2; + /*Initialize Start Code for MPEG2*/ + codec_type_parse = CODEC_TYPE_MPEG2; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "mpg"); +#endif + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("\n H263 Decoder selected"); + drv_ctx.decoder_format = VDEC_CODECTYPE_H263; + eCompressionFormat = OMX_VIDEO_CodingH263; + output_capability = V4L2_PIX_FMT_H263; + codec_type_parse = CODEC_TYPE_H263; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "263"); +#endif + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW ("\n DIVX 311 Decoder selected"); + drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3; + output_capability = V4L2_PIX_FMT_DIVX_311; + eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; + codec_type_parse = CODEC_TYPE_DIVX; + m_frame_parser.init_start_codes (codec_type_parse); + + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_ERROR ("\n DIVX 4 Decoder selected"); + drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4; + output_capability = V4L2_PIX_FMT_DIVX; + eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; + codec_type_parse = CODEC_TYPE_DIVX; + codec_ambiguous = true; + m_frame_parser.init_start_codes (codec_type_parse); + + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_ERROR ("\n DIVX 5/6 Decoder selected"); + drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6; + output_capability = V4L2_PIX_FMT_DIVX; + eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; + codec_type_parse = CODEC_TYPE_DIVX; + codec_ambiguous = true; + m_frame_parser.init_start_codes (codec_type_parse); + + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); + drv_ctx.decoder_format = VDEC_CODECTYPE_H264; + output_capability=V4L2_PIX_FMT_H264; + eCompressionFormat = OMX_VIDEO_CodingAVC; + codec_type_parse = CODEC_TYPE_H264; + m_frame_parser.init_start_codes (codec_type_parse); + m_frame_parser.init_nal_length(nal_length); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "264"); +#endif + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); + drv_ctx.decoder_format = VDEC_CODECTYPE_VC1; + eCompressionFormat = OMX_VIDEO_CodingWMV; + codec_type_parse = CODEC_TYPE_VC1; + output_capability = V4L2_PIX_FMT_VC1_ANNEX_G; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "vc1"); +#endif + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); + drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV; + eCompressionFormat = OMX_VIDEO_CodingWMV; + codec_type_parse = CODEC_TYPE_VC1; + output_capability = V4L2_PIX_FMT_VC1_ANNEX_G; + m_frame_parser.init_start_codes (codec_type_parse); +#ifdef INPUT_BUFFER_LOG + strcat(inputfilename, "vc1"); +#endif + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", \ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE); + output_capability=V4L2_PIX_FMT_VP8; + eCompressionFormat = OMX_VIDEO_CodingVPX; + codec_type_parse = CODEC_TYPE_VP8; + arbitrary_bytes = false; + } + else + { + DEBUG_PRINT_ERROR("\nERROR:Unknown Component\n"); + eRet = OMX_ErrorInvalidComponentName; + } +#ifdef INPUT_BUFFER_LOG + inputBufferFile1 = fopen (inputfilename, "ab"); +#endif + if (eRet == OMX_ErrorNone) + { + + drv_ctx.output_format = VDEC_YUV_FORMAT_TILE_4x2; + capture_capability= V4L2_PIX_FMT_NV12; + ret = subscribe_to_events(drv_ctx.video_driver_fd); + if (ret) { + DEBUG_PRINT_ERROR("\n Subscribe Event Failed \n"); + return OMX_ErrorInsufficientResources; + } + + struct v4l2_capability cap; + ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap); + if (ret) { + DEBUG_PRINT_ERROR("Failed to query capabilities\n"); + /*TODO: How to handle this case */ + } else { + DEBUG_PRINT_HIGH("Capabilities: driver_name = %s, card = %s, bus_info = %s," + " version = %d, capabilities = %x\n", cap.driver, cap.card, + cap.bus_info, cap.version, cap.capabilities); + } + ret=0; + fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fdesc.index=0; + while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) { + DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x\n", fdesc.description, + fdesc.pixelformat, fdesc.flags); + fdesc.index++; + } + fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fdesc.index=0; + while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) { + + DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x\n", fdesc.description, + fdesc.pixelformat, fdesc.flags); + fdesc.index++; + } + + drv_ctx.video_resolution.frame_height=drv_ctx.video_resolution.scan_lines=240; + drv_ctx.video_resolution.frame_width=drv_ctx.video_resolution.stride=320; + fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; + fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; + fmt.fmt.pix_mp.pixelformat = output_capability; + ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); + if (ret) { + /*TODO: How to handle this case */ + DEBUG_PRINT_ERROR("Failed to set format on output port\n"); + } + DEBUG_PRINT_HIGH("\n Set Format was successful \n "); + if (codec_ambiguous) { + if (output_capability == V4L2_PIX_FMT_DIVX) { + struct v4l2_control divx_ctrl; + + if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) { + divx_ctrl.id = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4; + } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) { + divx_ctrl.id = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5; + } else { + divx_ctrl.id = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5; + } + + divx_ctrl.value = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT; + ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &fmt); + if (ret) { + DEBUG_PRINT_ERROR("Failed to set divx version\n"); + } + } else { + DEBUG_PRINT_ERROR("Codec should not be ambiguous"); + } + } + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; + fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; + fmt.fmt.pix_mp.pixelformat = capture_capability; + ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); + if (ret) { + /*TODO: How to handle this case */ + DEBUG_PRINT_ERROR("Failed to set format on capture port\n"); + } + DEBUG_PRINT_HIGH("\n Set Format was successful \n "); + + /*Get the Buffer requirements for input and output ports*/ + drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT; + drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + drv_ctx.op_buf.alignment=4096; + drv_ctx.ip_buf.alignment=4096; + drv_ctx.interlace = VDEC_InterlaceFrameProgressive; + drv_ctx.extradata = 0; + drv_ctx.picture_order = VDEC_ORDER_DECODE; + drv_ctx.idr_only_decoding = 0; + + m_state = OMX_StateLoaded; + eRet=get_buffer_req(&drv_ctx.ip_buf); + DEBUG_PRINT_HIGH("Input Buffer Size =%d \n ",drv_ctx.ip_buf.buffer_size); + +#ifdef DEFAULT_EXTRADATA + if (eRet == OMX_ErrorNone && !secure_mode) + eRet = enable_extradata(DEFAULT_EXTRADATA); +#endif + if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + if (m_frame_parser.mutils == NULL) + { + m_frame_parser.mutils = new H264_Utils(); + + if (m_frame_parser.mutils == NULL) + { + DEBUG_PRINT_ERROR("\n parser utils Allocation failed "); + eRet = OMX_ErrorInsufficientResources; + } + else + { + h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size; + h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size); + h264_scratch.nFilledLen = 0; + h264_scratch.nOffset = 0; + + if (h264_scratch.pBuffer == NULL) + { + DEBUG_PRINT_ERROR("\n h264_scratch.pBuffer Allocation failed "); + return OMX_ErrorInsufficientResources; + } + m_frame_parser.mutils->initialize_frame_checking_environment(); + m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size); + } + } + + h264_parser = new h264_stream_parser(); + if (!h264_parser) + { + DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!"); + eRet = OMX_ErrorInsufficientResources; + } + } + + if(pipe(fds)) + { + DEBUG_PRINT_ERROR("pipe creation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + else + { + int temp1[2]; + if(fds[0] == 0 || fds[1] == 0) + { + if (pipe (temp1)) + { + DEBUG_PRINT_ERROR("pipe creation failed\n"); + return OMX_ErrorInsufficientResources; + } + //close (fds[0]); + //close (fds[1]); + fds[0] = temp1 [0]; + fds[1] = temp1 [1]; + } + m_pipe_in = fds[0]; + m_pipe_out = fds[1]; + r = pthread_create(&msg_thread_id,0,message_thread,this); + + if(r < 0) + { + DEBUG_PRINT_ERROR("\n component_init(): message_thread creation failed"); + eRet = OMX_ErrorInsufficientResources; + } + } + } + + if (eRet != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n Component Init Failed"); + DEBUG_PRINT_HIGH("\n Calling VDEC_IOCTL_STOP_NEXT_MSG"); + (void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG, + NULL); + DEBUG_PRINT_HIGH("\n Calling close() on Video Driver"); + close (drv_ctx.video_driver_fd); + drv_ctx.video_driver_fd = -1; + } + else + { + DEBUG_PRINT_HIGH("\n omx_vdec::component_init() success"); + } + + //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer)); + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::GetComponentVersion + +DESCRIPTION + Returns the component version. + +PARAMETERS + TBD. + +RETURN VALUE + OMX_ErrorNone. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::get_component_version + ( + OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STRING componentName, + OMX_OUT OMX_VERSIONTYPE* componentVersion, + OMX_OUT OMX_VERSIONTYPE* specVersion, + OMX_OUT OMX_UUIDTYPE* componentUUID + ) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Comp Version in Invalid State\n"); + return OMX_ErrorInvalidState; + } + /* TBD -- Return the proper version */ + if (specVersion) + { + specVersion->nVersion = OMX_SPEC_VERSION; + } + return OMX_ErrorNone; +} +/* ====================================================================== +FUNCTION + omx_vdec::SendCommand + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData + ) +{ + DEBUG_PRINT_LOW("\n send_command: Recieved a Command from Client"); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX + && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) + { + DEBUG_PRINT_ERROR("\n send_command(): ERROR OMX_CommandFlush " + "to invalid port: %d", param1); + return OMX_ErrorBadPortIndex; + } + post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); + sem_wait(&m_cmd_lock); + DEBUG_PRINT_LOW("\n send_command: Command Processed\n"); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::SendCommand + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData + ) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_STATETYPE eState = (OMX_STATETYPE) param1; + int bFlag = 1,sem_posted = 0,ret=0; + + DEBUG_PRINT_LOW("\n send_command_proxy(): cmd = %d", cmd); + DEBUG_PRINT_HIGH("\n send_command_proxy(): Current State %d, Expected State %d", + m_state, eState); + + if(cmd == OMX_CommandStateSet) + { + DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandStateSet issued"); + DEBUG_PRINT_HIGH("\n Current State %d, Expected State %d", m_state, eState); + /***************************/ + /* Current State is Loaded */ + /***************************/ + if(m_state == OMX_StateLoaded) + { + if(eState == OMX_StateIdle) + { + //if all buffers are allocated or all ports disabled + if(allocate_done() || + (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) + { + DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle\n"); + } + else + { + DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + /* Requesting transition from Loaded to Loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded\n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Loaded to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources\n"); + } + /* Requesting transition from Loaded to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Loaded to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Loaded to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)\n",\ + eState); + eRet = OMX_ErrorBadParameter; + } + } + + /***************************/ + /* Current State is IDLE */ + /***************************/ + else if(m_state == OMX_StateIdle) + { + if(eState == OMX_StateLoaded) + { + if(release_done()) + { + /* + Since error is None , we will post an event at the end + of this function definition + */ + DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded\n"); + } + else + { + DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); + // Skip the event notification + bFlag = 0; + } + } + /* Requesting transition from Idle to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n"); + //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING); + bFlag = 1; + DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n"); + m_state=OMX_StateExecuting; + DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful\n"); + } + /* Requesting transition from Idle to Idle */ + else if(eState == OMX_StateIdle) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle\n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Idle to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Idle to Pause */ + else if(eState == OMX_StatePause) + { + /*To pause the Video core we need to start the driver*/ + if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START, + NULL) < */0) + { + DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_START FAILED"); + omx_report_error (); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); + DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause\n"); + bFlag = 0; + } + } + /* Requesting transition from Idle to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /******************************/ + /* Current State is Executing */ + /******************************/ + else if(m_state == OMX_StateExecuting) + { + DEBUG_PRINT_LOW("\n Command Recieved in OMX_StateExecuting"); + /* Requesting transition from Executing to Idle */ + if(eState == OMX_StateIdle) + { + /* Since error is None , we will post an event + at the end of this function definition + */ + DEBUG_PRINT_LOW("\n send_command_proxy(): Executing --> Idle \n"); + //BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); + if(!sem_posted) + { + sem_posted = 1; + sem_post (&m_cmd_lock); + execute_omx_flush(OMX_ALL); + } + bFlag = 1; + int rc=0; + enum v4l2_buf_type btype; + btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype); + if (rc) { + /*TODO: How to handle this case */ + DEBUG_PRINT_ERROR("\n Failed to call streamoff on OUTPUT Port \n"); + } else { + streaming[OUTPUT_PORT] = false; + } + btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype); + if (rc) { + /*TODO: How to handle this case */ + DEBUG_PRINT_ERROR("\n Failed to call streamoff on CAPTURE Port \n"); + } else { + streaming[CAPTURE_PORT] = false; + } + m_state = OMX_StateIdle; + } + /* Requesting transition from Executing to Paused */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_LOW("\n PAUSE Command Issued"); + if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_PAUSE, + NULL) < */0) + { + DEBUG_PRINT_ERROR("\n Error In Pause State"); + post_event(OMX_EventError,OMX_ErrorHardware,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); + DEBUG_PRINT_LOW("send_command_proxy(): Executing-->Pause\n"); + bFlag = 0; + } + } + /* Requesting transition from Executing to Loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Loaded \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Executing to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> WaitForResources \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Executing to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Executing \n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Executing to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Invalid \n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is Pause */ + /***************************/ + else if(m_state == OMX_StatePause) + { + /* Requesting transition from Pause to Executing */ + if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_LOW("\n Pause --> Executing \n"); + if (/*ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_RESUME, + NULL) < */0) + { + DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_RESUME failed"); + post_event(OMX_EventError,OMX_ErrorHardware,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING); + DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n"); + post_event (NULL,VDEC_S_SUCCESS,\ + OMX_COMPONENT_GENERATE_RESUME_DONE); + bFlag = 0; + } + } + /* Requesting transition from Pause to Idle */ + else if(eState == OMX_StateIdle) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_LOW("\n Pause --> Idle \n"); + BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); + if(!sem_posted) + { + sem_posted = 1; + sem_post (&m_cmd_lock); + execute_omx_flush(OMX_ALL); + } + bFlag = 0; + } + /* Requesting transition from Pause to loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("\n Pause --> loaded \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Pause to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("\n Pause --> WaitForResources \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Pause to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("\n Pause --> Pause \n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Pause to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\n Pause --> Invalid \n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is WaitForResources */ + /***************************/ + else if(m_state == OMX_StateWaitForResources) + { + /* Requesting transition from WaitForResources to Loaded */ + if(eState == OMX_StateLoaded) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded\n"); + } + /* Requesting transition from WaitForResources to WaitForResources */ + else if (eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources\n"); + post_event(OMX_EventError,OMX_ErrorSameState, + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from WaitForResources to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from WaitForResources to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from WaitForResources to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + /* Requesting transition from WaitForResources to Loaded - + is NOT tested by Khronos TS */ + + } + else + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)\n",m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } + /********************************/ + /* Current State is Invalid */ + /*******************************/ + else if(m_state == OMX_StateInvalid) + { + /* State Transition from Inavlid to any state */ + if(eState == (OMX_StateLoaded || OMX_StateWaitForResources + || OMX_StateIdle || OMX_StateExecuting + || OMX_StatePause || OMX_StateInvalid)) + { + DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded\n"); + post_event(OMX_EventError,OMX_ErrorInvalidState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + } + else if (cmd == OMX_CommandFlush) + { + DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandFlush issued" + "with param1: %d", param1); + if(OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); + } + if(OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) + { + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING); + } + if (!sem_posted){ + sem_posted = 1; + DEBUG_PRINT_LOW("\n Set the Semaphore"); + sem_post (&m_cmd_lock); + execute_omx_flush(param1); + } + bFlag = 0; + } + else if ( cmd == OMX_CommandPortEnable) + { + DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortEnable issued" + "with param1: %d", param1); + if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) + { + m_inp_bEnabled = OMX_TRUE; + + if( (m_state == OMX_StateLoaded && + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || allocate_input_done()) + { + post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + DEBUG_PRINT_LOW("\n Enable output Port command recieved"); + m_out_bEnabled = OMX_TRUE; + + if( (m_state == OMX_StateLoaded && + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (allocate_output_done())) + { + post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + + } + else + { + DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + } + else if (cmd == OMX_CommandPortDisable) + { + DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortDisable issued" + "with param1: %d", param1); + if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) + { + m_inp_bEnabled = OMX_FALSE; + if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_input_done()) + { + post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); + if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + if(!sem_posted) + { + sem_posted = 1; + sem_post (&m_cmd_lock); + } + execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX); + } + + // Skip the event notification + bFlag = 0; + } + } + if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) + { + m_out_bEnabled = OMX_FALSE; + DEBUG_PRINT_LOW("\n Disable output Port command recieved"); + if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_output_done()) + { + post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\ + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + if (!sem_posted) + { + sem_posted = 1; + sem_post (&m_cmd_lock); + } + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); + execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX); + } + // Skip the event notification + bFlag = 0; + + } + } + } + else + { + DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)\n",cmd); + eRet = OMX_ErrorNotImplemented; + } + if(eRet == OMX_ErrorNone && bFlag) + { + post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); + } + if(!sem_posted) + { + sem_post(&m_cmd_lock); + } + + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::ExecuteOmxFlush + +DESCRIPTION + Executes the OMX flush. + +PARAMETERS + flushtype - input flush(1)/output flush(0)/ both. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_vdec::execute_omx_flush(OMX_U32 flushType) +{ + bool bRet = false; + struct v4l2_plane plane; + struct v4l2_buffer v4l2_buf ={0}; + struct v4l2_decoder_cmd dec; + DEBUG_PRINT_LOW("in %s", __func__); + dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH; + switch (flushType) + { + case OMX_CORE_INPUT_PORT_INDEX: + input_flush_progress = true; + dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT; + break; + case OMX_CORE_OUTPUT_PORT_INDEX: + output_flush_progress = true; + dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE; + break; + default: + input_flush_progress = true; + output_flush_progress = true; + dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | + V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE; + } + + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) + { + DEBUG_PRINT_ERROR("\n Flush Port (%d) Failed ", flushType); + bRet = false; + } + + return bRet; +} +/*========================================================================= +FUNCTION : execute_output_flush + +DESCRIPTION + Executes the OMX flush at OUTPUT PORT. + +PARAMETERS + None. + +RETURN VALUE + true/false +==========================================================================*/ +bool omx_vdec::execute_output_flush() +{ + unsigned p1 = 0; // Parameter - 1 + unsigned p2 = 0; // Parameter - 2 + unsigned ident = 0; + bool bRet = true; + + /*Generate FBD for all Buffers in the FTBq*/ + pthread_mutex_lock(&m_lock); + DEBUG_PRINT_LOW("\n Initiate Output Flush"); + while (m_ftb_q.m_size) + { + DEBUG_PRINT_LOW("\n Buffer queue size %d pending buf cnt %d", + m_ftb_q.m_size,pending_output_buffers); + m_ftb_q.pop_entry(&p1,&p2,&ident); + DEBUG_PRINT_LOW("\n ID(%x) P1(%x) P2(%x)", ident, p1, p2); + if(ident == OMX_COMPONENT_GENERATE_FTB ) + { + pending_output_buffers++; + fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); + } + else if (ident == OMX_COMPONENT_GENERATE_FBD) + { + fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); + } + } + pthread_mutex_unlock(&m_lock); + output_flush_progress = false; + + if (arbitrary_bytes) + { + prev_ts = LLONG_MAX; + rst_prev_ts = true; + } + DEBUG_PRINT_HIGH("\n OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers); + return bRet; +} +/*========================================================================= +FUNCTION : execute_input_flush + +DESCRIPTION + Executes the OMX flush at INPUT PORT. + +PARAMETERS + None. + +RETURN VALUE + true/false +==========================================================================*/ +bool omx_vdec::execute_input_flush() +{ + unsigned i =0; + unsigned p1 = 0; // Parameter - 1 + unsigned p2 = 0; // Parameter - 2 + unsigned ident = 0; + bool bRet = true; + + /*Generate EBD for all Buffers in the ETBq*/ + DEBUG_PRINT_LOW("\n Initiate Input Flush \n"); + + pthread_mutex_lock(&m_lock); + DEBUG_PRINT_LOW("\n Check if the Queue is empty \n"); + while (m_etb_q.m_size) + { + m_etb_q.pop_entry(&p1,&p2,&ident); + + if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) + { + DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2); + m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2); + } + else if(ident == OMX_COMPONENT_GENERATE_ETB) + { + pending_input_buffers++; + DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d", + (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers); + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); + } + else if (ident == OMX_COMPONENT_GENERATE_EBD) + { + DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p", + (OMX_BUFFERHEADERTYPE *)p1); + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); + } + } + time_stamp_dts.flush_timestamp(); + /*Check if Heap Buffers are to be flushed*/ + if (arbitrary_bytes) + { + DEBUG_PRINT_LOW("\n Reset all the variables before flusing"); + h264_scratch.nFilledLen = 0; + nal_count = 0; + look_ahead_nal = false; + frame_count = 0; + h264_last_au_ts = LLONG_MAX; + h264_last_au_flags = 0; + memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); + m_demux_entries = 0; + DEBUG_PRINT_LOW("\n Initialize parser"); + if (m_frame_parser.mutils) + { + m_frame_parser.mutils->initialize_frame_checking_environment(); + } + + while (m_input_pending_q.m_size) + { + m_input_pending_q.pop_entry(&p1,&p2,&ident); + m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1); + } + + if (psource_frame) + { + m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame); + psource_frame = NULL; + } + + if (pdest_frame) + { + pdest_frame->nFilledLen = 0; + m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL); + pdest_frame = NULL; + } + m_frame_parser.flush(); + } + pthread_mutex_unlock(&m_lock); + input_flush_progress = false; + if (!arbitrary_bytes) + { + prev_ts = LLONG_MAX; + rst_prev_ts = true; + } +#ifdef _ANDROID_ + if (m_debug_timestamp) + { + m_timestamp_list.reset_ts_list(); + } +#endif + DEBUG_PRINT_HIGH("\n OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers); + return bRet; +} + + +/* ====================================================================== +FUNCTION + omx_vdec::SendCommandEvent + +DESCRIPTION + Send the event to decoder pipe. This is needed to generate the callbacks + in decoder thread context. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_vdec::post_event(unsigned int p1, + unsigned int p2, + unsigned int id) +{ + bool bRet = false; + + + pthread_mutex_lock(&m_lock); + + if (id == OMX_COMPONENT_GENERATE_FTB || + id == OMX_COMPONENT_GENERATE_FBD) + { + m_ftb_q.insert_entry(p1,p2,id); + } + else if (id == OMX_COMPONENT_GENERATE_ETB || + id == OMX_COMPONENT_GENERATE_EBD || + id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) + { + m_etb_q.insert_entry(p1,p2,id); + } + else + { + m_cmd_q.insert_entry(p1,p2,id); + } + + bRet = true; + DEBUG_PRINT_LOW("\n Value of this pointer in post_event %p",this); + post_message(this, id); + + pthread_mutex_unlock(&m_lock); + + return bRet; +} + +OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(!profileLevelType) + return OMX_ErrorBadParameter; + + if(profileLevelType->nPortIndex == 0) { + if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + + } + else if (profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + } + else if(profileLevelType->nProfileIndex == 2) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + } + else + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", + profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_H263Level70; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else if(profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) + { + eRet = OMX_ErrorNoMore; + } + else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; + } + else if(profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain; + profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n", profileLevelType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::GetParameter + +DESCRIPTION + OMX Get Parameter method implementation + +PARAMETERS + . + +RETURN VALUE + Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_INOUT OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + DEBUG_PRINT_LOW("get_parameter: \n"); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(paramData == NULL) + { + DEBUG_PRINT_LOW("Get Param in Invalid paramData \n"); + return OMX_ErrorBadParameter; + } + switch(paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn = + (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition\n"); + eRet = update_portdef(portDefn); + if (eRet == OMX_ErrorNone) + m_port_def = *portDefn; + break; + } + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n"); + + portParamType->nVersion.nVersion = OMX_SPEC_VERSION; + portParamType->nSize = sizeof(portParamType); + portParamType->nPorts = 2; + portParamType->nStartPortNumber = 0; + break; + } + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = + (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat\n"); + + portFmt->nVersion.nVersion = OMX_SPEC_VERSION; + portFmt->nSize = sizeof(portFmt); + + if (0 == portFmt->nPortIndex) + { + if (0 == portFmt->nIndex) + { + portFmt->eColorFormat = OMX_COLOR_FormatUnused; + portFmt->eCompressionFormat = eCompressionFormat; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\ + " NoMore compression formats\n"); + eRet = OMX_ErrorNoMore; + } + } + else if (1 == portFmt->nPortIndex) + { + portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused; + + if(0 == portFmt->nIndex) + portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE) + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; + else + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\ + " NoMore Color formats\n"); + eRet = OMX_ErrorNoMore; + } + portFmt->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n", + (int)portFmt->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + /*Component should support this port definition*/ + case OMX_IndexParamAudioInit: + { + OMX_PORT_PARAM_TYPE *audioPortParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit\n"); + audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION; + audioPortParamType->nSize = sizeof(audioPortParamType); + audioPortParamType->nPorts = 0; + audioPortParamType->nStartPortNumber = 0; + break; + } + /*Component should support this port definition*/ + case OMX_IndexParamImageInit: + { + OMX_PORT_PARAM_TYPE *imagePortParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit\n"); + imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION; + imagePortParamType->nSize = sizeof(imagePortParamType); + imagePortParamType->nPorts = 0; + imagePortParamType->nStartPortNumber = 0; + break; + + } + /*Component should support this port definition*/ + case OMX_IndexParamOtherInit: + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x\n", + paramIndex); + eRet =OMX_ErrorUnsupportedIndex; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *comp_role; + comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; + comp_role->nVersion.nVersion = OMX_SPEC_VERSION; + comp_role->nSize = sizeof(*comp_role); + + DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d\n", + paramIndex); + strlcpy((char*)comp_role->cRole,(const char*)m_cRole, + OMX_MAX_STRINGNAME_SIZE); + break; + } + /* Added for parameter test */ + case OMX_IndexParamPriorityMgmt: + { + + OMX_PRIORITYMGMTTYPE *priorityMgmType = + (OMX_PRIORITYMGMTTYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n"); + priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION; + priorityMgmType->nSize = sizeof(priorityMgmType); + + break; + } + /* Added for parameter test */ + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = + (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n"); + + bufferSupplierType->nSize = sizeof(bufferSupplierType); + bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; + if(0 == bufferSupplierType->nPortIndex) + bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; + else if (1 == bufferSupplierType->nPortIndex) + bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; + else + eRet = OMX_ErrorBadPortIndex; + + + break; + } + case OMX_IndexParamVideoAvc: + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x\n", + paramIndex); + break; + } + case OMX_IndexParamVideoH263: + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x\n", + paramIndex); + break; + } + case OMX_IndexParamVideoMpeg4: + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x\n", + paramIndex); + break; + } + case OMX_IndexParamVideoMpeg2: + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x\n", + paramIndex); + break; + } + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x\n", paramIndex); + OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType = + (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData; + eRet = get_supported_profile_level_for_1080p(profileLevelType); + break; + } +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) + case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: + { + DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage\n"); + GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData; + if(nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) { + + if(secure_mode) { + nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED | + GRALLOC_USAGE_PRIVATE_UNCACHED); + } else { + nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED); + } + } else { + DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!\n"); + eRet = OMX_ErrorBadParameter; + } + } + break; +#endif + + default: + { + DEBUG_PRINT_ERROR("get_parameter: unknown param %08x\n", paramIndex); + eRet =OMX_ErrorUnsupportedIndex; + } + + } + + DEBUG_PRINT_LOW("\n get_parameter returning WxH(%d x %d) SxSH(%d x %d)\n", + drv_ctx.video_resolution.frame_width, + drv_ctx.video_resolution.frame_height, + drv_ctx.video_resolution.stride, + drv_ctx.video_resolution.scan_lines); + + return eRet; +} + +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) +OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data) +{ + DEBUG_PRINT_LOW("Inside use_android_native_buffer"); + OMX_ERRORTYPE eRet = OMX_ErrorNone; + UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data; + + if((params == NULL) || + (params->nativeBuffer == NULL) || + (params->nativeBuffer->handle == NULL) || + !m_enable_android_native_buffers) + return OMX_ErrorBadParameter; + m_use_android_native_buffers = OMX_TRUE; + sp nBuf = params->nativeBuffer; + private_handle_t *handle = (private_handle_t *)nBuf->handle; + if(OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port + OMX_U8 *buffer = NULL; + if(!secure_mode) { + buffer = (OMX_U8*)mmap(0, handle->size, + PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); + if(buffer == MAP_FAILED) { + DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); + return OMX_ErrorInsufficientResources; + } + } + eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer); + } else { + eRet = OMX_ErrorBadParameter; + } + return eRet; +} +#endif +/* ====================================================================== +FUNCTION + omx_vdec::Setparameter + +DESCRIPTION + OMX Set Parameter method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_IN OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Set Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(paramData == NULL) + { + DEBUG_PRINT_ERROR("Get Param in Invalid paramData \n"); + return OMX_ErrorBadParameter; + } + if((m_state != OMX_StateLoaded) && + BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) && + (m_out_bEnabled == OMX_TRUE) && + BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) && + (m_inp_bEnabled == OMX_TRUE)) { + DEBUG_PRINT_ERROR("Set Param in Invalid State \n"); + return OMX_ErrorIncorrectStateOperation; + } + switch(paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has + //been called. + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d\n", + (int)portDefn->format.video.nFrameHeight, + (int)portDefn->format.video.nFrameWidth); + if(OMX_DirOutput == portDefn->eDir) + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port\n"); + m_display_id = portDefn->format.video.pNativeWindow; + if ( portDefn->nBufferCountActual >= drv_ctx.op_buf.mincount && + portDefn->nBufferSize >= drv_ctx.op_buf.buffer_size ) + { + drv_ctx.op_buf.actualcount = portDefn->nBufferCountActual; + drv_ctx.op_buf.buffer_size = portDefn->nBufferSize; + eRet = set_buffer_req(&drv_ctx.op_buf); + if (eRet == OMX_ErrorNone) + m_port_def = *portDefn; + } + else + { + DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%d: %u)\n", + drv_ctx.op_buf.mincount, drv_ctx.op_buf.buffer_size, + portDefn->nBufferCountActual, portDefn->nBufferSize); + eRet = OMX_ErrorBadParameter; + } + } + else if(OMX_DirInput == portDefn->eDir) + { + if((portDefn->format.video.xFramerate >> 16) > 0 && + (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) + { + // Frame rate only should be set if this is a "known value" or to + // activate ts prediction logic (arbitrary mode only) sending input + // timestamps with max value (LLONG_MAX). + DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %d", + portDefn->format.video.xFramerate >> 16); + Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator, + drv_ctx.frame_rate.fps_denominator); + if(!drv_ctx.frame_rate.fps_numerator) + { + DEBUG_PRINT_ERROR("Numerator is zero setting to 30"); + drv_ctx.frame_rate.fps_numerator = 30; + } + if(drv_ctx.frame_rate.fps_denominator) + drv_ctx.frame_rate.fps_numerator = (int) + drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator; + drv_ctx.frame_rate.fps_denominator = 1; + frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 / + drv_ctx.frame_rate.fps_numerator; + ioctl_msg.in = &drv_ctx.frame_rate; + if (/*ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_FRAME_RATE, + (void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("Setting frame rate to driver failed"); + } + DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)", + frm_int, drv_ctx.frame_rate.fps_numerator / + (float)drv_ctx.frame_rate.fps_denominator); + } + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port\n"); + if(drv_ctx.video_resolution.frame_height != + portDefn->format.video.nFrameHeight || + drv_ctx.video_resolution.frame_width != + portDefn->format.video.nFrameWidth) + { + DEBUG_PRINT_LOW("\n SetParam IP: WxH(%d x %d)\n", + portDefn->format.video.nFrameWidth, + portDefn->format.video.nFrameHeight); + if (portDefn->format.video.nFrameHeight != 0x0 && + portDefn->format.video.nFrameWidth != 0x0) + { + drv_ctx.video_resolution.frame_height = + drv_ctx.video_resolution.scan_lines = + portDefn->format.video.nFrameHeight; + drv_ctx.video_resolution.frame_width = + drv_ctx.video_resolution.stride = + portDefn->format.video.nFrameWidth; + ioctl_msg.in = &drv_ctx.video_resolution; + ioctl_msg.out = NULL; + if (/*ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_PICRES, + (void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\n Set Resolution failed"); + eRet = OMX_ErrorUnsupportedSetting; + } + else + eRet = get_buffer_req(&drv_ctx.op_buf); + } + } + else if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount + && portDefn->nBufferSize == drv_ctx.ip_buf.buffer_size) + { + drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual; + drv_ctx.ip_buf.buffer_size = portDefn->nBufferSize; + eRet = set_buffer_req(&drv_ctx.ip_buf); + } + else + { + DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%d: %u)\n", + drv_ctx.ip_buf.mincount, drv_ctx.ip_buf.buffer_size, + portDefn->nBufferCountActual, portDefn->nBufferSize); + eRet = OMX_ErrorBadParameter; + } + } + else if (portDefn->eDir == OMX_DirMax) + { + DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d", + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + } + break; + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = + (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; + int ret=0; + struct v4l2_format fmt; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d\n", + portFmt->eColorFormat); + + if(1 == portFmt->nPortIndex) + { + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; + fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; + fmt.fmt.pix_mp.pixelformat = capture_capability; + enum vdec_output_fromat op_format; + if(portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) + op_format = VDEC_YUV_FORMAT_NV12; + else if(portFmt->eColorFormat == + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka) + op_format = VDEC_YUV_FORMAT_TILE_4x2; + else + eRet = OMX_ErrorBadParameter; + + if(eRet == OMX_ErrorNone) + { + drv_ctx.output_format = op_format; + ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); + if(ret) + { + DEBUG_PRINT_ERROR("\n Set output format failed"); + eRet = OMX_ErrorUnsupportedSetting; + /*TODO: How to handle this case */ + } + else + { + eRet = get_buffer_req(&drv_ctx.op_buf); + } + } + } + } + break; + + case OMX_QcomIndexPortDefn: + { + OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt = + (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %d\n", + portFmt->nFramePackingFormat); + + /* Input port */ + if (portFmt->nPortIndex == 0) + { + if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) + { + if(secure_mode) { + arbitrary_bytes = false; + DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode in secure session"); + eRet = OMX_ErrorUnsupportedSetting; + } else { + arbitrary_bytes = true; + } + } + else if (portFmt->nFramePackingFormat == + OMX_QCOM_FramePacking_OnlyOneCompleteFrame) + { + arbitrary_bytes = false; + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %d\n", + portFmt->nFramePackingFormat); + eRet = OMX_ErrorUnsupportedSetting; + } + } + else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) + { + DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port\n"); + if( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid && + portFmt->nMemRegion < OMX_QCOM_MemRegionMax) && + portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) + { + m_out_mem_region_smi = OMX_TRUE; + if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) + { + DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set\n"); + m_use_output_pmem = OMX_TRUE; + } + } + } + } + break; + + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *comp_role; + comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s\n", + comp_role->cRole); + + if((m_state == OMX_StateLoaded)&& + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + DEBUG_PRINT_LOW("Set Parameter called in valid state"); + } + else + { + DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + + if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((char*)comp_role->cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet =OMX_ErrorUnsupportedSetting; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet = OMX_ErrorUnsupportedSetting; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((const char*)comp_role->cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet =OMX_ErrorUnsupportedSetting; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((const char*)comp_role->cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet = OMX_ErrorUnsupportedSetting; + } + } + else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) || + (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE)) + ) + { + if(!strncmp((const char*)comp_role->cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet =OMX_ErrorUnsupportedSetting; + } + } + else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) || + (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE)) + ) + { + if(!strncmp((const char*)comp_role->cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet =OMX_ErrorUnsupportedSetting; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((const char*)comp_role->cRole,"video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown Index %s\n", comp_role->cRole); + eRet = OMX_ErrorUnsupportedSetting; + } + } + else + { + DEBUG_PRINT_ERROR("Setparameter: unknown param %s\n", drv_ctx.kind); + eRet = OMX_ErrorInvalidComponentName; + } + break; + } + + case OMX_IndexParamPriorityMgmt: + { + if(m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %d\n", + priorityMgmtype->nGroupID); + + DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %d\n", + priorityMgmtype->nGroupPriority); + + m_priority_mgm.nGroupID = priorityMgmtype->nGroupID; + m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority; + + break; + } + + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d\n", + bufferSupplierType->eBufferSupplier); + if(bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1) + m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier; + + else + + eRet = OMX_ErrorBadPortIndex; + + break; + + } + case OMX_IndexParamVideoAvc: + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d\n", + paramIndex); + break; + } + case OMX_IndexParamVideoH263: + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d\n", + paramIndex); + break; + } + case OMX_IndexParamVideoMpeg4: + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d\n", + paramIndex); + break; + } + case OMX_IndexParamVideoMpeg2: + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d\n", + paramIndex); + break; + } + case OMX_QcomIndexParamVideoDecoderPictureOrder: + { + QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder = + (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData; + struct v4l2_control control; + int pic_order,rc=0; + DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d\n", + pictureOrder->eOutputPictureOrder); + if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) { + pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY; + } + else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER){ + pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE; + time_stamp_dts.set_timestamp_reorder_mode(false); + } + else + eRet = OMX_ErrorBadParameter; + if (eRet == OMX_ErrorNone) + { + control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER; + control.value = pic_order; + rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control); + if(rc) + { + DEBUG_PRINT_ERROR("\n Set picture order failed"); + eRet = OMX_ErrorUnsupportedSetting; + } + } + break; + } + case OMX_QcomIndexParamConcealMBMapExtraData: + if(!secure_mode) + eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, + ((QOMX_ENABLETYPE *)paramData)->bEnable); + else { + DEBUG_PRINT_ERROR("\n secure mode setting not supported"); + eRet = OMX_ErrorUnsupportedSetting; + } + break; + case OMX_QcomIndexParamFrameInfoExtraData: + { + if(!secure_mode) + eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, + ((QOMX_ENABLETYPE *)paramData)->bEnable); + else { + DEBUG_PRINT_ERROR("\n secure mode setting not supported"); + eRet = OMX_ErrorUnsupportedSetting; + } + break; + } + case OMX_QcomIndexParamInterlaceExtraData: + if(!secure_mode) + eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, + ((QOMX_ENABLETYPE *)paramData)->bEnable); + else { + DEBUG_PRINT_ERROR("\n secure mode setting not supported"); + eRet = OMX_ErrorUnsupportedSetting; + } + break; + case OMX_QcomIndexParamH264TimeInfo: + if(!secure_mode) + eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, + ((QOMX_ENABLETYPE *)paramData)->bEnable); + else { + DEBUG_PRINT_ERROR("\n secure mode setting not supported"); + eRet = OMX_ErrorUnsupportedSetting; + } + break; + case OMX_QcomIndexParamVideoDivx: + { + QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData; + +#if 0 + createDivxDrmContext( divXType->pDrmHandle ); +#endif + } + break; + case OMX_QcomIndexPlatformPvt: + { + DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port\n"); + OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData; + if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) + { + DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type); + eRet = OMX_ErrorUnsupportedSetting; + } + else + { + m_out_pvt_entry_pmem = OMX_TRUE; + if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) + { + DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set\n"); + m_use_output_pmem = OMX_TRUE; + } + } + + } + break; + case OMX_QcomIndexParamVideoSyncFrameDecodingMode: + { + DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode"); + DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode"); + drv_ctx.idr_only_decoding = 1; + int rc; //= ioctl(drv_ctx.video_driver_fd, + // VDEC_IOCTL_SET_IDR_ONLY_DECODING); + if(rc < 0) { + DEBUG_PRINT_ERROR("Failed to set IDR only decoding on driver."); + eRet = OMX_ErrorHardware; + } + } + break; + + case OMX_QcomIndexParamIndexExtraDataType: + { + if(!secure_mode) { + QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData; + if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) && + (extradataIndexType->bEnabled == OMX_TRUE) && + (extradataIndexType->nPortIndex == 1)) + { + DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming\n"); + eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, extradataIndexType->bEnabled); + // Set smooth streaming parameter + int rc;// = ioctl(drv_ctx.video_driver_fd, + // VDEC_IOCTL_SET_CONT_ON_RECONFIG); + if(rc < 0) { + DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver."); + eRet = OMX_ErrorHardware; + } + } + } + } + break; + +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) + /* Need to allow following two set_parameters even in Idle + * state. This is ANDROID architecture which is not in sync + * with openmax standard. */ + case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: + { + EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData; + if(enableNativeBuffers) { + m_enable_android_native_buffers = enableNativeBuffers->enable; + } + } + break; + case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: + { + eRet = use_android_native_buffer(hComp, paramData); + } + break; +#endif + case OMX_QcomIndexParamEnableTimeStampReorder: + { + QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData; + if (drv_ctx.picture_order == QOMX_VIDEO_DISPLAY_ORDER) { + if (reorder->bEnable == OMX_TRUE) { + frm_int =0; + time_stamp_dts.set_timestamp_reorder_mode(true); + } + else + time_stamp_dts.set_timestamp_reorder_mode(false); + } else { + time_stamp_dts.set_timestamp_reorder_mode(false); + if (reorder->bEnable == OMX_TRUE) + { + eRet = OMX_ErrorUnsupportedSetting; + } + } + } + break; + default: + { + DEBUG_PRINT_ERROR("Setparameter: unknown param %d\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::GetConfig + +DESCRIPTION + OMX Get Config Method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_INOUT OMX_PTR configData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if (m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + switch (configIndex) + { + case OMX_QcomIndexConfigInterlaced: + { + OMX_QCOM_CONFIG_INTERLACETYPE *configFmt = + (OMX_QCOM_CONFIG_INTERLACETYPE *) configData; + if (configFmt->nPortIndex == 1) + { + if (configFmt->nIndex == 0) + { + configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive; + } + else if (configFmt->nIndex == 1) + { + configFmt->eInterlaceType = + OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; + } + else if (configFmt->nIndex == 2) + { + configFmt->eInterlaceType = + OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; + } + else + { + DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:" + " NoMore Interlaced formats\n"); + eRet = OMX_ErrorNoMore; + } + + } + else + { + DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port\n", + (int)configFmt->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_QcomIndexQueryNumberOfVideoDecInstance: + { + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances = + (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData; + //ioctl_msg.out = (void*)&decoderinstances->nNumOfInstances; + //(void)(ioctl(drv_ctx.video_driver_fd, + //VDEC_IOCTL_GET_NUMBER_INSTANCES,&ioctl_msg)); + + decoderinstances->nNumOfInstances = 16; + /*TODO: How to handle this case */ + break; + } + case OMX_QcomIndexConfigVideoFramePackingArrangement: + { + if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt = + (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData; + h264_parser->get_frame_pack_data(configFmt); + } + else + { + DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs"); + } + break; + } + default: + { + DEBUG_PRINT_ERROR("get_config: unknown param %d\n",configIndex); + eRet = OMX_ErrorBadParameter; + } + + } + + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::SetConfig + +DESCRIPTION + OMX Set Config method implementation + +PARAMETERS + . + +RETURN VALUE + OMX Error None if successful. +========================================================================== */ +OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_IN OMX_PTR configData) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Config in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_VIDEO_CONFIG_NALSIZE *pNal; + + DEBUG_PRINT_LOW("\n Set Config Called"); + + if (m_state == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("set_config:Ignore in Exe state\n"); + return ret; + } + + if (configIndex == OMX_IndexVendorVideoExtraData) + { + OMX_VENDOR_EXTRADATATYPE *config = (OMX_VENDOR_EXTRADATATYPE *) configData; + DEBUG_PRINT_LOW("\n Index OMX_IndexVendorVideoExtraData called"); + if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc")) + { + DEBUG_PRINT_LOW("\n Index OMX_IndexVendorVideoExtraData AVC"); + OMX_U32 extra_size; + // Parsing done here for the AVC atom is definitely not generic + // Currently this piece of code is working, but certainly + // not tested with all .mp4 files. + // Incase of failure, we might need to revisit this + // for a generic piece of code. + + // Retrieve size of NAL length field + // byte #4 contains the size of NAL lenght field + nal_length = (config->pData[4] & 0x03) + 1; + + extra_size = 0; + if (nal_length > 2) + { + /* Presently we assume that only one SPS and one PPS in AvC1 Atom */ + extra_size = (nal_length - 2) * 2; + } + + // SPS starts from byte #6 + OMX_U8 *pSrcBuf = (OMX_U8 *) (&config->pData[6]); + OMX_U8 *pDestBuf; + m_vendor_config.nPortIndex = config->nPortIndex; + + // minus 6 --> SPS starts from byte #6 + // minus 1 --> picture param set byte to be ignored from avcatom + m_vendor_config.nDataSize = config->nDataSize - 6 - 1 + extra_size; + m_vendor_config.pData = (OMX_U8 *) malloc(m_vendor_config.nDataSize); + OMX_U32 len; + OMX_U8 index = 0; + // case where SPS+PPS is sent as part of set_config + pDestBuf = m_vendor_config.pData; + + DEBUG_PRINT_LOW("Rxd SPS+PPS nPortIndex[%d] len[%d] data[0x%x]\n", + m_vendor_config.nPortIndex, + m_vendor_config.nDataSize, + m_vendor_config.pData); + while (index < 2) + { + uint8 *psize; + len = *pSrcBuf; + len = len << 8; + len |= *(pSrcBuf + 1); + psize = (uint8 *) & len; + memcpy(pDestBuf + nal_length, pSrcBuf + 2,len); + for (int i = 0; i < nal_length; i++) + { + pDestBuf[i] = psize[nal_length - 1 - i]; + } + //memcpy(pDestBuf,pSrcBuf,(len+2)); + pDestBuf += len + nal_length; + pSrcBuf += len + 2; + index++; + pSrcBuf++; // skip picture param set + len = 0; + } + } + else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4") || + !strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2")) + { + m_vendor_config.nPortIndex = config->nPortIndex; + m_vendor_config.nDataSize = config->nDataSize; + m_vendor_config.pData = (OMX_U8 *) malloc((config->nDataSize)); + memcpy(m_vendor_config.pData, config->pData,config->nDataSize); + } + else if (!strcmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1")) + { + if(m_vendor_config.pData) + { + free(m_vendor_config.pData); + m_vendor_config.pData = NULL; + m_vendor_config.nDataSize = 0; + } + + if (((*((OMX_U32 *) config->pData)) & + VC1_SP_MP_START_CODE_MASK) == + VC1_SP_MP_START_CODE) + { + DEBUG_PRINT_LOW("set_config - VC1 simple/main profile\n"); + m_vendor_config.nPortIndex = config->nPortIndex; + m_vendor_config.nDataSize = config->nDataSize; + m_vendor_config.pData = + (OMX_U8 *) malloc(config->nDataSize); + memcpy(m_vendor_config.pData, config->pData, + config->nDataSize); + m_vc1_profile = VC1_SP_MP_RCV; + } + else if (*((OMX_U32 *) config->pData) == VC1_AP_SEQ_START_CODE) + { + DEBUG_PRINT_LOW("set_config - VC1 Advance profile\n"); + m_vendor_config.nPortIndex = config->nPortIndex; + m_vendor_config.nDataSize = config->nDataSize; + m_vendor_config.pData = + (OMX_U8 *) malloc((config->nDataSize)); + memcpy(m_vendor_config.pData, config->pData, + config->nDataSize); + m_vc1_profile = VC1_AP; + } + else if ((config->nDataSize == VC1_STRUCT_C_LEN)) + { + DEBUG_PRINT_LOW("set_config - VC1 Simple/Main profile struct C only\n"); + m_vendor_config.nPortIndex = config->nPortIndex; + m_vendor_config.nDataSize = config->nDataSize; + m_vendor_config.pData = (OMX_U8*)malloc(config->nDataSize); + memcpy(m_vendor_config.pData,config->pData,config->nDataSize); + m_vc1_profile = VC1_SP_MP_RCV; + } + else + { + DEBUG_PRINT_LOW("set_config - Error: Unknown VC1 profile\n"); + } + } + return ret; + } + else if (configIndex == OMX_IndexConfigVideoNalSize) + { + + pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData); + nal_length = pNal->nNaluBytes; + m_frame_parser.init_nal_length(nal_length); + DEBUG_PRINT_LOW("\n OMX_IndexConfigVideoNalSize called with Size %d",nal_length); + return ret; + } + + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_vdec::GetExtensionIndex + +DESCRIPTION + OMX GetExtensionIndex method implementaion. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_STRING paramName, + OMX_OUT OMX_INDEXTYPE* indexType) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Get Extension Index in Invalid State\n"); + return OMX_ErrorInvalidState; + } + else if (!strncmp(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode",sizeof("OMX.QCOM.index.param.video.SyncFrameDecodingMode") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode; + } + else if (!strncmp(paramName, "OMX.QCOM.index.param.IndexExtraData",sizeof("OMX.QCOM.index.param.IndexExtraData") - 1)) + { + *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType; + } +#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) + else if(!strncmp(paramName,"OMX.google.android.index.enableAndroidNativeBuffers", sizeof("OMX.google.android.index.enableAndroidNativeBuffers") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers; + } + else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer2", sizeof("OMX.google.android.index.enableAndroidNativeBuffer2") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2; + } + else if(!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer", sizeof("OMX.google.android.index.enableAndroidNativeBuffer") - 1)) { + DEBUG_PRINT_ERROR("Extension: %s is supported\n", paramName); + *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer; + } + else if(!strncmp(paramName,"OMX.google.android.index.getAndroidNativeBufferUsage", sizeof("OMX.google.android.index.getAndroidNativeBufferUsage") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage; + } +#endif + else { + DEBUG_PRINT_ERROR("Extension: %s not implemented\n", paramName); + return OMX_ErrorNotImplemented; + } + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::GetState + +DESCRIPTION + Returns the state information back to the caller. + +PARAMETERS + . + +RETURN VALUE + Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STATETYPE* state) +{ + *state = m_state; + DEBUG_PRINT_LOW("get_state: Returning the state %d\n",*state); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::ComponentTunnelRequest + +DESCRIPTION + OMX Component Tunnel Request method implementation. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_HANDLETYPE peerComponent, + OMX_IN OMX_U32 peerPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) +{ + DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented\n"); + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_vdec::UseOutputBuffer + +DESCRIPTION + Helper function for Use buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::use_output_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header + unsigned i= 0; // Temporary counter + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct vdec_setbuffer_cmd setbuffers; + OMX_PTR privateAppData = NULL; + private_handle_t *handle = NULL; + OMX_U8 *buff = buffer; + if (!m_out_mem_ptr) { + DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers"); + eRet = allocate_output_headers(); + } + + if (eRet == OMX_ErrorNone) { + for(i=0; i< drv_ctx.op_buf.actualcount; i++) { + if(BITMASK_ABSENT(&m_out_bm_count,i)) + { + break; + } + } + } + + if(i >= drv_ctx.op_buf.actualcount) { + eRet = OMX_ErrorInsufficientResources; + } + + if (eRet == OMX_ErrorNone) { +#if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_) + if(m_enable_android_native_buffers) { + if(m_use_android_native_buffers) { + UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData; + sp nBuf = params->nativeBuffer; + handle = (private_handle_t *)nBuf->handle; + privateAppData = params->pAppPrivate; + } + else { + handle = (private_handle_t *)buff; + if(!secure_mode) { + buff = (OMX_U8*)mmap(0, handle->size, + PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); + if (buff == MAP_FAILED) { + DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size); + return OMX_ErrorInsufficientResources; + } + } + privateAppData = appData; + } +#if defined(_ANDROID_ICS_) + native_buffer[i].nativehandle = handle; +#endif + if(!handle) { + DEBUG_PRINT_ERROR("Native Buffer handle is NULL"); + return OMX_ErrorBadParameter; + } + drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd; + drv_ctx.ptr_outputbuffer[i].offset = 0; + drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; + drv_ctx.ptr_outputbuffer[i].mmaped_size = + drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; + } else +#endif + + if (!ouput_egl_buffers && !m_use_output_pmem) { +#ifdef USE_ION + drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( + drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment, + &drv_ctx.op_buf_ion_info[i].ion_alloc_data, + &drv_ctx.op_buf_ion_info[i].fd_ion_data, 0); + if(drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) { + return OMX_ErrorInsufficientResources; + } + drv_ctx.ptr_outputbuffer[i].pmem_fd = \ + drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; +#else + drv_ctx.ptr_outputbuffer[i].pmem_fd = \ + open (MEM_DEVICE,O_RDWR); + + if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { + return OMX_ErrorInsufficientResources; + } + + if(drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) + { + drv_ctx.ptr_outputbuffer[i].pmem_fd = \ + open (MEM_DEVICE,O_RDWR); + if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) { + return OMX_ErrorInsufficientResources; + } + } + + if(!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd, + drv_ctx.op_buf.buffer_size, + drv_ctx.op_buf.alignment)) + { + DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed"); + close(drv_ctx.ptr_outputbuffer[i].pmem_fd); + return OMX_ErrorInsufficientResources; + } +#endif + if(!secure_mode) { + drv_ctx.ptr_outputbuffer[i].bufferaddr = + (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size, + PROT_READ|PROT_WRITE, MAP_SHARED, + drv_ctx.ptr_outputbuffer[i].pmem_fd,0); + if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) { + close(drv_ctx.ptr_outputbuffer[i].pmem_fd); +#ifdef USE_ION + free_ion_memory(&drv_ctx.op_buf_ion_info[i]); +#endif + return OMX_ErrorInsufficientResources; + } + } + drv_ctx.ptr_outputbuffer[i].offset = 0; + privateAppData = appData; + } + else { + + DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem); + if (!appData || !bytes ) { + if(!secure_mode && !buffer) { + DEBUG_PRINT_ERROR("\n Bad parameters for use buffer in EGL image case"); + return OMX_ErrorBadParameter; + } + } + + OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list; + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info; + pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData; + if (!pmem_list->entryList || !pmem_list->entryList->entry || + !pmem_list->nEntries || + pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) { + DEBUG_PRINT_ERROR("\n Pmem info not valid in use buffer"); + return OMX_ErrorBadParameter; + } + pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + pmem_list->entryList->entry; + DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%x", + pmem_info->pmem_fd); + drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd; + drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset; + drv_ctx.ptr_outputbuffer[i].bufferaddr = buff; + drv_ctx.ptr_outputbuffer[i].mmaped_size = + drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size; + privateAppData = appData; + } + m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; + m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd; + + *bufferHdr = (m_out_mem_ptr + i ); + if(secure_mode) + drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; + //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i], + sizeof (vdec_bufferpayload)); + + // ioctl_msg.in = &setbuffers; + // ioctl_msg.out = NULL; + + DEBUG_PRINT_HIGH("\n Set the Output Buffer Idx: %d Addr: %x, pmem_fd=%0x%x", i, + drv_ctx.ptr_outputbuffer[i],drv_ctx.ptr_outputbuffer[i].pmem_fd ); + // if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_BUFFER, + // &ioctl_msg) < 0) + // { + // DEBUG_PRINT_ERROR("\n Set output buffer failed"); + // return OMX_ErrorInsufficientResources; + // } + // found an empty buffer at i + (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size; + (*bufferHdr)->pBuffer = buff; + (*bufferHdr)->pAppPrivate = privateAppData; + BITMASK_SET(&m_out_bm_count,i); + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::use_input_heap_buffers + +DESCRIPTION + OMX Use Buffer Heap allocation method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None , if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::use_input_heap_buffers( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + DEBUG_PRINT_LOW("Inside %s, %p\n", __FUNCTION__, buffer); + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(!m_inp_heap_ptr) + m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) + calloc( (sizeof(OMX_BUFFERHEADERTYPE)), + drv_ctx.ip_buf.actualcount); + if(!m_phdr_pmem_ptr) + m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) + calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), + drv_ctx.ip_buf.actualcount); + if(!m_inp_heap_ptr || !m_phdr_pmem_ptr) + { + DEBUG_PRINT_ERROR("Insufficent memory"); + eRet = OMX_ErrorInsufficientResources; + } + else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) + { + input_use_buffer = true; + memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE)); + m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer; + m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes; + m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData; + m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput; + m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax; + *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt]; + eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes); + DEBUG_PRINT_HIGH("\n Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]); + if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr[m_in_alloc_cnt], NULL, NULL)) + { + DEBUG_PRINT_ERROR("\nERROR:Free_q is full"); + return OMX_ErrorInsufficientResources; + } + m_in_alloc_cnt++; + } + else + { + DEBUG_PRINT_ERROR("All i/p buffers have been set!"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_vdec::UseBuffer + +DESCRIPTION + OMX Use Buffer method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None , if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::use_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE error = OMX_ErrorNone; + struct vdec_setbuffer_cmd setbuffers; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + + if (bufferHdr == NULL || bytes == 0) + { + if(!secure_mode && buffer == NULL) { + DEBUG_PRINT_ERROR("bad param 0x%p %ld 0x%p",bufferHdr, bytes, buffer); + return OMX_ErrorBadParameter; + } + } + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Use Buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(port == OMX_CORE_INPUT_PORT_INDEX) + error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer); + else if(port == OMX_CORE_OUTPUT_PORT_INDEX) + error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested + else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port); + error = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", port, *bufferHdr, error); + if(error == OMX_ErrorNone) + { + if(allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); + post_event(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated && + BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + else if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated && + BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + return error; +} + +OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex, + OMX_BUFFERHEADERTYPE *pmem_bufferHdr) +{ + if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) + { + if(m_inp_heap_ptr[bufferindex].pBuffer) + free(m_inp_heap_ptr[bufferindex].pBuffer); + m_inp_heap_ptr[bufferindex].pBuffer = NULL; + } + if (pmem_bufferHdr) + free_input_buffer(pmem_bufferHdr); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) +{ + unsigned int index = 0; + if (bufferHdr == NULL || m_inp_mem_ptr == NULL) + { + return OMX_ErrorBadParameter; + } + + index = bufferHdr - m_inp_mem_ptr; + DEBUG_PRINT_LOW("\n Free Input Buffer index = %d",index); + + if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) + { + DEBUG_PRINT_LOW("\n Free Input Buffer index = %d",index); + if (drv_ctx.ptr_inputbuffer[index].pmem_fd > 0) + { + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct vdec_setbuffer_cmd setbuffers; + setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT; + memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index], + sizeof (vdec_bufferpayload)); + ioctl_msg.in = &setbuffers; + ioctl_msg.out = NULL; + int ioctl_r; //= ioctl (drv_ctx.video_driver_fd, + // VDEC_IOCTL_FREE_BUFFER, &ioctl_msg); + if (ioctl_r < 0) + { + DEBUG_PRINT_ERROR("\nVDEC_IOCTL_FREE_BUFFER returned error %d", ioctl_r); + } + + DEBUG_PRINT_LOW("\n unmap the input buffer fd=%d", + drv_ctx.ptr_inputbuffer[index].pmem_fd); + DEBUG_PRINT_LOW("\n unmap the input buffer size=%d address = %d", + drv_ctx.ptr_inputbuffer[index].mmaped_size, + drv_ctx.ptr_inputbuffer[index].bufferaddr); + munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr, + drv_ctx.ptr_inputbuffer[index].mmaped_size); + close (drv_ctx.ptr_inputbuffer[index].pmem_fd); + drv_ctx.ptr_inputbuffer[index].pmem_fd = -1; + if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) + { + free(m_desc_buffer_ptr[index].buf_addr); + m_desc_buffer_ptr[index].buf_addr = NULL; + m_desc_buffer_ptr[index].desc_data_size = 0; + } +#ifdef USE_ION + free_ion_memory(&drv_ctx.ip_buf_ion_info[index]); +#endif + } + } + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) +{ + unsigned int index = 0; + + if (bufferHdr == NULL || m_out_mem_ptr == NULL) + { + return OMX_ErrorBadParameter; + } + + index = bufferHdr - m_out_mem_ptr; + DEBUG_PRINT_LOW("\n Free ouput Buffer index = %d",index); + + if (index < drv_ctx.op_buf.actualcount + && drv_ctx.ptr_outputbuffer) + { + DEBUG_PRINT_LOW("\n Free ouput Buffer index = %d addr = %x", index, + drv_ctx.ptr_outputbuffer[index].bufferaddr); + + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct vdec_setbuffer_cmd setbuffers; + setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index], + sizeof (vdec_bufferpayload)); + ioctl_msg.in = &setbuffers; + ioctl_msg.out = NULL; + DEBUG_PRINT_LOW("\nRelease the Output Buffer"); + if (/*ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_FREE_BUFFER, + &ioctl_msg) < */0) + DEBUG_PRINT_ERROR("\nRelease output buffer failed in VCD"); + +#ifdef _ANDROID_ + if(m_enable_android_native_buffers) { + if(drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) { + munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr, + drv_ctx.ptr_outputbuffer[index].mmaped_size); + } + drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; + } else { +#endif + if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) + { + DEBUG_PRINT_LOW("\n unmap the output buffer fd = %d", + drv_ctx.ptr_outputbuffer[0].pmem_fd); + DEBUG_PRINT_LOW("\n unmap the ouput buffer size=%d address = %d", + drv_ctx.ptr_outputbuffer[0].mmaped_size, + drv_ctx.ptr_outputbuffer[0].bufferaddr); + munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr, + drv_ctx.ptr_outputbuffer[0].mmaped_size); + close (drv_ctx.ptr_outputbuffer[0].pmem_fd); + drv_ctx.ptr_outputbuffer[0].pmem_fd = -1; +#ifdef USE_ION + free_ion_memory(&drv_ctx.op_buf_ion_info[0]); +#endif + } +#ifdef _ANDROID_ + } +#endif + } + + return OMX_ErrorNone; + +} + +OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes) +{ + OMX_BUFFERHEADERTYPE *input = NULL; + unsigned char *buf_addr = NULL; + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned i = 0; + + /* Sanity Check*/ + if (bufferHdr == NULL) + { + return OMX_ErrorBadParameter; + } + + if (m_inp_heap_ptr == NULL) + { + m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \ + calloc( (sizeof(OMX_BUFFERHEADERTYPE)), + drv_ctx.ip_buf.actualcount); + m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \ + calloc( (sizeof(OMX_BUFFERHEADERTYPE*)), + drv_ctx.ip_buf.actualcount); + + if (m_inp_heap_ptr == NULL) + { + DEBUG_PRINT_ERROR("\n m_inp_heap_ptr Allocation failed "); + return OMX_ErrorInsufficientResources; + } + } + + /*Find a Free index*/ + for(i=0; i< drv_ctx.ip_buf.actualcount; i++) + { + if(BITMASK_ABSENT(&m_heap_inp_bm_count,i)) + { + DEBUG_PRINT_LOW("\n Free Input Buffer Index %d",i); + break; + } + } + + if (i < drv_ctx.ip_buf.actualcount) + { + buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size); + + if (buf_addr == NULL) + { + return OMX_ErrorInsufficientResources; + } + + *bufferHdr = (m_inp_heap_ptr + i); + input = *bufferHdr; + BITMASK_SET(&m_heap_inp_bm_count,i); + + input->pBuffer = (OMX_U8 *)buf_addr; + input->nSize = sizeof(OMX_BUFFERHEADERTYPE); + input->nVersion.nVersion = OMX_SPEC_VERSION; + input->nAllocLen = drv_ctx.ip_buf.buffer_size; + input->pAppPrivate = appData; + input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + DEBUG_PRINT_LOW("\n Address of Heap Buffer %p",*bufferHdr ); + eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes); + DEBUG_PRINT_LOW("\n Address of Pmem Buffer %p",m_phdr_pmem_ptr [i] ); + /*Add the Buffers to freeq*/ + if (!m_input_free_q.insert_entry((unsigned)m_phdr_pmem_ptr [i],NULL,NULL)) + { + DEBUG_PRINT_ERROR("\nERROR:Free_q is full"); + return OMX_ErrorInsufficientResources; + } + } + else + { + return OMX_ErrorBadParameter; + } + + return eRet; + +} + + +/* ====================================================================== +FUNCTION + omx_vdec::AllocateInputBuffer + +DESCRIPTION + Helper function for allocate buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::allocate_input_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct vdec_setbuffer_cmd setbuffers; + OMX_BUFFERHEADERTYPE *input = NULL; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + unsigned i = 0; + unsigned char *buf_addr = NULL; + int pmem_fd = -1; + + if(bytes != drv_ctx.ip_buf.buffer_size) + { + DEBUG_PRINT_LOW("\n Requested Size is wrong %d epected is %d", + bytes, drv_ctx.ip_buf.buffer_size); + return OMX_ErrorBadParameter; + } + + if(!m_inp_mem_ptr) + { + DEBUG_PRINT_HIGH("\n Allocate i/p buffer Header: Cnt(%d) Sz(%d)", + drv_ctx.ip_buf.actualcount, + drv_ctx.ip_buf.buffer_size); + + m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ + calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount); + + if (m_inp_mem_ptr == NULL) + { + return OMX_ErrorInsufficientResources; + } + + drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \ + calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount); + + if (drv_ctx.ptr_inputbuffer == NULL) + { + return OMX_ErrorInsufficientResources; + } +#ifdef USE_ION + drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \ + calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount); + + if (drv_ctx.ip_buf_ion_info == NULL) + { + return OMX_ErrorInsufficientResources; + } +#endif + + for (i=0; i < drv_ctx.ip_buf.actualcount; i++) + { + drv_ctx.ptr_inputbuffer [i].pmem_fd = -1; +#ifdef USE_ION + drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1; +#endif + } + } + + for(i=0; i< drv_ctx.ip_buf.actualcount; i++) + { + if(BITMASK_ABSENT(&m_inp_bm_count,i)) + { + DEBUG_PRINT_LOW("\n Free Input Buffer Index %d",i); + break; + } + } + + if(i < drv_ctx.ip_buf.actualcount) + { + struct v4l2_buffer buf; + struct v4l2_plane plane; + int rc; + DEBUG_PRINT_LOW("\n Allocate input Buffer"); +#ifdef USE_ION + drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory( + drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment, + &drv_ctx.ip_buf_ion_info[i].ion_alloc_data, + &drv_ctx.ip_buf_ion_info[i].fd_ion_data, 0); + if(drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) { + return OMX_ErrorInsufficientResources; + } + pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd; +#else + pmem_fd = open (MEM_DEVICE,O_RDWR); + + if (pmem_fd < 0) + { + DEBUG_PRINT_ERROR("\n open failed for pmem/adsp for input buffer"); + return OMX_ErrorInsufficientResources; + } + + if (pmem_fd == 0) + { + pmem_fd = open (MEM_DEVICE,O_RDWR); + + if (pmem_fd < 0) + { + DEBUG_PRINT_ERROR("\n open failed for pmem/adsp for input buffer"); + return OMX_ErrorInsufficientResources; + } + } + + if(!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size, + drv_ctx.ip_buf.alignment)) + { + DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed"); + close(pmem_fd); + return OMX_ErrorInsufficientResources; + } +#endif + if (!secure_mode) { + buf_addr = (unsigned char *)mmap(NULL, + drv_ctx.ip_buf.buffer_size, + PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0); + + if (buf_addr == MAP_FAILED) + { + close(pmem_fd); +#ifdef USE_ION + free_ion_memory(&drv_ctx.ip_buf_ion_info[i]); +#endif + DEBUG_PRINT_ERROR("\n Map Failed to allocate input buffer"); + return OMX_ErrorInsufficientResources; + } + } + *bufferHdr = (m_inp_mem_ptr + i); + if (secure_mode) + drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr; + else + drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr; + drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd; + drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size; + drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size; + drv_ctx.ptr_inputbuffer [i].offset = 0; + + + buf.index = i; + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + plane.bytesused = 0; + plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size; + plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr; + plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd; + plane.reserved[1] = 0; + plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset; + buf.m.planes = &plane; + buf.length = 1; + + DEBUG_PRINT_LOW("\n Set the Output Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_inputbuffer[i]); + + rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf); + + if (rc) { + DEBUG_PRINT_ERROR("Failed to prepare bufs\n"); + /*TODO: How to handle this case */ + return OMX_ErrorInsufficientResources; + } + + input = *bufferHdr; + BITMASK_SET(&m_inp_bm_count,i); + DEBUG_PRINT_LOW("\n Buffer address %p of pmem",*bufferHdr); + if (secure_mode) + input->pBuffer = (OMX_U8 *)drv_ctx.ptr_inputbuffer [i].pmem_fd; + else + input->pBuffer = (OMX_U8 *)buf_addr; + input->nSize = sizeof(OMX_BUFFERHEADERTYPE); + input->nVersion.nVersion = OMX_SPEC_VERSION; + input->nAllocLen = drv_ctx.ip_buf.buffer_size; + input->pAppPrivate = appData; + input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX; + input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i]; + + if (drv_ctx.disable_dmx) + { + eRet = allocate_desc_buffer(i); + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR:Input Buffer Index not found"); + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + + +/* ====================================================================== +FUNCTION + omx_vdec::AllocateOutputBuffer + +DESCRIPTION + Helper fn for AllocateBuffer in the output pin + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything went well. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::allocate_output_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header + unsigned i= 0; // Temporary counter + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct vdec_setbuffer_cmd setbuffers; +#ifdef USE_ION + int ion_device_fd =-1; + struct ion_allocation_data ion_alloc_data; + struct ion_fd_data fd_ion_data; +#endif + if(!m_out_mem_ptr) + { + DEBUG_PRINT_HIGH("\n Allocate o/p buffer Header: Cnt(%d) Sz(%d)", + drv_ctx.op_buf.actualcount, + drv_ctx.op_buf.buffer_size); + int nBufHdrSize = 0; + int nPlatformEntrySize = 0; + int nPlatformListSize = 0; + int nPMEMInfoSize = 0; + int pmem_fd = -1; + unsigned char *pmem_baseaddress = NULL; + + OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; + OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; + + DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n", + drv_ctx.op_buf.actualcount); + nBufHdrSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_BUFFERHEADERTYPE); + + nPMEMInfoSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); + nPlatformListSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); + nPlatformEntrySize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); + + DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",nBufHdrSize, + sizeof(OMX_BUFFERHEADERTYPE), + nPMEMInfoSize, + nPlatformListSize); + DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d \n",nPlatformEntrySize, + drv_ctx.op_buf.actualcount); +#ifdef USE_ION + ion_device_fd = alloc_map_ion_memory( + drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount, + drv_ctx.op_buf.alignment, + &ion_alloc_data, &fd_ion_data, 0); + if (ion_device_fd < 0) { + return OMX_ErrorInsufficientResources; + } + pmem_fd = fd_ion_data.fd; +#else + pmem_fd = open (MEM_DEVICE,O_RDWR); + + if (pmem_fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR:pmem fd for output buffer %d", + drv_ctx.op_buf.buffer_size); + return OMX_ErrorInsufficientResources; + } + + if(pmem_fd == 0) + { + pmem_fd = open (MEM_DEVICE,O_RDWR); + + if (pmem_fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR:pmem fd for output buffer %d", + drv_ctx.op_buf.buffer_size); + return OMX_ErrorInsufficientResources; + } + } + + if(!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size * + drv_ctx.op_buf.actualcount, + drv_ctx.op_buf.alignment)) + { + DEBUG_PRINT_ERROR("\n align_pmem_buffers() failed"); + close(pmem_fd); + return OMX_ErrorInsufficientResources; + } +#endif + if (!secure_mode) { + pmem_baseaddress = (unsigned char *)mmap(NULL, + (drv_ctx.op_buf.buffer_size * + drv_ctx.op_buf.actualcount), + PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0); + if (pmem_baseaddress == MAP_FAILED) + { + DEBUG_PRINT_ERROR("\n MMAP failed for Size %d", + drv_ctx.op_buf.buffer_size); + close(pmem_fd); +#ifdef USE_ION + free_ion_memory(&drv_ctx.op_buf_ion_info[i]); +#endif + return OMX_ErrorInsufficientResources; + } + } + m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); + // Alloc mem for platform specific info + char *pPtr=NULL; + pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + + nPMEMInfoSize,1); + drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\ + calloc (sizeof(struct vdec_bufferpayload), + drv_ctx.op_buf.actualcount); + drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ + calloc (sizeof (struct vdec_output_frameinfo), + drv_ctx.op_buf.actualcount); +#ifdef USE_ION + drv_ctx.op_buf_ion_info = (struct vdec_ion *)\ + calloc (sizeof(struct vdec_ion), + drv_ctx.op_buf.actualcount); +#endif + + if(m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer + && drv_ctx.ptr_respbuffer) + { + drv_ctx.ptr_outputbuffer[0].mmaped_size = + (drv_ctx.op_buf.buffer_size * + drv_ctx.op_buf.actualcount); + bufHdr = m_out_mem_ptr; + m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); + m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) + (((char *) m_platform_list) + nPlatformListSize); + m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + (((char *) m_platform_entry) + nPlatformEntrySize); + pPlatformList = m_platform_list; + pPlatformEntry = m_platform_entry; + pPMEMInfo = m_pmem_info; + + DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr); + + // Settting the entire storage nicely + DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p\n",bufHdr, m_out_mem_ptr,pPlatformEntry); + DEBUG_PRINT_LOW(" Pmem Info = %p \n",pPMEMInfo); + for(i=0; i < drv_ctx.op_buf.actualcount ; i++) + { + bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + // Set the values when we determine the right HxW param + bufHdr->nAllocLen = bytes; + bufHdr->nFilledLen = 0; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + // Platform specific PMEM Information + // Initialize the Platform Entry + //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d\n",i); + pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; + pPlatformEntry->entry = pPMEMInfo; + // Initialize the Platform List + pPlatformList->nEntries = 1; + pPlatformList->entryList = pPlatformEntry; + // Keep pBuffer NULL till vdec is opened + bufHdr->pBuffer = NULL; + bufHdr->nOffset = 0; + + pPMEMInfo->offset = drv_ctx.op_buf.buffer_size*i; + pPMEMInfo->pmem_fd = 0; + bufHdr->pPlatformPrivate = pPlatformList; + + drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd; +#ifdef USE_ION + drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd; + drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data; + drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data; +#endif + + /*Create a mapping between buffers*/ + bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; + drv_ctx.ptr_respbuffer[i].client_data = (void *)\ + &drv_ctx.ptr_outputbuffer[i]; + drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i; + drv_ctx.ptr_outputbuffer[i].bufferaddr = + pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i); + + DEBUG_PRINT_LOW("\n pmem_fd = %d offset = %d address = %p", + pmem_fd, drv_ctx.ptr_outputbuffer[i].offset, + drv_ctx.ptr_outputbuffer[i].bufferaddr); + // Move the buffer and buffer header pointers + bufHdr++; + pPMEMInfo++; + pPlatformEntry++; + pPlatformList++; + } + } + else + { + DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%x][0x%x]\n",\ + m_out_mem_ptr, pPtr); + if(m_out_mem_ptr) + { + free(m_out_mem_ptr); + m_out_mem_ptr = NULL; + } + if(pPtr) + { + free(pPtr); + pPtr = NULL; + } + if(drv_ctx.ptr_outputbuffer) + { + free(drv_ctx.ptr_outputbuffer); + drv_ctx.ptr_outputbuffer = NULL; + } + if(drv_ctx.ptr_respbuffer) + { + free(drv_ctx.ptr_respbuffer); + drv_ctx.ptr_respbuffer = NULL; + } +#ifdef USE_ION + if (drv_ctx.op_buf_ion_info) { + DEBUG_PRINT_LOW("\n Free o/p ion context"); + free(drv_ctx.op_buf_ion_info); + drv_ctx.op_buf_ion_info = NULL; + } +#endif + eRet = OMX_ErrorInsufficientResources; + } + } + + for(i=0; i< drv_ctx.op_buf.actualcount; i++) + { + if(BITMASK_ABSENT(&m_out_bm_count,i)) + { + DEBUG_PRINT_LOW("\n Found a Free Output Buffer %d",i); + break; + } + } + + if (eRet == OMX_ErrorNone) + { + if(i < drv_ctx.op_buf.actualcount) + { + struct v4l2_buffer buf; + struct v4l2_plane plane; + int rc; + m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset; + + drv_ctx.ptr_outputbuffer[i].buffer_len = + drv_ctx.op_buf.buffer_size; + + *bufferHdr = (m_out_mem_ptr + i ); + if (secure_mode) { + drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr; + } + drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size; + + buf.index = i; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + plane.length = drv_ctx.op_buf.buffer_size; + plane.m.userptr = (unsigned long)(drv_ctx.ptr_outputbuffer[i].bufferaddr-drv_ctx.ptr_outputbuffer[i].offset); +#ifdef USE_ION + plane.reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd; +#endif + plane.reserved[1] = drv_ctx.ptr_outputbuffer[i].offset; + plane.data_offset = 0; + buf.m.planes = &plane; + buf.length = 1; + + DEBUG_PRINT_LOW("\n Set the Output Buffer Idx: %d Addr: %x", i, drv_ctx.ptr_outputbuffer[i]); + rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf); + if (rc) { + /*TODO: How to handle this case */ + return OMX_ErrorInsufficientResources; + } + + if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) { + enum v4l2_buf_type buf_type; + buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type); + if (rc) { + return OMX_ErrorInsufficientResources; + } else { + streaming[CAPTURE_PORT] = true; + DEBUG_PRINT_LOW("\n STREAMON Successful \n "); + } + } + + (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr; + (*bufferHdr)->pAppPrivate = appData; + BITMASK_SET(&m_out_bm_count,i); + } + else + { + DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient \n"); + eRet = OMX_ErrorInsufficientResources; + } + } + + return eRet; +} + + +// AllocateBuffer -- API Call +/* ====================================================================== +FUNCTION + omx_vdec::AllocateBuffer + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + unsigned i = 0; + OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type + + DEBUG_PRINT_LOW("\n Allocate buffer on port %d \n", (int)port); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Allocate Buf in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if(port == OMX_CORE_INPUT_PORT_INDEX) + { + if (arbitrary_bytes) + { + eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes); + } + else + { + eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); + } + } + else if(port == OMX_CORE_OUTPUT_PORT_INDEX) + { + eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); + } + else + { + DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port); + eRet = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done"); + if(eRet == OMX_ErrorNone) + { + if(allocate_done()){ + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); + post_event(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if(port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if(port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + } + DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d\n",eRet); + return eRet; +} + +// Free Buffer - API call +/* ====================================================================== +FUNCTION + omx_vdec::FreeBuffer + +DESCRIPTION + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned int nPortIndex; + DEBUG_PRINT_LOW("In for decoder free_buffer \n"); + + if(m_state == OMX_StateIdle && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + DEBUG_PRINT_LOW(" free buffer while Component in Loading pending\n"); + } + else if((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)|| + (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) + { + DEBUG_PRINT_LOW("Free Buffer while port %d disabled\n", port); + } + else if(m_state == OMX_StateExecuting || m_state == OMX_StatePause) + { + DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled\n"); + post_event(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + + return OMX_ErrorIncorrectStateOperation; + } + else if (m_state != OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers\n"); + post_event(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + } + + if(port == OMX_CORE_INPUT_PORT_INDEX) + { + /*Check if arbitrary bytes*/ + if(!arbitrary_bytes && !input_use_buffer) + nPortIndex = buffer - m_inp_mem_ptr; + else + nPortIndex = buffer - m_inp_heap_ptr; + + DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d \n", nPortIndex); + if(nPortIndex < drv_ctx.ip_buf.actualcount) + { + // Clear the bit associated with it. + BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); + BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex); + if (input_use_buffer == true) + { + + DEBUG_PRINT_LOW("\n Free pmem Buffer index %d",nPortIndex); + if(m_phdr_pmem_ptr) + free_input_buffer(m_phdr_pmem_ptr[nPortIndex]); + } + else + { + if (arbitrary_bytes) + { + if(m_phdr_pmem_ptr) + free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]); + else + free_input_buffer(nPortIndex,NULL); + } + else + free_input_buffer(buffer); + } + m_inp_bPopulated = OMX_FALSE; + /*Free the Buffer Header*/ + if (release_input_done()) + { + DEBUG_PRINT_HIGH("\n ALL input buffers are freed/released"); + free_input_buffer_header(); + } + } + else + { + DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + + if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) + && release_input_done()) + { + DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); + post_event(OMX_CommandPortDisable, + OMX_CORE_INPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + else if(port == OMX_CORE_OUTPUT_PORT_INDEX) + { + // check if the buffer is valid + nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr; + if(nPortIndex < drv_ctx.op_buf.actualcount) + { + DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d \n", nPortIndex); + // Clear the bit associated with it. + BITMASK_CLEAR(&m_out_bm_count,nPortIndex); + m_out_bPopulated = OMX_FALSE; + free_output_buffer (buffer); + + if (release_output_done()) + { + free_output_buffer_header(); + } + } + else + { + DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) + && release_output_done()) + { + DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it\n"); + + DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); +#ifdef _ANDROID_ICS_ + if (m_enable_android_native_buffers) + { + DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers"); + memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); + } +#endif + + post_event(OMX_CommandPortDisable, + OMX_CORE_OUTPUT_PORT_INDEX, + OMX_COMPONENT_GENERATE_EVENT); + } + } + else + { + eRet = OMX_ErrorBadPortIndex; + } + if((eRet == OMX_ErrorNone) && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + if(release_done()) + { + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); + post_event(OMX_CommandStateSet, OMX_StateLoaded, + OMX_COMPONENT_GENERATE_EVENT); + } + } + return eRet; +} + + +/* ====================================================================== +FUNCTION + omx_vdec::EmptyThisBuffer + +DESCRIPTION + This routine is used to push the encoded video frames to + the video decoder. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything went successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE ret1 = OMX_ErrorNone; + unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount; + + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("Empty this buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if (buffer == NULL) + { + DEBUG_PRINT_ERROR("\nERROR:ETB Buffer is NULL"); + return OMX_ErrorBadParameter; + } + + if (!m_inp_bEnabled) + { + DEBUG_PRINT_ERROR("\nERROR:ETB incorrect state operation, input port is disabled."); + return OMX_ErrorIncorrectStateOperation; + } + + if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) + { + DEBUG_PRINT_ERROR("\nERROR:ETB invalid port in header %d", buffer->nInputPortIndex); + return OMX_ErrorBadPortIndex; + } + +#ifdef _ANDROID_ + if(iDivXDrmDecrypt) + { + OMX_ERRORTYPE drmErr = iDivXDrmDecrypt->Decrypt(buffer); + if(drmErr != OMX_ErrorNone) { + // this error can be ignored + DEBUG_PRINT_LOW("\nERROR:iDivXDrmDecrypt->Decrypt %d", drmErr); + } + } +#endif //_ANDROID_ + if (perf_flag) + { + if (!latency) + { + dec_time.stop(); + latency = dec_time.processing_time_us(); + dec_time.start(); + } + } + + if (arbitrary_bytes) + { + nBufferIndex = buffer - m_inp_heap_ptr; + } + else + { + if (input_use_buffer == true) + { + nBufferIndex = buffer - m_inp_heap_ptr; + m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen; + m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp; + m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags; + buffer = &m_inp_mem_ptr[nBufferIndex]; + DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %d", + &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, buffer->nFilledLen); + } + else{ + nBufferIndex = buffer - m_inp_mem_ptr; + } + } + + if (nBufferIndex > drv_ctx.ip_buf.actualcount ) + { + DEBUG_PRINT_ERROR("\nERROR:ETB nBufferIndex is invalid"); + return OMX_ErrorBadParameter; + } + + DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%lu)", + buffer, buffer->pBuffer, buffer->nTimeStamp, buffer->nFilledLen); + if (arbitrary_bytes) + { + post_event ((unsigned)hComp,(unsigned)buffer, + OMX_COMPONENT_GENERATE_ETB_ARBITRARY); + } + else + { + if (!(client_extradata & OMX_TIMEINFO_EXTRADATA)) + set_frame_rate(buffer->nTimeStamp); + post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB); + } + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::empty_this_buffer_proxy + +DESCRIPTION + This routine is used to push the encoded video frames to + the video decoder. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything went successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + int push_cnt = 0,i=0; + unsigned nPortIndex = 0; + OMX_ERRORTYPE ret = OMX_ErrorNone; + struct vdec_input_frameinfo frameinfo; + struct vdec_bufferpayload *temp_buffer; + struct vdec_ioctl_msg ioctl_msg; + struct vdec_seqheader seq_header; + bool port_setting_changed = true; + bool not_coded_vop = false; + + /*Should we generate a Aync error event*/ + if (buffer == NULL || buffer->pInputPortPrivate == NULL) + { + DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy is invalid"); + return OMX_ErrorBadParameter; + } + + nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); + + if (nPortIndex > drv_ctx.ip_buf.actualcount) + { + DEBUG_PRINT_ERROR("\nERROR:empty_this_buffer_proxy invalid nPortIndex[%u]", + nPortIndex); + return OMX_ErrorBadParameter; + } + + pending_input_buffers++; + + /* return zero length and not an EOS buffer */ + if (!arbitrary_bytes && (buffer->nFilledLen == 0) && + ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) + { + DEBUG_PRINT_HIGH("\n return zero legth buffer"); + post_event ((unsigned int)buffer,VDEC_S_SUCCESS, + OMX_COMPONENT_GENERATE_EBD); + return OMX_ErrorNone; + } + + + if(codec_type_parse == CODEC_TYPE_MPEG4 || codec_type_parse == CODEC_TYPE_DIVX){ + mp4StreamType psBits; + psBits.data = (unsigned char *)(buffer->pBuffer + buffer->nOffset); + psBits.numBytes = buffer->nFilledLen; + mp4_headerparser.parseHeader(&psBits); + not_coded_vop = mp4_headerparser.is_notcodec_vop( + (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen); + if(not_coded_vop) { + DEBUG_PRINT_HIGH("\n Found Not coded vop len %d frame number %d", + buffer->nFilledLen,frame_count); + if(buffer->nFlags & OMX_BUFFERFLAG_EOS){ + DEBUG_PRINT_HIGH("\n Eos and Not coded Vop set len to zero"); + not_coded_vop = false; + buffer->nFilledLen = 0; + } + } + } + + if(input_flush_progress == true + + || not_coded_vop + + ) + { + DEBUG_PRINT_LOW("\n Flush in progress return buffer "); + post_event ((unsigned int)buffer,VDEC_S_SUCCESS, + OMX_COMPONENT_GENERATE_EBD); + return OMX_ErrorNone; + } + + temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate; + + if ((temp_buffer - drv_ctx.ptr_inputbuffer) > drv_ctx.ip_buf.actualcount) + { + return OMX_ErrorBadParameter; + } + + DEBUG_PRINT_LOW("\n ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); + /*for use buffer we need to memcpy the data*/ + temp_buffer->buffer_len = buffer->nFilledLen; + + if (input_use_buffer) + { + if (buffer->nFilledLen <= temp_buffer->buffer_len) + { + if(arbitrary_bytes) + { + memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen); + } + else + { + memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset), + buffer->nFilledLen); + } + } + else + { + return OMX_ErrorBadParameter; + } + + } + + frameinfo.bufferaddr = temp_buffer->bufferaddr; + frameinfo.client_data = (void *) buffer; + frameinfo.datalen = temp_buffer->buffer_len; + frameinfo.flags = 0; + frameinfo.offset = buffer->nOffset; + frameinfo.pmem_fd = temp_buffer->pmem_fd; + frameinfo.pmem_offset = temp_buffer->offset; + frameinfo.timestamp = buffer->nTimeStamp; + if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) + { + DEBUG_PRINT_LOW("ETB: dmx enabled"); + if (m_demux_entries == 0) + { + extract_demux_addr_offsets(buffer); + } + + DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%d",m_demux_entries); + handle_demux_data(buffer); + frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr; + frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size; + } + else + { + frameinfo.desc_addr = NULL; + frameinfo.desc_size = 0; + } + if(!arbitrary_bytes) + { + frameinfo.flags |= buffer->nFlags; + } + +#ifdef _ANDROID_ + if (m_debug_timestamp) + { + if(arbitrary_bytes) + { + DEBUG_PRINT_LOW("\n Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); + m_timestamp_list.insert_ts(buffer->nTimeStamp); + } + else if(!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) + { + DEBUG_PRINT_LOW("\n Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp); + m_timestamp_list.insert_ts(buffer->nTimeStamp); + } + } +#endif + +#ifdef INPUT_BUFFER_LOG + if (inputBufferFile1) + { + fwrite((const char *)temp_buffer->bufferaddr, + temp_buffer->buffer_len,1,inputBufferFile1); + } +#endif + + if(buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) + { + frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; + buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; + } + + if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) + { + DEBUG_PRINT_HIGH("\n Rxd i/p EOS, Notify Driver that EOS has been reached"); + frameinfo.flags |= VDEC_BUFFERFLAG_EOS; + h264_scratch.nFilledLen = 0; + nal_count = 0; + look_ahead_nal = false; + frame_count = 0; + if (m_frame_parser.mutils) + m_frame_parser.mutils->initialize_frame_checking_environment(); + m_frame_parser.flush(); + h264_last_au_ts = LLONG_MAX; + h264_last_au_flags = 0; + memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); + m_demux_entries = 0; + } + struct v4l2_buffer buf = {0}; + struct v4l2_plane plane; + int rc; + unsigned long print_count; + if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) + { buf.flags = V4L2_BUF_FLAG_EOS; + DEBUG_PRINT_HIGH("\n INPUT EOS reached \n") ; + } + OMX_ERRORTYPE eRet = OMX_ErrorNone; + buf.index = nPortIndex; + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + plane.bytesused = temp_buffer->buffer_len; + plane.length = drv_ctx.ip_buf.buffer_size; + plane.m.userptr = (unsigned long)(temp_buffer->bufferaddr-temp_buffer->offset); + plane.reserved[0] = temp_buffer->pmem_fd; + plane.reserved[1] = temp_buffer->offset; + plane.data_offset = 0; + buf.m.planes = &plane; + buf.length = 1; + rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); + if(!streaming[OUTPUT_PORT]) + { + enum v4l2_buf_type buf_type; + int ret,r; + + struct v4l2_control control; + control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER; + control.value = 1; + ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control); + if(ret) + printf("\n Continue data Xfer failed \n"); + buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n"); + ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type); + if(!ret) { + DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful \n"); + streaming[OUTPUT_PORT] = true; + ret = pthread_create(&async_thread_id,0,async_message_thread,this); + if(ret < 0) + DEBUG_PRINT_ERROR("\n Failed to create async_message_thread \n"); + } else{ + /*TODO: How to handle this case */ + DEBUG_PRINT_ERROR(" \n Failed to call streamon on OUTPUT \n"); + } +} + DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%d)", + frameinfo.bufferaddr, frameinfo.timestamp, frameinfo.datalen); + time_stamp_dts.insert_timestamp(buffer); + + return ret; +} + +/* ====================================================================== +FUNCTION + omx_vdec::FillThisBuffer + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("FTB in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if (!m_out_bEnabled) + { + DEBUG_PRINT_ERROR("\nERROR:FTB incorrect state operation, output port is disabled."); + return OMX_ErrorIncorrectStateOperation; + } + + if (buffer == NULL || ((buffer - m_out_mem_ptr) >= drv_ctx.op_buf.actualcount)) + { + return OMX_ErrorBadParameter; + } + + if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) + { + DEBUG_PRINT_ERROR("\nERROR:FTB invalid port in header %d", buffer->nOutputPortIndex); + return OMX_ErrorBadPortIndex; + } + + DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); + post_event((unsigned) hComp, (unsigned)buffer,OMX_COMPONENT_GENERATE_FTB); + return OMX_ErrorNone; +} +/* ====================================================================== +FUNCTION + omx_vdec::fill_this_buffer_proxy + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd) +{ + OMX_ERRORTYPE nRet = OMX_ErrorNone; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + OMX_BUFFERHEADERTYPE *buffer = bufferAdd; + unsigned nPortIndex = 0; + struct vdec_fillbuffer_cmd fillbuffer; + struct vdec_bufferpayload *ptr_outputbuffer = NULL; + struct vdec_output_frameinfo *ptr_respbuffer = NULL; + + nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_out_mem_ptr); + + if (bufferAdd == NULL || ((buffer - m_out_mem_ptr) > + drv_ctx.op_buf.actualcount) ) + return OMX_ErrorBadParameter; + + DEBUG_PRINT_LOW("\n FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p", + bufferAdd, bufferAdd->pBuffer); + /*Return back the output buffer to client*/ + if(m_out_bEnabled != OMX_TRUE || output_flush_progress == true) + { + DEBUG_PRINT_LOW("\n Output Buffers return flush/disable condition"); + buffer->nFilledLen = 0; + m_cb.FillBufferDone (hComp,m_app_data,buffer); + return OMX_ErrorNone; + } + pending_output_buffers++; + ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate; + if (ptr_respbuffer) + { + ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data; + } + + if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) + { + DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL"); + buffer->nFilledLen = 0; + m_cb.FillBufferDone (hComp,m_app_data,buffer); + pending_output_buffers--; + return OMX_ErrorBadParameter; + } + + // memcpy (&fillbuffer.buffer,ptr_outputbuffer,\ + sizeof(struct vdec_bufferpayload)); + // fillbuffer.client_data = bufferAdd; + +#ifdef _ANDROID_ICS_ + if (m_enable_android_native_buffers) + { + // Acquire a write lock on this buffer. + if (GENLOCK_NO_ERROR != genlock_lock_buffer(native_buffer[buffer - m_out_mem_ptr].nativehandle, + GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) { + DEBUG_PRINT_ERROR("Failed to acquire genlock"); + buffer->nFilledLen = 0; + m_cb.FillBufferDone (hComp,m_app_data,buffer); + pending_output_buffers--; + return OMX_ErrorInsufficientResources; + } else { + native_buffer[buffer - m_out_mem_ptr].inuse = true; + } + } +#endif + int rc = 0; + struct v4l2_buffer buf={0}; + struct v4l2_plane plane; + + buf.index = nPortIndex; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + plane.bytesused = buffer->nFilledLen; + plane.length = drv_ctx.op_buf.buffer_size; + plane.m.userptr = (unsigned long)(drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr-drv_ctx.ptr_outputbuffer[nPortIndex].offset); + plane.reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd; + plane.reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset; + plane.data_offset = 0; + buf.m.planes = &plane; + buf.length = 1; + + rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf); + if (rc) { + /*TODO: How to handle this case */ + DEBUG_PRINT_ERROR("Failed to qbuf to driver"); + } +//#ifdef _ANDROID_ICS_ + // if (m_enable_android_native_buffers) + // { + // Unlock the buffer + // if (GENLOCK_NO_ERROR != genlock_unlock_buffer(native_buffer[buffer - m_out_mem_ptr].nativehandle)) { + // DEBUG_PRINT_ERROR("Releasing genlock failed"); + // return OMX_ErrorInsufficientResources; + /// } else { + // native_buffer[buffer - m_out_mem_ptr].inuse = false; + // } + // } +//#endif + //m_cb.FillBufferDone (hComp,m_app_data,buffer); + // pending_output_buffers--; + // return OMX_ErrorBadParameter; + //} + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::SetCallbacks + +DESCRIPTION + Set the callbacks. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_CALLBACKTYPE* callbacks, + OMX_IN OMX_PTR appData) +{ + + m_cb = *callbacks; + DEBUG_PRINT_LOW("\n Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\ + m_cb.EventHandler,m_cb.FillBufferDone); + m_app_data = appData; + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_vdec::ComponentDeInit + +DESCRIPTION + Destroys the component and release memory allocated to the heap. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp) +{ +#ifdef _ANDROID_ + if(iDivXDrmDecrypt) + { + delete iDivXDrmDecrypt; + iDivXDrmDecrypt=NULL; + } +#endif //_ANDROID_ + + int i = 0; + if (OMX_StateLoaded != m_state) + { + DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d\n",\ + m_state); + DEBUG_PRINT_ERROR("\nPlayback Ended - FAILED"); + } + else + { + DEBUG_PRINT_HIGH("\n Playback Ended - PASSED"); + } + + /*Check if the output buffers have to be cleaned up*/ + if(m_out_mem_ptr) + { + DEBUG_PRINT_LOW("Freeing the Output Memory\n"); + for (i=0; i < drv_ctx.op_buf.actualcount; i++ ) + { + free_output_buffer (&m_out_mem_ptr[i]); +#ifdef _ANDROID_ICS_ + if (m_enable_android_native_buffers) + { + if (native_buffer[i].inuse) + { + if (GENLOCK_NO_ERROR != genlock_unlock_buffer(native_buffer[i].nativehandle)) { + DEBUG_PRINT_ERROR("Unlocking genlock failed"); + } + native_buffer[i].inuse = false; + } + } +#endif + } +#ifdef _ANDROID_ICS_ + memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS)); +#endif + } + + /*Check if the input buffers have to be cleaned up*/ + if(m_inp_mem_ptr || m_inp_heap_ptr) + { + DEBUG_PRINT_LOW("Freeing the Input Memory\n"); + for (i=0; i. + +PARAMETERS + . + +RETURN VALUE + Not Implemented error. + +========================================================================== */ +OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN void* eglImage) +{ + OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list; + OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry; + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info; + +#ifdef USE_EGL_IMAGE_GPU + PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc; + EGLint fd = -1, offset = 0,pmemPtr = 0; +#else + int fd = -1, offset = 0; +#endif + DEBUG_PRINT_HIGH("\nuse EGL image support for decoder"); + if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) { + DEBUG_PRINT_ERROR("\n "); + } +#ifdef USE_EGL_IMAGE_GPU + if(m_display_id == NULL) { + DEBUG_PRINT_ERROR("Display ID is not set by IL client \n"); + return OMX_ErrorInsufficientResources; + } + egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC) + eglGetProcAddress("eglQueryImageKHR"); + egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE_QCOM,&fd); + egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET_QCOM,&offset); + egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR,&pmemPtr); +#else //with OMX test app + struct temp_egl { + int pmem_fd; + int offset; + }; + struct temp_egl *temp_egl_id = NULL; + void * pmemPtr = (void *) eglImage; + temp_egl_id = (struct temp_egl *)eglImage; + if (temp_egl_id != NULL) + { + fd = temp_egl_id->pmem_fd; + offset = temp_egl_id->offset; + } +#endif + if (fd < 0) { + DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d \n",fd); + return OMX_ErrorInsufficientResources; + } + pmem_info.pmem_fd = (OMX_U32) fd; + pmem_info.offset = (OMX_U32) offset; + pmem_entry.entry = (void *) &pmem_info; + pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; + pmem_list.entryList = &pmem_entry; + pmem_list.nEntries = 1; + ouput_egl_buffers = true; + if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port, + (void *)&pmem_list, drv_ctx.op_buf.buffer_size, + (OMX_U8 *)pmemPtr)) { + DEBUG_PRINT_ERROR("use buffer call failed for egl image\n"); + return OMX_ErrorInsufficientResources; + } + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_vdec::ComponentRoleEnum + +DESCRIPTION + OMX Component Role Enum method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_U8* role, + OMX_IN OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + eRet = OMX_ErrorNoMore; + } + } + if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_LOW("\n No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + + else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) || + (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE)) + ) + + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_LOW("\n No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_LOW("\n No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + else if( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) || + (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE)) + ) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_LOW("\n No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_LOW("\n No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR:Querying Role on Unknown Component\n"); + eRet = OMX_ErrorInvalidComponentName; + } + return eRet; +} + + + + +/* ====================================================================== +FUNCTION + omx_vdec::AllocateDone + +DESCRIPTION + Checks if entire buffer pool is allocated by IL Client or not. + Need this to move to IDLE state. + +PARAMETERS + None. + +RETURN VALUE + true/false. + +========================================================================== */ +bool omx_vdec::allocate_done(void) +{ + bool bRet = false; + bool bRet_In = false; + bool bRet_Out = false; + + bRet_In = allocate_input_done(); + bRet_Out = allocate_output_done(); + + if(bRet_In && bRet_Out) + { + bRet = true; + } + + return bRet; +} +/* ====================================================================== +FUNCTION + omx_vdec::AllocateInputDone + +DESCRIPTION + Checks if I/P buffer pool is allocated by IL Client or not. + +PARAMETERS + None. + +RETURN VALUE + true/false. + +========================================================================== */ +bool omx_vdec::allocate_input_done(void) +{ + bool bRet = false; + unsigned i=0; + + if (m_inp_mem_ptr == NULL) + { + return bRet; + } + if(m_inp_mem_ptr ) + { + for(;i= drv_ctx.op_buf.actualcount) + { + DEBUG_PRINT_ERROR("\n [FBD] ERROR in ptr(%p)", buffer); + return OMX_ErrorBadParameter; + } + else if (output_flush_progress) + { + DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer); + buffer->nFilledLen = 0; + buffer->nTimeStamp = 0; + buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; + buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ; + buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT; + } + + DEBUG_PRINT_LOW("\n fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p", + buffer, buffer->pBuffer); + pending_output_buffers --; + + if (buffer->nFlags & OMX_BUFFERFLAG_EOS) + { + DEBUG_PRINT_HIGH("\n Output EOS has been reached"); + if (!output_flush_progress) + post_event(NULL,NULL,OMX_COMPONENT_GENERATE_EOS_DONE); + + if (psource_frame) + { + m_cb.EmptyBufferDone(&m_cmp, m_app_data, psource_frame); + psource_frame = NULL; + } + if (pdest_frame) + { + pdest_frame->nFilledLen = 0; + m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL); + pdest_frame = NULL; + } + } + + DEBUG_PRINT_LOW("\n In fill Buffer done call address %p ",buffer); +#ifdef OUTPUT_BUFFER_LOG + if (outputBufferFile1) + { + fwrite (buffer->pBuffer,1,buffer->nFilledLen, + outputBufferFile1); + } +#endif + + /* For use buffer we need to copy the data */ + if (!output_flush_progress) + { + time_stamp_dts.get_next_timestamp(buffer, + (drv_ctx.interlace != VDEC_InterlaceFrameProgressive) + ?true:false); + } + if (m_cb.FillBufferDone) + { + if (buffer->nFilledLen > 0) + { + /*if (client_extradata) + handle_extradata(buffer);*/ + if (client_extradata & OMX_TIMEINFO_EXTRADATA) + // Keep min timestamp interval to handle corrupted bit stream scenario + set_frame_rate(buffer->nTimeStamp); + else if (arbitrary_bytes) + adjust_timestamp(buffer->nTimeStamp); + if (perf_flag) + { + if (!proc_frms) + { + dec_time.stop(); + latency = dec_time.processing_time_us() - latency; + DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3); + dec_time.start(); + fps_metrics.start(); + } + proc_frms++; + if (buffer->nFlags & OMX_BUFFERFLAG_EOS) + { + OMX_U64 proc_time = 0; + fps_metrics.stop(); + proc_time = fps_metrics.processing_time_us(); + DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%lu) proc_time(%.2f)S fps(%.2f)", + proc_frms, (float)proc_time / 1e6, + (float)(1e6 * proc_frms) / proc_time); + proc_frms = 0; + } + } + +#ifdef OUTPUT_EXTRADATA_LOG + if (outputExtradataFile) + { + + OMX_OTHER_EXTRADATATYPE *p_extra = NULL; + p_extra = (OMX_OTHER_EXTRADATATYPE *) + ((unsigned)(buffer->pBuffer + buffer->nOffset + + buffer->nFilledLen + 3)&(~3)); + while(p_extra && + (OMX_U8*)p_extra < (buffer->pBuffer + buffer->nAllocLen) ) + { + DEBUG_PRINT_LOW("\nWRITING extradata, size=%d,type=%d",p_extra->nSize, p_extra->eType); + fwrite (p_extra,1,p_extra->nSize,outputExtradataFile); + if (p_extra->eType == OMX_ExtraDataNone) + { + break; + } + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + } + } +#endif + } + if (buffer->nFlags & OMX_BUFFERFLAG_EOS){ + prev_ts = LLONG_MAX; + rst_prev_ts = true; + } + + pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) + buffer->pPlatformPrivate)->entryList->entry; + DEBUG_PRINT_LOW("\n Before FBD callback Accessed Pmeminfo %d",pPMEMInfo->pmem_fd); +#ifdef _ANDROID_ICS_ + if (m_enable_android_native_buffers) + { + if (native_buffer[buffer - m_out_mem_ptr].inuse) { + if (GENLOCK_NO_ERROR != genlock_unlock_buffer(native_buffer[buffer - m_out_mem_ptr].nativehandle)) { + DEBUG_PRINT_ERROR("Unlocking genlock failed"); + return OMX_ErrorInsufficientResources; + } + else { + native_buffer[buffer - m_out_mem_ptr].inuse = false; + } + } + } +#endif + m_cb.FillBufferDone (hComp,m_app_data,buffer); + DEBUG_PRINT_LOW("\n After Fill Buffer Done callback %d",pPMEMInfo->pmem_fd); + } + else + { + return OMX_ErrorBadParameter; + } + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + + if (buffer == NULL || ((buffer - m_inp_mem_ptr) > drv_ctx.ip_buf.actualcount)) + { + DEBUG_PRINT_ERROR("\n empty_buffer_done: ERROR bufhdr = %p", buffer); + return OMX_ErrorBadParameter; + } + + DEBUG_PRINT_LOW("\n empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p", + buffer, buffer->pBuffer); + pending_input_buffers--; + + if (arbitrary_bytes) + { + if (pdest_frame == NULL && input_flush_progress == false) + { + DEBUG_PRINT_LOW("\n Push input from buffer done address of Buffer %p",buffer); + pdest_frame = buffer; + buffer->nFilledLen = 0; + buffer->nTimeStamp = LLONG_MAX; + push_input_buffer (hComp); + } + else + { + DEBUG_PRINT_LOW("\n Push buffer into freeq address of Buffer %p",buffer); + buffer->nFilledLen = 0; + if (!m_input_free_q.insert_entry((unsigned)buffer,NULL,NULL)) + { + DEBUG_PRINT_ERROR("\nERROR:i/p free Queue is FULL Error"); + } + } + } + else if(m_cb.EmptyBufferDone) + { + buffer->nFilledLen = 0; + if (input_use_buffer == true){ + buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr]; + } + m_cb.EmptyBufferDone(hComp ,m_app_data, buffer); + } + return OMX_ErrorNone; +} + + +int omx_vdec::async_message_process (void *context, void* message) +{ + omx_vdec* omx = NULL; + struct vdec_msginfo *vdec_msg = NULL; + OMX_BUFFERHEADERTYPE* omxhdr = NULL; + struct v4l2_buffer *v4l2_buf_ptr=NULL; + struct vdec_output_frameinfo *output_respbuf = NULL; + int rc=1; + if (context == NULL || message == NULL) + { + DEBUG_PRINT_ERROR("\n FATAL ERROR in omx_vdec::async_message_process NULL Check"); + return -1; + } + vdec_msg = (struct vdec_msginfo *)message; + + omx = reinterpret_cast(context); + +#ifdef _ANDROID_ + if (omx->m_debug_timestamp) + { + if ( (vdec_msg->msgcode == VDEC_MSG_RESP_OUTPUT_BUFFER_DONE) && + !(omx->output_flush_progress) ) + { + OMX_TICKS expected_ts = 0; + omx->m_timestamp_list.pop_min_ts(expected_ts); + DEBUG_PRINT_LOW("\n Current timestamp (%lld),Popped TIMESTAMP (%lld) from list", + vdec_msg->msgdata.output_frame.time_stamp, expected_ts); + + if (vdec_msg->msgdata.output_frame.time_stamp != expected_ts) + { + DEBUG_PRINT_ERROR("\n ERROR in omx_vdec::async_message_process timestamp Check"); + } + } + } +#endif + + switch (vdec_msg->msgcode) + { + + case VDEC_MSG_EVT_HW_ERROR: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_HARDWARE_ERROR); + break; + + case VDEC_MSG_RESP_START_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_START_DONE); + break; + + case VDEC_MSG_RESP_STOP_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_STOP_DONE); + break; + + case VDEC_MSG_RESP_RESUME_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_RESUME_DONE); + break; + + case VDEC_MSG_RESP_PAUSE_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_PAUSE_DONE); + break; + + case VDEC_MSG_RESP_FLUSH_INPUT_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH); + break; + case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE: + omx->post_event (NULL,vdec_msg->status_code,\ + OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH); + break; + case VDEC_MSG_RESP_INPUT_FLUSHED: + case VDEC_MSG_RESP_INPUT_BUFFER_DONE: + + // omxhdr = (OMX_BUFFERHEADERTYPE* ) \ + // vdec_msg->msgdata.input_frame_clientdata; + + v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata; + omxhdr=omx->m_inp_mem_ptr+v4l2_buf_ptr->index; + if (omxhdr == NULL || + ((omxhdr - omx->m_inp_mem_ptr) > omx->drv_ctx.ip_buf.actualcount) ) + { + omxhdr = NULL; + vdec_msg->status_code = VDEC_S_EFATAL; + } + + omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code, + OMX_COMPONENT_GENERATE_EBD); + break; + case VDEC_MSG_EVT_INFO_FIELD_DROPPED: + int64_t *timestamp; + timestamp = (int64_t *) malloc(sizeof(int64_t)); + if (timestamp) { + *timestamp = vdec_msg->msgdata.output_frame.time_stamp; + omx->post_event ((unsigned int)timestamp, vdec_msg->status_code, + OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED); + DEBUG_PRINT_HIGH("\nField dropped time stamp is %lld", + vdec_msg->msgdata.output_frame.time_stamp); + } + break; + case VDEC_MSG_RESP_OUTPUT_FLUSHED: + case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: + + v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data; + omxhdr=omx->m_out_mem_ptr+v4l2_buf_ptr->index; + DEBUG_PRINT_LOW("[RespBufDone] Buf(%p) Ts(%lld) Pic_type(%u)", + omxhdr, vdec_msg->msgdata.output_frame.time_stamp, + vdec_msg->msgdata.output_frame.pic_type); + + if (omxhdr && omxhdr->pOutputPortPrivate && + ((omxhdr - omx->m_out_mem_ptr) < omx->drv_ctx.op_buf.actualcount) && + (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate + - omx->drv_ctx.ptr_respbuffer) < omx->drv_ctx.op_buf.actualcount)) + { + if ( vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) + { + omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len; + omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset; + omxhdr->nTimeStamp = omx->m_out_mem_ptr[v4l2_buf_ptr->index].nTimeStamp; + omxhdr->nFlags = omx->m_out_mem_ptr[v4l2_buf_ptr->index].nFlags; + + if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_EOS) + { + omxhdr->nFlags |= OMX_BUFFERFLAG_EOS; + //rc = -1; + } + vdec_msg->msgdata.output_frame.bufferaddr=omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr; + output_respbuf = (struct vdec_output_frameinfo *)\ + omxhdr->pOutputPortPrivate; + // output_respbuf->framesize.bottom = + // vdec_msg->msgdata.output_frame.framesize.bottom; + // output_respbuf->framesize.left = + // vdec_msg->msgdata.output_frame.framesize.left; + // output_respbuf->framesize.right = + // vdec_msg->msgdata.output_frame.framesize.right; + // output_respbuf->framesize.top = + // vdec_msg->msgdata.output_frame.framesize.top; + output_respbuf->len = vdec_msg->msgdata.output_frame.len; + output_respbuf->offset = vdec_msg->msgdata.output_frame.offset; + // output_respbuf->time_stamp = vdec_msg->msgdata.output_frame.time_stamp; + // output_respbuf->flags = vdec_msg->msgdata.output_frame.flags; + // output_respbuf->pic_type = vdec_msg->msgdata.output_frame.pic_type; + // output_respbuf->interlaced_format = vdec_msg->msgdata.output_frame.interlaced_format; + + if (omx->output_use_buffer) + memcpy ( omxhdr->pBuffer, + (vdec_msg->msgdata.output_frame.bufferaddr + + vdec_msg->msgdata.output_frame.offset), + vdec_msg->msgdata.output_frame.len ); + } + else + omxhdr->nFilledLen = 0; + omx->post_event ((unsigned int)omxhdr, vdec_msg->status_code, + OMX_COMPONENT_GENERATE_FBD); + } + else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) + omx->post_event (NULL, vdec_msg->status_code, + OMX_COMPONENT_GENERATE_EOS_DONE); + else + omx->post_event (NULL, vdec_msg->status_code, + OMX_COMPONENT_GENERATE_HARDWARE_ERROR); + break; + case VDEC_MSG_EVT_CONFIG_CHANGED: + DEBUG_PRINT_HIGH("\n Port settings changed"); + omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code, + OMX_COMPONENT_GENERATE_PORT_RECONFIG); + break; + case VDEC_MSG_EVT_INFO_CONFIG_CHANGED: + { + DEBUG_PRINT_HIGH("\n Port settings changed info"); + // get_buffer_req and populate port defn structure + OMX_ERRORTYPE eRet = OMX_ErrorNone; + omx->m_port_def.nPortIndex = 1; + eRet = omx->update_portdef(&(omx->m_port_def)); + omx->post_event ((unsigned int)omxhdr,vdec_msg->status_code, + OMX_COMPONENT_GENERATE_INFO_PORT_RECONFIG); + break; + } + default: + break; + } + return rc; +} + +OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary ( + OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer + ) +{ + unsigned address,p2,id; + DEBUG_PRINT_LOW("\n Empty this arbitrary"); + + if (buffer == NULL) + { + return OMX_ErrorBadParameter; + } + DEBUG_PRINT_LOW("\n ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer); + DEBUG_PRINT_LOW("\n ETBProxyArb: nFilledLen %u, flags %d, timestamp %u", + buffer->nFilledLen, buffer->nFlags, (unsigned)buffer->nTimeStamp); + + /* return zero length and not an EOS buffer */ + /* return buffer if input flush in progress */ + if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) && + ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) + { + DEBUG_PRINT_HIGH("\n return zero legth buffer or flush in progress"); + m_cb.EmptyBufferDone (hComp,m_app_data,buffer); + return OMX_ErrorNone; + } + + if (psource_frame == NULL) + { + DEBUG_PRINT_LOW("\n Set Buffer as source Buffer %p time stamp %d",buffer,buffer->nTimeStamp); + psource_frame = buffer; + DEBUG_PRINT_LOW("\n Try to Push One Input Buffer "); + push_input_buffer (hComp); + } + else + { + DEBUG_PRINT_LOW("\n Push the source buffer into pendingq %p",buffer); + if (!m_input_pending_q.insert_entry((unsigned)buffer,NULL,NULL)) + { + return OMX_ErrorBadParameter; + } + } + + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp) +{ + unsigned address,p2,id; + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pdest_frame == NULL || psource_frame == NULL) + { + /*Check if we have a destination buffer*/ + if (pdest_frame == NULL) + { + DEBUG_PRINT_LOW("\n Get a Destination buffer from the queue"); + if (m_input_free_q.m_size) + { + m_input_free_q.pop_entry(&address,&p2,&id); + pdest_frame = (OMX_BUFFERHEADERTYPE *)address; + pdest_frame->nFilledLen = 0; + pdest_frame->nTimeStamp = LLONG_MAX; + DEBUG_PRINT_LOW("\n Address of Pmem Buffer %p",pdest_frame); + } + } + + /*Check if we have a destination buffer*/ + if (psource_frame == NULL) + { + DEBUG_PRINT_LOW("\n Get a source buffer from the queue"); + if (m_input_pending_q.m_size) + { + m_input_pending_q.pop_entry(&address,&p2,&id); + psource_frame = (OMX_BUFFERHEADERTYPE *)address; + DEBUG_PRINT_LOW("\n Next source Buffer %p time stamp %d",psource_frame, + psource_frame->nTimeStamp); + DEBUG_PRINT_LOW("\n Next source Buffer flag %d length %d", + psource_frame->nFlags,psource_frame->nFilledLen); + + } + } + + } + + while ((pdest_frame != NULL) && (psource_frame != NULL)) + { + switch (codec_type_parse) + { + case CODEC_TYPE_MPEG4: + case CODEC_TYPE_H263: + case CODEC_TYPE_MPEG2: + ret = push_input_sc_codec(hComp); + break; + case CODEC_TYPE_H264: + ret = push_input_h264(hComp); + break; + case CODEC_TYPE_VC1: + ret = push_input_vc1(hComp); + break; + } + if (ret != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n Pushing input Buffer Failed"); + omx_report_error (); + break; + } + } + + return ret; +} + +OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp) +{ + OMX_U32 partial_frame = 1; + OMX_BOOL generate_ebd = OMX_TRUE; + unsigned address,p2,id; + + DEBUG_PRINT_LOW("\n Start Parsing the bit stream address %p TimeStamp %d", + psource_frame,psource_frame->nTimeStamp); + if (m_frame_parser.parse_sc_frame(psource_frame, + pdest_frame,&partial_frame) == -1) + { + DEBUG_PRINT_ERROR("\n Error In Parsing Return Error"); + return OMX_ErrorBadParameter; + } + + if (partial_frame == 0) + { + DEBUG_PRINT_LOW("\n Frame size %d source %p frame count %d", + pdest_frame->nFilledLen,psource_frame,frame_count); + + + DEBUG_PRINT_LOW("\n TimeStamp updated %d",pdest_frame->nTimeStamp); + /*First Parsed buffer will have only header Hence skip*/ + if (frame_count == 0) + { + DEBUG_PRINT_LOW("\n H263/MPEG4 Codec First Frame "); + + if(codec_type_parse == CODEC_TYPE_MPEG4 || + codec_type_parse == CODEC_TYPE_DIVX) { + mp4StreamType psBits; + psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset; + psBits.numBytes = pdest_frame->nFilledLen; + mp4_headerparser.parseHeader(&psBits); + } + + frame_count++; + } + else + { + pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; + if(pdest_frame->nFilledLen) + { + /*Push the frame to the Decoder*/ + if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) + { + return OMX_ErrorBadParameter; + } + frame_count++; + pdest_frame = NULL; + + if (m_input_free_q.m_size) + { + m_input_free_q.pop_entry(&address,&p2,&id); + pdest_frame = (OMX_BUFFERHEADERTYPE *) address; + pdest_frame->nFilledLen = 0; + } + } + else if(!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) + { + DEBUG_PRINT_ERROR("\nZero len buffer return back to POOL"); + m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL); + pdest_frame = NULL; + } + } + } + else + { + DEBUG_PRINT_LOW("\n Not a Complete Frame %d",pdest_frame->nFilledLen); + /*Check if Destination Buffer is full*/ + if (pdest_frame->nAllocLen == + pdest_frame->nFilledLen + pdest_frame->nOffset) + { + DEBUG_PRINT_ERROR("\nERROR:Frame Not found though Destination Filled"); + return OMX_ErrorStreamCorrupt; + } + } + + if (psource_frame->nFilledLen == 0) + { + if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) + { + if (pdest_frame) + { + pdest_frame->nFlags |= psource_frame->nFlags; + DEBUG_PRINT_LOW("\n Frame Found start Decoding Size =%d TimeStamp = %x", + pdest_frame->nFilledLen,pdest_frame->nTimeStamp); + DEBUG_PRINT_LOW("\n Found a frame size = %d number = %d", + pdest_frame->nFilledLen,frame_count++); + /*Push the frame to the Decoder*/ + if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) + { + return OMX_ErrorBadParameter; + } + frame_count++; + pdest_frame = NULL; + } + else + { + DEBUG_PRINT_LOW("\n Last frame in else dest addr") ; + generate_ebd = OMX_FALSE; + } + } + if(generate_ebd) + { + DEBUG_PRINT_LOW("\n Buffer Consumed return back to client %p",psource_frame); + m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame); + psource_frame = NULL; + + if (m_input_pending_q.m_size) + { + DEBUG_PRINT_LOW("\n Pull Next source Buffer %p",psource_frame); + m_input_pending_q.pop_entry(&address,&p2,&id); + psource_frame = (OMX_BUFFERHEADERTYPE *) address; + DEBUG_PRINT_LOW("\n Next source Buffer %p time stamp %d",psource_frame, + psource_frame->nTimeStamp); + DEBUG_PRINT_LOW("\n Next source Buffer flag %d length %d", + psource_frame->nFlags,psource_frame->nFilledLen); + } + } + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp) +{ + OMX_U32 partial_frame = 1; + unsigned address,p2,id; + OMX_BOOL isNewFrame = OMX_FALSE; + OMX_BOOL generate_ebd = OMX_TRUE; + + if (h264_scratch.pBuffer == NULL) + { + DEBUG_PRINT_ERROR("\nERROR:H.264 Scratch Buffer not allocated"); + return OMX_ErrorBadParameter; + } + DEBUG_PRINT_LOW("\n Pending h264_scratch.nFilledLen %d " + "look_ahead_nal %d", h264_scratch.nFilledLen, look_ahead_nal); + DEBUG_PRINT_LOW("\n Pending pdest_frame->nFilledLen %d",pdest_frame->nFilledLen); + if (h264_scratch.nFilledLen && look_ahead_nal) + { + look_ahead_nal = false; + if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= + h264_scratch.nFilledLen) + { + memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), + h264_scratch.pBuffer,h264_scratch.nFilledLen); + pdest_frame->nFilledLen += h264_scratch.nFilledLen; + DEBUG_PRINT_LOW("\n Copy the previous NAL (h264 scratch) into Dest frame"); + h264_scratch.nFilledLen = 0; + } + else + { + DEBUG_PRINT_ERROR("\n Error:1: Destination buffer overflow for H264"); + return OMX_ErrorBadParameter; + } + } + if (nal_length == 0) + { + DEBUG_PRINT_LOW("\n Zero NAL, hence parse using start code"); + if (m_frame_parser.parse_sc_frame(psource_frame, + &h264_scratch,&partial_frame) == -1) + { + DEBUG_PRINT_ERROR("\n Error In Parsing Return Error"); + return OMX_ErrorBadParameter; + } + } + else + { + DEBUG_PRINT_LOW("\n Non-zero NAL length clip, hence parse with NAL size %d ",nal_length); + if (m_frame_parser.parse_h264_nallength(psource_frame, + &h264_scratch,&partial_frame) == -1) + { + DEBUG_PRINT_ERROR("\n Error In Parsing NAL size, Return Error"); + return OMX_ErrorBadParameter; + } + } + + if (partial_frame == 0) + { + if (nal_count == 0 && h264_scratch.nFilledLen == 0) + { + DEBUG_PRINT_LOW("\n First NAL with Zero Length, hence Skip"); + nal_count++; + h264_scratch.nTimeStamp = psource_frame->nTimeStamp; + h264_scratch.nFlags = psource_frame->nFlags; + } + else + { + DEBUG_PRINT_LOW("\n Parsed New NAL Length = %d",h264_scratch.nFilledLen); + if(h264_scratch.nFilledLen) + { + h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen, + NALU_TYPE_SPS); +#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT + if (client_extradata & OMX_TIMEINFO_EXTRADATA) + h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, + h264_scratch.nFilledLen, NALU_TYPE_SEI); + else if (client_extradata & OMX_FRAMEINFO_EXTRADATA) + // If timeinfo is present frame info from SEI is already processed + h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, + h264_scratch.nFilledLen, NALU_TYPE_SEI); +#endif + m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame); + nal_count++; + if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) { + pdest_frame->nTimeStamp = h264_last_au_ts; + pdest_frame->nFlags = h264_last_au_flags; +#ifdef PANSCAN_HDLR + if (client_extradata & OMX_FRAMEINFO_EXTRADATA) + h264_parser->update_panscan_data(h264_last_au_ts); +#endif + } + if(m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR || + m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) { + h264_last_au_ts = h264_scratch.nTimeStamp; + h264_last_au_flags = h264_scratch.nFlags; +#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT + if (client_extradata & OMX_TIMEINFO_EXTRADATA) + { + OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts); + if (!VALID_TS(h264_last_au_ts)) + h264_last_au_ts = ts_in_sei; + } +#endif + } else + h264_last_au_ts = LLONG_MAX; + } + + if (!isNewFrame) + { + if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= + h264_scratch.nFilledLen) + { + DEBUG_PRINT_LOW("\n Not a NewFrame Copy into Dest len %d", + h264_scratch.nFilledLen); + memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), + h264_scratch.pBuffer,h264_scratch.nFilledLen); + pdest_frame->nFilledLen += h264_scratch.nFilledLen; + if(m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ) + pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ; + h264_scratch.nFilledLen = 0; + } + else + { + DEBUG_PRINT_LOW("\n Error:2: Destination buffer overflow for H264"); + return OMX_ErrorBadParameter; + } + } + else + { + look_ahead_nal = true; + DEBUG_PRINT_LOW("\n Frame Found start Decoding Size =%d TimeStamp = %x", + pdest_frame->nFilledLen,pdest_frame->nTimeStamp); + DEBUG_PRINT_LOW("\n Found a frame size = %d number = %d", + pdest_frame->nFilledLen,frame_count++); + + if (pdest_frame->nFilledLen == 0) + { + DEBUG_PRINT_LOW("\n Copy the Current Frame since and push it"); + look_ahead_nal = false; + if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= + h264_scratch.nFilledLen) + { + memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), + h264_scratch.pBuffer,h264_scratch.nFilledLen); + pdest_frame->nFilledLen += h264_scratch.nFilledLen; + h264_scratch.nFilledLen = 0; + } + else + { + DEBUG_PRINT_ERROR("\n Error:3: Destination buffer overflow for H264"); + return OMX_ErrorBadParameter; + } + } + else + { + if(psource_frame->nFilledLen || h264_scratch.nFilledLen) + { + DEBUG_PRINT_LOW("\n Reset the EOS Flag"); + pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS; + } + /*Push the frame to the Decoder*/ + if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) + { + return OMX_ErrorBadParameter; + } + //frame_count++; + pdest_frame = NULL; + if (m_input_free_q.m_size) + { + m_input_free_q.pop_entry(&address,&p2,&id); + pdest_frame = (OMX_BUFFERHEADERTYPE *) address; + DEBUG_PRINT_LOW("\n Pop the next pdest_buffer %p",pdest_frame); + pdest_frame->nFilledLen = 0; + pdest_frame->nFlags = 0; + pdest_frame->nTimeStamp = LLONG_MAX; + } + } + } + } + } + else + { + DEBUG_PRINT_LOW("\n Not a Complete Frame, pdest_frame->nFilledLen %d",pdest_frame->nFilledLen); + /*Check if Destination Buffer is full*/ + if (h264_scratch.nAllocLen == + h264_scratch.nFilledLen + h264_scratch.nOffset) + { + DEBUG_PRINT_ERROR("\nERROR: Frame Not found though Destination Filled"); + return OMX_ErrorStreamCorrupt; + } + } + + if (!psource_frame->nFilledLen) + { + DEBUG_PRINT_LOW("\n Buffer Consumed return source %p back to client",psource_frame); + + if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) + { + if (pdest_frame) + { + DEBUG_PRINT_LOW("\n EOS Reached Pass Last Buffer"); + if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >= + h264_scratch.nFilledLen) + { + memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen), + h264_scratch.pBuffer,h264_scratch.nFilledLen); + pdest_frame->nFilledLen += h264_scratch.nFilledLen; + h264_scratch.nFilledLen = 0; + } + else + { + DEBUG_PRINT_ERROR("\nERROR:4: Destination buffer overflow for H264"); + return OMX_ErrorBadParameter; + } + pdest_frame->nTimeStamp = h264_scratch.nTimeStamp; + pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags; + + DEBUG_PRINT_LOW("\n pdest_frame->nFilledLen =%d TimeStamp = %x", + pdest_frame->nFilledLen,pdest_frame->nTimeStamp); + DEBUG_PRINT_LOW("\n Push AU frame number %d to driver", frame_count++); +#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT + if (client_extradata & OMX_TIMEINFO_EXTRADATA) + { + OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp); + if (!VALID_TS(pdest_frame->nTimeStamp)) + pdest_frame->nTimeStamp = ts_in_sei; + } +#endif + /*Push the frame to the Decoder*/ + if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) + { + return OMX_ErrorBadParameter; + } + frame_count++; + pdest_frame = NULL; + } + else + { + DEBUG_PRINT_LOW("\n Last frame in else dest addr %p size %d", + pdest_frame,h264_scratch.nFilledLen); + generate_ebd = OMX_FALSE; + } + } + } + if(generate_ebd && !psource_frame->nFilledLen) + { + m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame); + psource_frame = NULL; + if (m_input_pending_q.m_size) + { + DEBUG_PRINT_LOW("\n Pull Next source Buffer %p",psource_frame); + m_input_pending_q.pop_entry(&address,&p2,&id); + psource_frame = (OMX_BUFFERHEADERTYPE *) address; + DEBUG_PRINT_LOW("\nNext source Buffer flag %d src length %d", + psource_frame->nFlags,psource_frame->nFilledLen); + } + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_vdec::push_input_vc1 (OMX_HANDLETYPE hComp) +{ + OMX_U8 *buf, *pdest; + OMX_U32 partial_frame = 1; + OMX_U32 buf_len, dest_len; + + if(first_frame == 0) + { + first_frame = 1; + DEBUG_PRINT_LOW("\nFirst i/p buffer for VC1 arbitrary bytes\n"); + if(!m_vendor_config.pData) + { + DEBUG_PRINT_LOW("\nCheck profile type in 1st source buffer\n"); + buf = psource_frame->pBuffer; + buf_len = psource_frame->nFilledLen; + + if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) == + VC1_SP_MP_START_CODE) + { + m_vc1_profile = VC1_SP_MP_RCV; + } + else if(*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) + { + m_vc1_profile = VC1_AP; + } + else + { + DEBUG_PRINT_ERROR("\nInvalid sequence layer in first buffer\n"); + return OMX_ErrorStreamCorrupt; + } + } + else + { + pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen + + pdest_frame->nOffset; + dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen + + pdest_frame->nOffset); + + if(dest_len < m_vendor_config.nDataSize) + { + DEBUG_PRINT_ERROR("\nDestination buffer full\n"); + return OMX_ErrorBadParameter; + } + else + { + memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize); + pdest_frame->nFilledLen += m_vendor_config.nDataSize; + } + } + } + + switch(m_vc1_profile) + { + case VC1_AP: + DEBUG_PRINT_LOW("\n VC1 AP, hence parse using frame start code"); + if (push_input_sc_codec(hComp) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n Error In Parsing VC1 AP start code"); + return OMX_ErrorBadParameter; + } + break; + + case VC1_SP_MP_RCV: + default: + DEBUG_PRINT_ERROR("\n Unsupported VC1 profile in ArbitraryBytes Mode\n"); + return OMX_ErrorBadParameter; + } + return OMX_ErrorNone; +} + +bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size, + OMX_U32 alignment) +{ + struct pmem_allocation allocation; + allocation.size = buffer_size; + allocation.align = clip2(alignment); + if (allocation.align < 4096) + { + allocation.align = 4096; + } + if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) + { + DEBUG_PRINT_ERROR("\n Aligment(%u) failed with pmem driver Sz(%lu)", + allocation.align, allocation.size); + return false; + } + return true; +} +#ifdef USE_ION +int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size, + OMX_U32 alignment, struct ion_allocation_data *alloc_data, + struct ion_fd_data *fd_data, int flag) +{ + int fd = -EINVAL; + int rc = -EINVAL; + int ion_dev_flag; + struct vdec_ion ion_buf_info; + if (!alloc_data || buffer_size <= 0 || !fd_data) { + DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory\n"); + return -EINVAL; + } + if(!secure_mode && flag == CACHED) + { + ion_dev_flag = O_RDONLY; + } else { + ion_dev_flag = (O_RDONLY | O_DSYNC); + } + fd = open (MEM_DEVICE, ion_dev_flag); + if (fd < 0) { + DEBUG_PRINT_ERROR("opening ion device failed with fd = %d\n", fd); + return fd; + } + alloc_data->len = buffer_size; + alloc_data->align = clip2(alignment); + if (alloc_data->align < 4096) + { + alloc_data->align = 4096; + } + if(secure_mode) { + alloc_data->flags = (ION_HEAP(MEM_HEAP_ID) | ION_SECURE); + } else { + alloc_data->flags = ION_HEAP(MEM_HEAP_ID); + } + rc = ioctl(fd,ION_IOC_ALLOC,alloc_data); + if (rc || !alloc_data->handle) { + DEBUG_PRINT_ERROR("\n ION ALLOC memory failed "); + alloc_data->handle = NULL; + close(fd); + fd = -ENOMEM; + return fd; + } + fd_data->handle = alloc_data->handle; + rc = ioctl(fd,ION_IOC_MAP,fd_data); + if (rc) { + DEBUG_PRINT_ERROR("\n ION MAP failed "); + ion_buf_info.ion_alloc_data = *alloc_data; + ion_buf_info.ion_device_fd = fd; + ion_buf_info.fd_ion_data = *fd_data; + free_ion_memory(&ion_buf_info); + fd_data->fd =-1; + close(fd); + fd = -ENOMEM; + } + + return fd; +} + +void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info) { + + if(!buf_ion_info) { + DEBUG_PRINT_ERROR("\n ION: free called with invalid fd/allocdata"); + return; + } + if(ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE, + &buf_ion_info->ion_alloc_data.handle)) { + DEBUG_PRINT_ERROR("\n ION: free failed" ); + } + close(buf_ion_info->ion_device_fd); + buf_ion_info->ion_device_fd = -1; + buf_ion_info->ion_alloc_data.handle = NULL; + buf_ion_info->fd_ion_data.fd = -1; +} +#endif +void omx_vdec::free_output_buffer_header() +{ + DEBUG_PRINT_HIGH("\n ALL output buffers are freed/released"); + output_use_buffer = false; + ouput_egl_buffers = false; + + if (m_out_mem_ptr) + { + free (m_out_mem_ptr); + m_out_mem_ptr = NULL; + } + + if(m_platform_list) + { + free(m_platform_list); + m_platform_list = NULL; + } + + if (drv_ctx.ptr_respbuffer) + { + free (drv_ctx.ptr_respbuffer); + drv_ctx.ptr_respbuffer = NULL; + } + if (drv_ctx.ptr_outputbuffer) + { + free (drv_ctx.ptr_outputbuffer); + drv_ctx.ptr_outputbuffer = NULL; + } +#ifdef USE_ION + if (drv_ctx.op_buf_ion_info) { + DEBUG_PRINT_LOW("\n Free o/p ion context"); + free(drv_ctx.op_buf_ion_info); + drv_ctx.op_buf_ion_info = NULL; + } +#endif +} + +void omx_vdec::free_input_buffer_header() +{ + input_use_buffer = false; + if (arbitrary_bytes) + { + if (m_frame_parser.mutils) + { + DEBUG_PRINT_LOW("\n Free utils parser"); + delete (m_frame_parser.mutils); + m_frame_parser.mutils = NULL; + } + + if (m_inp_heap_ptr) + { + DEBUG_PRINT_LOW("\n Free input Heap Pointer"); + free (m_inp_heap_ptr); + m_inp_heap_ptr = NULL; + } + + if (m_phdr_pmem_ptr) + { + DEBUG_PRINT_LOW("\n Free input pmem header Pointer"); + free (m_phdr_pmem_ptr); + m_phdr_pmem_ptr = NULL; + } + } + if (m_inp_mem_ptr) + { + DEBUG_PRINT_LOW("\n Free input pmem Pointer area"); + free (m_inp_mem_ptr); + m_inp_mem_ptr = NULL; + } + if (drv_ctx.ptr_inputbuffer) + { + DEBUG_PRINT_LOW("\n Free Driver Context pointer"); + free (drv_ctx.ptr_inputbuffer); + drv_ctx.ptr_inputbuffer = NULL; + } +#ifdef USE_ION + if (drv_ctx.ip_buf_ion_info) { + DEBUG_PRINT_LOW("\n Free ion context"); + free(drv_ctx.ip_buf_ion_info); + drv_ctx.ip_buf_ion_info = NULL; + } +#endif +} +void omx_vdec::stream_off() +{ + int rc=0; + enum v4l2_buf_type btype; + btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype); + if (rc) { + /*TODO: How to handle this case */ + DEBUG_PRINT_ERROR("\n Failed to call streamoff on OUTPUT Port \n"); + } else { + streaming[CAPTURE_PORT] = false; + } +} + +OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct v4l2_requestbuffers bufreq; + unsigned int buf_size = 0, extra_data_size = 0; + struct v4l2_format fmt; + int ret; + DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%d)", + buffer_prop->actualcount, buffer_prop->buffer_size); + bufreq.memory = V4L2_MEMORY_USERPTR; + if(in_reconfig == true) + bufreq.count = 0; + else + bufreq.count = 2; + if(buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT){ + bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt.fmt.pix_mp.pixelformat = output_capability; + }else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT){ + bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.pixelformat = capture_capability; + }else {eRet = OMX_ErrorBadParameter;} + if(eRet==OMX_ErrorNone){ + ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq); + } + if(ret) + { + DEBUG_PRINT_ERROR("Requesting buffer requirements failed"); + /*TODO: How to handle this case */ + eRet = OMX_ErrorInsufficientResources; + return eRet; + } + else + { + buffer_prop->actualcount = bufreq.count; + buffer_prop->mincount = bufreq.count; + DEBUG_PRINT_HIGH("Count = %d \n ",bufreq.count); + } + DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%d)", + buffer_prop->actualcount, buffer_prop->buffer_size); + + fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; + fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; + + ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt); + + drv_ctx.video_resolution.frame_height = fmt.fmt.pix_mp.height; + drv_ctx.video_resolution.frame_width = fmt.fmt.pix_mp.width; + + DEBUG_PRINT_HIGH("Buffer Size = %d \n ",fmt.fmt.pix_mp.plane_fmt[0].sizeimage); + + if(ret) + { + /*TODO: How to handle this case */ + DEBUG_PRINT_ERROR("Requesting buffer requirements failed"); + eRet = OMX_ErrorInsufficientResources; + } + else + { + buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage; + buf_size = buffer_prop->buffer_size; + if (client_extradata & OMX_FRAMEINFO_EXTRADATA) + { + DEBUG_PRINT_HIGH("Frame info extra data enabled!"); + extra_data_size += OMX_FRAMEINFO_EXTRADATA_SIZE; + } + if (client_extradata & OMX_INTERLACE_EXTRADATA) + { + DEBUG_PRINT_HIGH("Interlace extra data enabled!"); + extra_data_size += OMX_INTERLACE_EXTRADATA_SIZE; + } + if (client_extradata & OMX_PORTDEF_EXTRADATA) + { + extra_data_size += OMX_PORTDEF_EXTRADATA_SIZE; + DEBUG_PRINT_HIGH("Smooth streaming enabled extra_data_size=%d\n", + extra_data_size); + } + if (extra_data_size) + { + extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator + buf_size = ((buf_size + 3)&(~3)); //Align extradata start address to 64Bit + } + buf_size += extra_data_size; + buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); + DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%d) BufSize(%d)", + buffer_prop->actualcount, buffer_prop->buffer_size, buf_size); + if (in_reconfig) // BufReq will be set to driver when port is disabled + buffer_prop->buffer_size = buf_size; + else if (buf_size != buffer_prop->buffer_size) + { + buffer_prop->buffer_size = buf_size; + eRet = set_buffer_req(buffer_prop); + } + } + DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%d)", + buffer_prop->actualcount, buffer_prop->buffer_size); + return eRet; +} + +OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned buf_size = 0; + struct v4l2_format fmt; + int ret; + DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%d)", + buffer_prop->actualcount, buffer_prop->buffer_size); + buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1)); + if (buf_size != buffer_prop->buffer_size) + { + DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%d) Required(%d)", + buffer_prop->buffer_size, buf_size); + eRet = OMX_ErrorBadParameter; + } + else + { + fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height; + fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width; + if(buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT){ + fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt.fmt.pix_mp.pixelformat = output_capability; + }else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT){ +fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.pixelformat = capture_capability; +} else {eRet = OMX_ErrorBadParameter;} + ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt); + if(ret) + { + /*TODO: How to handle this case */ + DEBUG_PRINT_ERROR("Setting buffer requirements failed"); + eRet = OMX_ErrorInsufficientResources; + } + } + return eRet; +} + +OMX_ERRORTYPE omx_vdec::update_picture_resolution() +{ + struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; + OMX_ERRORTYPE eRet = OMX_ErrorNone; + ioctl_msg.in = NULL; + ioctl_msg.out = &drv_ctx.video_resolution; + if (/*ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_GET_PICRES, &ioctl_msg)*/0) + { + DEBUG_PRINT_ERROR("Error VDEC_IOCTL_GET_PICRES"); + eRet = OMX_ErrorHardware; + } + return eRet; +} + +OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if (!portDefn) + { + return OMX_ErrorBadParameter; + } + DEBUG_PRINT_LOW("omx_vdec::update_portdef\n"); + portDefn->nVersion.nVersion = OMX_SPEC_VERSION; + portDefn->nSize = sizeof(portDefn); + portDefn->eDomain = OMX_PortDomainVideo; + if (drv_ctx.frame_rate.fps_denominator > 0) + portDefn->format.video.xFramerate = drv_ctx.frame_rate.fps_numerator / + drv_ctx.frame_rate.fps_denominator; + else { + DEBUG_PRINT_ERROR("Error: Divide by zero \n"); + return OMX_ErrorBadParameter; + } + if (0 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirInput; + portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount; + portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount; + portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size; + portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused; + portDefn->format.video.eCompressionFormat = eCompressionFormat; + portDefn->bEnabled = m_inp_bEnabled; + portDefn->bPopulated = m_inp_bPopulated; + } + else if (1 == portDefn->nPortIndex) + { + portDefn->eDir = OMX_DirOutput; + eRet=get_buffer_req(&drv_ctx.op_buf); + if (in_reconfig) + { + portDefn->nBufferCountActual = op_buf_rcnfg.actualcount; + portDefn->nBufferCountMin = op_buf_rcnfg.mincount; + portDefn->nBufferSize = op_buf_rcnfg.buffer_size; + } + else + { + portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount; + portDefn->nBufferCountMin = drv_ctx.op_buf.mincount; + portDefn->nBufferSize = drv_ctx.op_buf.buffer_size; + } + portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + portDefn->bEnabled = m_out_bEnabled; + portDefn->bPopulated = m_out_bPopulated; + if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) + portDefn->format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + else if (drv_ctx.output_format == VDEC_YUV_FORMAT_TILE_4x2) + portDefn->format.video.eColorFormat = (OMX_COLOR_FORMATTYPE) + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; + else + { + DEBUG_PRINT_ERROR("ERROR: Color format unknown: %x\n", drv_ctx.output_format); + } + } + else + { + portDefn->eDir = OMX_DirMax; + DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d", + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height; + portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width; + portDefn->format.video.nStride = drv_ctx.video_resolution.stride; + portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines; + DEBUG_PRINT_LOW("update_portdef Width = %d Height = %d Stride = %u" + "SliceHeight = %u \n", portDefn->format.video.nFrameHeight, + portDefn->format.video.nFrameWidth, + portDefn->format.video.nStride, + portDefn->format.video.nSliceHeight); + return eRet; + +} + +OMX_ERRORTYPE omx_vdec::allocate_output_headers() +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr = NULL; + unsigned i= 0; + + if(!m_out_mem_ptr) { + DEBUG_PRINT_HIGH("\n Use o/p buffer case - Header List allocation"); + int nBufHdrSize = 0; + int nPlatformEntrySize = 0; + int nPlatformListSize = 0; + int nPMEMInfoSize = 0; + OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList; + OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry; + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo; + + DEBUG_PRINT_LOW("Setting First Output Buffer(%d)\n", + drv_ctx.op_buf.actualcount); + nBufHdrSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_BUFFERHEADERTYPE); + + nPMEMInfoSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO); + nPlatformListSize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST); + nPlatformEntrySize = drv_ctx.op_buf.actualcount * + sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY); + + DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",nBufHdrSize, + sizeof(OMX_BUFFERHEADERTYPE), + nPMEMInfoSize, + nPlatformListSize); + DEBUG_PRINT_LOW("PE %d bmSize %d \n",nPlatformEntrySize, + m_out_bm_count); + m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); + // Alloc mem for platform specific info + char *pPtr=NULL; + pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize + + nPMEMInfoSize,1); + drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \ + calloc (sizeof(struct vdec_bufferpayload), + drv_ctx.op_buf.actualcount); + drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\ + calloc (sizeof (struct vdec_output_frameinfo), + drv_ctx.op_buf.actualcount); +#ifdef USE_ION + drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \ + calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount); +#endif + + if(m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer + && drv_ctx.ptr_respbuffer) + { + bufHdr = m_out_mem_ptr; + m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr); + m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) + (((char *) m_platform_list) + nPlatformListSize); + m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + (((char *) m_platform_entry) + nPlatformEntrySize); + pPlatformList = m_platform_list; + pPlatformEntry = m_platform_entry; + pPMEMInfo = m_pmem_info; + + DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr); + + // Settting the entire storage nicely + DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p\n",bufHdr, + m_out_mem_ptr,pPlatformEntry); + DEBUG_PRINT_LOW(" Pmem Info = %p \n",pPMEMInfo); + for(i=0; i < drv_ctx.op_buf.actualcount ; i++) + { + bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + // Set the values when we determine the right HxW param + bufHdr->nAllocLen = 0; + bufHdr->nFilledLen = 0; + bufHdr->pAppPrivate = NULL; + bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; + pPlatformEntry->entry = pPMEMInfo; + // Initialize the Platform List + pPlatformList->nEntries = 1; + pPlatformList->entryList = pPlatformEntry; + // Keep pBuffer NULL till vdec is opened + bufHdr->pBuffer = NULL; + pPMEMInfo->offset = 0; + pPMEMInfo->pmem_fd = 0; + bufHdr->pPlatformPrivate = pPlatformList; + drv_ctx.ptr_outputbuffer[i].pmem_fd = -1; +#ifdef USE_ION + drv_ctx.op_buf_ion_info[i].ion_device_fd =-1; +#endif + /*Create a mapping between buffers*/ + bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i]; + drv_ctx.ptr_respbuffer[i].client_data = (void *) \ + &drv_ctx.ptr_outputbuffer[i]; + // Move the buffer and buffer header pointers + bufHdr++; + pPMEMInfo++; + pPlatformEntry++; + pPlatformList++; + } + } + else + { + DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%x][0x%x]\n",\ + m_out_mem_ptr, pPtr); + if(m_out_mem_ptr) + { + free(m_out_mem_ptr); + m_out_mem_ptr = NULL; + } + if(pPtr) + { + free(pPtr); + pPtr = NULL; + } + if(drv_ctx.ptr_outputbuffer) + { + free(drv_ctx.ptr_outputbuffer); + drv_ctx.ptr_outputbuffer = NULL; + } + if(drv_ctx.ptr_respbuffer) + { + free(drv_ctx.ptr_respbuffer); + drv_ctx.ptr_respbuffer = NULL; + } +#ifdef USE_ION + if (drv_ctx.op_buf_ion_info) { + DEBUG_PRINT_LOW("\n Free o/p ion context"); + free(drv_ctx.op_buf_ion_info); + drv_ctx.op_buf_ion_info = NULL; + } +#endif + eRet = OMX_ErrorInsufficientResources; + } + } else { + eRet = OMX_ErrorInsufficientResources; + } + return eRet; +} + +void omx_vdec::complete_pending_buffer_done_cbs() +{ + unsigned p1; + unsigned p2; + unsigned ident; + omx_cmd_queue tmp_q, pending_bd_q; + pthread_mutex_lock(&m_lock); + // pop all pending GENERATE FDB from ftb queue + while (m_ftb_q.m_size) + { + m_ftb_q.pop_entry(&p1,&p2,&ident); + if(ident == OMX_COMPONENT_GENERATE_FBD) + { + pending_bd_q.insert_entry(p1,p2,ident); + } + else + { + tmp_q.insert_entry(p1,p2,ident); + } + } + //return all non GENERATE FDB to ftb queue + while(tmp_q.m_size) + { + tmp_q.pop_entry(&p1,&p2,&ident); + m_ftb_q.insert_entry(p1,p2,ident); + } + // pop all pending GENERATE EDB from etb queue + while (m_etb_q.m_size) + { + m_etb_q.pop_entry(&p1,&p2,&ident); + if(ident == OMX_COMPONENT_GENERATE_EBD) + { + pending_bd_q.insert_entry(p1,p2,ident); + } + else + { + tmp_q.insert_entry(p1,p2,ident); + } + } + //return all non GENERATE FDB to etb queue + while(tmp_q.m_size) + { + tmp_q.pop_entry(&p1,&p2,&ident); + m_etb_q.insert_entry(p1,p2,ident); + } + pthread_mutex_unlock(&m_lock); + // process all pending buffer dones + while(pending_bd_q.m_size) + { + pending_bd_q.pop_entry(&p1,&p2,&ident); + switch(ident) + { + case OMX_COMPONENT_GENERATE_EBD: + if(empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\nERROR: empty_buffer_done() failed!\n"); + omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_FBD: + if(fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) + { + DEBUG_PRINT_ERROR("\nERROR: fill_buffer_done() failed!\n"); + omx_report_error (); + } + break; + } + } +} + +void omx_vdec::set_frame_rate(OMX_S64 act_timestamp) +{ + OMX_U32 new_frame_interval = 0; + struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; + if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts + && (((act_timestamp > prev_ts )? act_timestamp - prev_ts: prev_ts-act_timestamp)>2000)) + { + new_frame_interval = (act_timestamp > prev_ts)? + act_timestamp - prev_ts : + prev_ts - act_timestamp; + if (new_frame_interval < frm_int || frm_int == 0) + { + frm_int = new_frame_interval; + if(frm_int) + { + drv_ctx.frame_rate.fps_numerator = 1e6; + drv_ctx.frame_rate.fps_denominator = frm_int; + DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)", + frm_int, drv_ctx.frame_rate.fps_numerator / + (float)drv_ctx.frame_rate.fps_denominator); + ioctl_msg.in = &drv_ctx.frame_rate; + if (/*ioctl (drv_ctx.video_driver_fd, VDEC_IOCTL_SET_FRAME_RATE, + (void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("Setting frame rate failed"); + } + } + } + } + prev_ts = act_timestamp; +} + +void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp) +{ + if (rst_prev_ts && VALID_TS(act_timestamp)) + { + prev_ts = act_timestamp; + rst_prev_ts = false; + } + else if (VALID_TS(prev_ts)) + { + bool codec_cond = (drv_ctx.timestamp_adjust)? + (!VALID_TS(act_timestamp) || (((act_timestamp > prev_ts)? + (act_timestamp - prev_ts):(prev_ts - act_timestamp)) <= 2000)): + (!VALID_TS(act_timestamp) || act_timestamp == prev_ts); + if(frm_int > 0 && codec_cond) + { + DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp); + act_timestamp = prev_ts + frm_int; + DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp); + prev_ts = act_timestamp; + } + else + set_frame_rate(act_timestamp); + } + else if (frm_int > 0) // In this case the frame rate was set along + { // with the port definition, start ts with 0 + act_timestamp = prev_ts = 0; // and correct if a valid ts is received. + rst_prev_ts = true; + } +} + +void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) +{ + OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL; + OMX_U32 num_conceal_MB = 0; + OMX_S64 ts_in_sei = 0; + OMX_U32 frame_rate = 0; + p_extra = (OMX_OTHER_EXTRADATATYPE *) + ((unsigned)(p_buf_hdr->pBuffer + p_buf_hdr->nOffset + + p_buf_hdr->nFilledLen + 3)&(~3)); + if ((OMX_U8*)p_extra > (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen)) + p_extra = NULL; + if (drv_ctx.extradata && (p_buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA)) + { + // Process driver extradata + while(p_extra && p_extra->eType != VDEC_EXTRADATA_NONE) + { + DEBUG_PRINT_LOW("handle_extradata : pBuf(%p) BufTS(%lld) Type(%x) DataSz(%u)", + p_buf_hdr, p_buf_hdr->nTimeStamp, p_extra->eType, p_extra->nDataSize); + if (p_extra->nSize < p_extra->nDataSize) + { + DEBUG_PRINT_ERROR(" \n Corrupt metadata Buffer size %d payload size %d", + p_extra->nSize, p_extra->nDataSize); + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + if ((OMX_U8*)p_extra > (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen) || + p_extra->nDataSize == 0) + p_extra = NULL; + continue; + } + if (p_extra->eType == VDEC_EXTRADATA_MB_ERROR_MAP) + { + if (client_extradata & OMX_FRAMEINFO_EXTRADATA) + num_conceal_MB = count_MB_in_extradata(p_extra); + if (client_extradata & VDEC_EXTRADATA_MB_ERROR_MAP) + // Map driver extradata to corresponding OMX type + p_extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataConcealMB; + else + p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client + if (m_debug_concealedmb) { + DEBUG_PRINT_HIGH("Concealed MB percentage is %u", num_conceal_MB); + } + } + else if (p_extra->eType == VDEC_EXTRADATA_SEI) + { + p_sei = p_extra; + + h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI); + + p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client + } + else if (p_extra->eType == VDEC_EXTRADATA_VUI) + { + p_vui = p_extra; + + h264_parser->parse_nal((OMX_U8*)p_vui->data, p_vui->nDataSize, NALU_TYPE_VUI, false); + + p_extra->eType = OMX_ExtraDataMax; // Invalid type to avoid expose this extradata to OMX client + } + print_debug_extradata(p_extra); + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + if ((OMX_U8*)p_extra > (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen) || + p_extra->nDataSize == 0) + p_extra = NULL; + } + if (!(client_extradata & VDEC_EXTRADATA_MB_ERROR_MAP)) + { + // Driver extradata is only exposed if MB map is requested by client, + // otherwise can be overwritten by omx extradata. + p_extra = (OMX_OTHER_EXTRADATATYPE *) + ((unsigned)(p_buf_hdr->pBuffer + p_buf_hdr->nOffset + + p_buf_hdr->nFilledLen + 3)&(~3)); + p_buf_hdr->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; + } + } + +#ifdef PROCESS_EXTRADATA_IN_OUTPUT_PORT + if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + if (client_extradata & OMX_TIMEINFO_EXTRADATA) + { + if (p_vui) + h264_parser->parse_nal((OMX_U8*)p_vui->data, p_vui->nDataSize, NALU_TYPE_VUI, false); + if (p_sei) + h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI); + ts_in_sei = h264_parser->process_ts_with_sei_vui(p_buf_hdr->nTimeStamp); + if (!VALID_TS(p_buf_hdr->nTimeStamp)) + p_buf_hdr->nTimeStamp = ts_in_sei; + } + else if ((client_extradata & OMX_FRAMEINFO_EXTRADATA) && p_sei) + // If timeinfo is present frame info from SEI is already processed + h264_parser->parse_nal((OMX_U8*)p_sei->data, p_sei->nDataSize, NALU_TYPE_SEI); + } +#endif + if ((client_extradata & OMX_INTERLACE_EXTRADATA) && p_extra && + ((OMX_U8*)p_extra + OMX_INTERLACE_EXTRADATA_SIZE) < + (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen)) + { + p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; + append_interlace_extradata(p_extra, + ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->interlaced_format); + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + } + if (client_extradata & OMX_FRAMEINFO_EXTRADATA && p_extra && + ((OMX_U8*)p_extra + OMX_FRAMEINFO_EXTRADATA_SIZE) < + (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen)) + { + p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; + /* vui extra data (frame_rate) information */ + if (h264_parser) + h264_parser->get_frame_rate(&frame_rate); + append_frame_info_extradata(p_extra, num_conceal_MB, + ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, + p_buf_hdr->nTimeStamp, frame_rate, NULL); + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + } + if ((client_extradata & OMX_PORTDEF_EXTRADATA) && + p_extra != NULL && + ((OMX_U8*)p_extra + OMX_PORTDEF_EXTRADATA_SIZE) < + (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen)) + { + p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; + append_portdef_extradata(p_extra); + p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize); + } + if (p_buf_hdr->nFlags & OMX_BUFFERFLAG_EXTRADATA) + if (p_extra && + ((OMX_U8*)p_extra + OMX_FRAMEINFO_EXTRADATA_SIZE) < + (p_buf_hdr->pBuffer + p_buf_hdr->nAllocLen)) + append_terminator_extradata(p_extra); + else + { + DEBUG_PRINT_ERROR("ERROR: Terminator extradata cannot be added"); + p_buf_hdr->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; + } +} + +OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata, bool enable) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_U32 driver_extradata = 0, extradata_size = 0; + struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; + if(m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only"); + return OMX_ErrorIncorrectStateOperation; + } + if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) + extradata_size += OMX_FRAMEINFO_EXTRADATA_SIZE; + if (requested_extradata & OMX_INTERLACE_EXTRADATA) + extradata_size += OMX_INTERLACE_EXTRADATA_SIZE; + if (requested_extradata & OMX_PORTDEF_EXTRADATA) + { + extradata_size += OMX_PORTDEF_EXTRADATA_SIZE; + } + DEBUG_PRINT_ERROR("enable_extradata: actual[%x] requested[%x] enable[%d]", + client_extradata, requested_extradata, enable); + + if (enable) + requested_extradata |= client_extradata; + else + { + requested_extradata = client_extradata & ~requested_extradata; + extradata_size *= -1; + } + + driver_extradata = requested_extradata & DRIVER_EXTRADATA_MASK; + if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) + driver_extradata |= VDEC_EXTRADATA_MB_ERROR_MAP; // Required for conceal MB frame info +#ifdef PROCESS_EXTRADATA_IN_OUTPUT_PORT + if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + driver_extradata |= ((requested_extradata & OMX_FRAMEINFO_EXTRADATA)? + VDEC_EXTRADATA_SEI : 0); // Required for pan scan frame info + driver_extradata |= ((requested_extradata & OMX_TIMEINFO_EXTRADATA)? + VDEC_EXTRADATA_VUI | VDEC_EXTRADATA_SEI : 0); //Required for time info + } + +#endif + if (driver_extradata != drv_ctx.extradata) + { + client_extradata = requested_extradata; + drv_ctx.extradata = driver_extradata; + //ioctl_msg.in = &drv_ctx.extradata; + //ioctl_msg.out = NULL; + //if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_SET_EXTRADATA, + // (void*)&ioctl_msg) < 0) + //{ + // DEBUG_PRINT_ERROR("\nSet extradata failed"); + // ret = OMX_ErrorUnsupportedSetting; + //} // else + // ret = get_buffer_req(&drv_ctx.op_buf); + } + else if ((client_extradata & ~DRIVER_EXTRADATA_MASK) != (requested_extradata & ~DRIVER_EXTRADATA_MASK)) + { + client_extradata = requested_extradata; + drv_ctx.op_buf.buffer_size += extradata_size; + // align the buffer size + drv_ctx.op_buf.buffer_size = (drv_ctx.op_buf.buffer_size + drv_ctx.op_buf.alignment - 1)&(~(drv_ctx.op_buf.alignment - 1)); + DEBUG_PRINT_LOW("Aligned buffer size with exreadata = %d\n", drv_ctx.op_buf.buffer_size); + if (!(client_extradata & ~DRIVER_EXTRADATA_MASK)) // If no omx extradata is required remove space for terminator + drv_ctx.op_buf.buffer_size -= sizeof(OMX_OTHER_EXTRADATATYPE); + ret = set_buffer_req(&drv_ctx.op_buf); + } + return ret; +} + +OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra) +{ + OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0; + OMX_U8 *data_ptr = extra->data, data = 0; + while (byte_count < extra->nDataSize) + { + data = *data_ptr; + while (data) + { + num_MB += (data&0x01); + data >>= 1; + } + data_ptr++; + byte_count++; + } + num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) * + (drv_ctx.video_resolution.frame_height + 15)) >> 8; + return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0); +} + +void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra) +{ + if (!m_debug_extradata) + return; + + DEBUG_PRINT_HIGH( + "============== Extra Data ==============\n" + " Size: %u \n" + " Version: %u \n" + " PortIndex: %u \n" + " Type: %x \n" + " DataSize: %u \n", + extra->nSize, extra->nVersion.nVersion, + extra->nPortIndex, extra->eType, extra->nDataSize); + + if (extra->eType == OMX_ExtraDataInterlaceFormat) + { + OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)extra->data; + DEBUG_PRINT_HIGH( + "------ Interlace Format ------\n" + " Size: %u \n" + " Version: %u \n" + " PortIndex: %u \n" + " Is Interlace Format: %u \n" + " Interlace Formats: %u \n" + "=========== End of Interlace ===========\n", + intfmt->nSize, intfmt->nVersion.nVersion, intfmt->nPortIndex, + intfmt->bInterlaceFormat, intfmt->nInterlaceFormats); + } + else if (extra->eType == OMX_ExtraDataFrameInfo) + { + OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data; + + DEBUG_PRINT_HIGH( + "-------- Frame Format --------\n" + " Picture Type: %u \n" + " Interlace Type: %u \n" + " Pan Scan Total Frame Num: %u \n" + " Concealed Macro Blocks: %u \n" + " frame rate: %u \n" + " Aspect Ratio X: %u \n" + " Aspect Ratio Y: %u \n", + fminfo->ePicType, + fminfo->interlaceType, + fminfo->panScan.numWindows, + fminfo->nConcealedMacroblocks, + fminfo->nFrameRate, + fminfo->aspectRatio.aspectRatioX, + fminfo->aspectRatio.aspectRatioY); + + for (int i = 0; i < fminfo->panScan.numWindows; i++) + { + DEBUG_PRINT_HIGH( + "------------------------------\n" + " Pan Scan Frame Num: %d \n" + " Rectangle x: %d \n" + " Rectangle y: %d \n" + " Rectangle dx: %d \n" + " Rectangle dy: %d \n", + i, fminfo->panScan.window[i].x, fminfo->panScan.window[i].y, + fminfo->panScan.window[i].dx, fminfo->panScan.window[i].dy); + } + + DEBUG_PRINT_HIGH("========= End of Frame Format =========="); + } + else if (extra->eType == OMX_ExtraDataNone) + { + DEBUG_PRINT_HIGH("========== End of Terminator ==========="); + } + else + { + DEBUG_PRINT_HIGH("======= End of Driver Extradata ========"); + } +} + +void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra, + OMX_U32 interlaced_format_type) +{ + OMX_STREAMINTERLACEFORMAT *interlace_format; + OMX_U32 mbaff = 0; + extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE; + extra->nVersion.nVersion = OMX_SPEC_VERSION; + extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat; + extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT); + interlace_format = (OMX_STREAMINTERLACEFORMAT *)extra->data; + interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT); + interlace_format->nVersion.nVersion = OMX_SPEC_VERSION; + interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + mbaff = (h264_parser)? (h264_parser->is_mbaff()): false; + if ((interlaced_format_type == VDEC_InterlaceFrameProgressive) && !mbaff) + { + interlace_format->bInterlaceFormat = OMX_FALSE; + interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive; + drv_ctx.interlace = VDEC_InterlaceFrameProgressive; + } + else + { + interlace_format->bInterlaceFormat = OMX_TRUE; + interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst; + drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst; + } + print_debug_extradata(extra); +} + + +void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra, + OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_S64 timestamp, OMX_U32 frame_rate, + vdec_aspectratioinfo *aspect_ratio_info) +{ + OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL; + extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE; + extra->nVersion.nVersion = OMX_SPEC_VERSION; + extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo; + extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO); + frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)extra->data; + switch (picture_type) + { + case PICTURE_TYPE_I: + frame_info->ePicType = OMX_VIDEO_PictureTypeI; + break; + case PICTURE_TYPE_P: + frame_info->ePicType = OMX_VIDEO_PictureTypeP; + break; + case PICTURE_TYPE_B: + frame_info->ePicType = OMX_VIDEO_PictureTypeB; + break; + default: + frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0; + } + if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst) + frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; + else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst) + frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; + else + frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive; + memset(&frame_info->panScan,0,sizeof(frame_info->panScan)); + memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio)); + if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) + { + h264_parser->fill_pan_scan_data(&frame_info->panScan, timestamp); + h264_parser->fill_aspect_ratio_info(&frame_info->aspectRatio); + } + frame_info->nConcealedMacroblocks = num_conceal_mb; + frame_info->nFrameRate = frame_rate; + print_debug_extradata(extra); +} + +void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra) +{ + OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL; + extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE; + extra->nVersion.nVersion = OMX_SPEC_VERSION; + extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX; + extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef; + extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)extra->data; + *portDefn = m_port_def; + DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u stride = %u" + "sliceheight = %u \n",portDefn->format.video.nFrameHeight, + portDefn->format.video.nFrameWidth, + portDefn->format.video.nStride, + portDefn->format.video.nSliceHeight); +} + +void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra) +{ + extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE); + extra->nVersion.nVersion = OMX_SPEC_VERSION; + extra->eType = OMX_ExtraDataNone; + extra->nDataSize = 0; + extra->data[0] = 0; + + print_debug_extradata(extra); +} + +OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if (index >= drv_ctx.ip_buf.actualcount) + { + DEBUG_PRINT_ERROR("\nERROR:Desc Buffer Index not found"); + return OMX_ErrorInsufficientResources; + } + if (m_desc_buffer_ptr == NULL) + { + m_desc_buffer_ptr = (desc_buffer_hdr*) \ + calloc( (sizeof(desc_buffer_hdr)), + drv_ctx.ip_buf.actualcount); + if (m_desc_buffer_ptr == NULL) + { + DEBUG_PRINT_ERROR("\n m_desc_buffer_ptr Allocation failed "); + return OMX_ErrorInsufficientResources; + } + } + + m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8)); + if (m_desc_buffer_ptr[index].buf_addr == NULL) + { + DEBUG_PRINT_ERROR("\ndesc buffer Allocation failed "); + return OMX_ErrorInsufficientResources; + } + + return eRet; +} + +void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset) +{ + DEBUG_PRINT_LOW("Inserting address offset (%d) at idx (%d)", address_offset,m_demux_entries); + if (m_demux_entries < 8192) + { + m_demux_offsets[m_demux_entries++] = address_offset; + } + return; +} + +void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr) +{ + OMX_U32 bytes_to_parse = buf_hdr->nFilledLen; + OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset; + OMX_U32 index = 0; + + m_demux_entries = 0; + + while (index < bytes_to_parse) + { + if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) && + (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) || + ((buf[index] == 0x00) && (buf[index+1] == 0x00) && + (buf[index+2] == 0x01)) ) + { + //Found start code, insert address offset + insert_demux_addr_offset(index); + if (buf[index+2] == 0x01) // 3 byte start code + index += 3; + else //4 byte start code + index += 4; + } + else + index++; + } + DEBUG_PRINT_LOW("Extracted (%d) demux entry offsets",m_demux_entries); + return; +} + +OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr) +{ + //fix this, handle 3 byte start code, vc1 terminator entry + OMX_U8 *p_demux_data = NULL; + OMX_U32 desc_data = 0; + OMX_U32 start_addr = 0; + OMX_U32 nal_size = 0; + OMX_U32 suffix_byte = 0; + OMX_U32 demux_index = 0; + OMX_U32 buffer_index = 0; + + if (m_desc_buffer_ptr == NULL) + { + DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries."); + return OMX_ErrorBadParameter; + } + + buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); + if (buffer_index > drv_ctx.ip_buf.actualcount) + { + DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%d)", buffer_index); + return OMX_ErrorBadParameter; + } + + p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr; + + if ( ((OMX_U8*)p_demux_data == NULL) || + ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) + { + DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries."); + return OMX_ErrorBadParameter; + } + else + { + for (; demux_index < m_demux_entries; demux_index++) + { + desc_data = 0; + start_addr = m_demux_offsets[demux_index]; + if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) + { + suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3]; + } + else + { + suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4]; + } + if (demux_index < (m_demux_entries - 1)) + { + nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2; + } + else + { + nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2; + } + DEBUG_PRINT_LOW("Start_addr(%p), suffix_byte(0x%x),nal_size(%d),demux_index(%d)", + start_addr, + suffix_byte, + nal_size, + demux_index); + desc_data = (start_addr >> 3) << 1; + desc_data |= (start_addr & 7) << 21; + desc_data |= suffix_byte << 24; + + memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); + memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32)); + memset(p_demux_data + 8, 0, sizeof(OMX_U32)); + memset(p_demux_data + 12, 0, sizeof(OMX_U32)); + + p_demux_data += 16; + } + if (codec_type_parse == CODEC_TYPE_VC1) + { + DEBUG_PRINT_LOW("VC1 terminator entry"); + desc_data = 0; + desc_data = 0x82 << 24; + memcpy(p_demux_data, &desc_data, sizeof(OMX_U32)); + memset(p_demux_data + 4, 0, sizeof(OMX_U32)); + memset(p_demux_data + 8, 0, sizeof(OMX_U32)); + memset(p_demux_data + 12, 0, sizeof(OMX_U32)); + p_demux_data += 16; + m_demux_entries++; + } + //Add zero word to indicate end of descriptors + memset(p_demux_data, 0, sizeof(OMX_U32)); + + m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32); + DEBUG_PRINT_LOW("desc table data size=%d", m_desc_buffer_ptr[buffer_index].desc_data_size); + } + memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); + m_demux_entries = 0; + DEBUG_PRINT_LOW("Demux table complete!"); + return OMX_ErrorNone; +} + +#if 0 +OMX_ERRORTYPE omx_vdec::createDivxDrmContext( OMX_PTR drmHandle ) +{ + OMX_ERRORTYPE err = OMX_ErrorNone; + if( drmHandle == NULL ) { + DEBUG_PRINT_HIGH("\n This clip is not DRM encrypted"); + iDivXDrmDecrypt = NULL; + return err; + } + + iDivXDrmDecrypt = DivXDrmDecrypt::Create( drmHandle ); + if (iDivXDrmDecrypt) { + DEBUG_PRINT_LOW("\nCreated DIVX DRM, now calling Init"); + OMX_ERRORTYPE err = iDivXDrmDecrypt->Init(); + if(err!=OMX_ErrorNone) { + DEBUG_PRINT_ERROR("\nERROR:iDivXDrmDecrypt->Init %d", err); + delete iDivXDrmDecrypt; + iDivXDrmDecrypt = NULL; + } + } + else { + DEBUG_PRINT_ERROR("\nUnable to Create DIVX DRM"); + return OMX_ErrorUndefined; + } + return err; +} +#endif + diff --git a/mm-video/vidc/vdec/src/queue.c b/mm-video/vidc/vdec/src/queue.c new file mode 100755 index 0000000..e0aeb9a --- /dev/null +++ b/mm-video/vidc/vdec/src/queue.c @@ -0,0 +1,128 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/* + Queue with Linked list +*/ + +#include "queue.h" +#include +#include + + +typedef struct Node +{ + void *element; + struct Node *next; +} Node; + +struct Queue +{ + Node *head; + Node *tail; + int current_size; +}; + +Queue *alloc_queue() +{ + Queue *q = (Queue *) malloc(sizeof(Queue)); + if (q) + { + q->head = q->tail = NULL; + q->current_size = 0; + } + return q; +} + +void free_queue(Queue *q) +{ + while (q->current_size) + { + pop(q); + } +} + +void free_queue_and_qelement(Queue *q) +{ + while (q->current_size) + { + void *element = pop(q); + if (element) + free(element); + } +} + +int push(Queue *q, void * element) +{ + Node *new_node = (Node *) malloc(sizeof(Node)); + + if (new_node == NULL) + return -1; + + new_node->element = element; + new_node->next = NULL; + + if (q->current_size == 0) + { + q->head = new_node; + } + else + { + q->tail->next = new_node; + } + + q->tail = new_node; + q->current_size++; + + return 0; +} + +void *pop(Queue *q) +{ + Node *temp; + void *element; + + if (q->current_size == 0) + return NULL; + + temp = q->head; + element = temp->element; + + if (q->current_size == 1) + { + q->head = q->tail = NULL; + } + else + { + q->head = q->head->next; + } + + free(temp); + q->current_size--; + return element; +} + diff --git a/mm-video/vidc/vdec/src/ts_parser.cpp b/mm-video/vidc/vdec/src/ts_parser.cpp new file mode 100644 index 0000000..4298058 --- /dev/null +++ b/mm-video/vidc/vdec/src/ts_parser.cpp @@ -0,0 +1,253 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include "ts_parser.h" + +#define DEBUG ALOGE +void omx_time_stamp_reorder::set_timestamp_reorder_mode(bool mode) +{ + reorder_ts = mode; +} + +void omx_time_stamp_reorder::enable_debug_print(bool flag) +{ + print_debug = flag; +} + +omx_time_stamp_reorder::~omx_time_stamp_reorder() +{ + delete_list(); +} + +omx_time_stamp_reorder::omx_time_stamp_reorder() +{ + reorder_ts = false; + phead = pcurrent = NULL; + error = false; + print_debug = false; +} + +void omx_time_stamp_reorder::delete_list() +{ + time_stamp_list *ptemp; + if (!phead) return; + while(phead->next != phead) { + ptemp = phead; + phead = phead->next; + phead->prev = ptemp->prev; + ptemp->prev->next = phead; + delete ptemp; + } + delete phead; + phead = NULL; +} + +bool omx_time_stamp_reorder::get_current_list() +{ + if (!phead) { + if(!add_new_list()) { + handle_error(); + return false; + } + } + pcurrent = phead->prev; + return true; +} + +bool omx_time_stamp_reorder::update_head() +{ + time_stamp_list *ptemp; + if(!phead) return false; + if (phead->next != phead) { + ptemp = phead; + phead = ptemp->next; + phead->prev = ptemp->prev; + ptemp->prev->next = phead; + delete ptemp; + } + return true; +} + +bool omx_time_stamp_reorder::add_new_list() +{ + bool status = true; + time_stamp_list *ptemp = NULL; + if (!phead) { + ptemp = phead = new time_stamp_list; + if (!phead) { + handle_error(); + status = false; + return status; + } + phead->prev = phead->next = phead; + } else { + ptemp = new time_stamp_list; + if (!ptemp) { + handle_error(); + status = false; + return status; + } + ptemp->prev = phead->prev; + ptemp->next = phead; + phead->prev->next = ptemp; + phead->prev = ptemp; + } + ptemp->entries_filled = 0; + for(int i=0; i < TIME_SZ; i++) { + ptemp->input_timestamps[i].in_use = false; + ptemp->input_timestamps[i].timestamps = -1; + } + return status; +} + +bool omx_time_stamp_reorder::insert_timestamp(OMX_BUFFERHEADERTYPE *header) +{ + OMX_TICKS *table_entry = NULL; + if (!reorder_ts || error || !header) { + if (error || !header) + DEBUG("\n Invalid condition in insert_timestamp %p", header); + return false; + } + if(!get_current_list()) { + handle_error(); + return false; + } + if (pcurrent->entries_filled > (TIME_SZ - 1)) { + DEBUG("\n Table full return error"); + handle_error(); + return false; + } + if (header->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + return true; + } + if ((header->nFlags & OMX_BUFFERFLAG_EOS) && !header->nFilledLen) + { + DEBUG("\n EOS with zero length recieved"); + if (!add_new_list()) { + handle_error(); + return false; + } + return true; + } + for(int i = 0; i < TIME_SZ && !table_entry; i++) { + if (!pcurrent->input_timestamps[i].in_use) { + table_entry = &pcurrent->input_timestamps[i].timestamps; + pcurrent->input_timestamps[i].in_use = true; + pcurrent->entries_filled++; + } + } + if (!table_entry) { + DEBUG("\n All entries in use"); + handle_error(); + return false; + } + *table_entry = header->nTimeStamp; + if (print_debug) + DEBUG("Time stamp inserted %lld", header->nTimeStamp); + if (header->nFlags & OMX_BUFFERFLAG_EOS) { + if (!add_new_list()) { + handle_error(); + return false; + } + } + return true; +} + +bool omx_time_stamp_reorder::remove_time_stamp(OMX_TICKS ts, bool is_interlaced = false) +{ + unsigned int num_ent_remove = (is_interlaced)?2:1; + if (!reorder_ts || error) { + DEBUG("\n not in avi mode"); + return false; + } + if (!phead || !phead->entries_filled) return false; + for(int i=0; i < TIME_SZ && num_ent_remove; i++) { + if (phead->input_timestamps[i].in_use && phead->input_timestamps[i].timestamps == ts) { + phead->input_timestamps[i].in_use = false; + phead->entries_filled--; + num_ent_remove--; + if (print_debug) + DEBUG("Removed TS %lld", ts); + } + } + if (!phead->entries_filled) { + if (!update_head()) { + handle_error(); + return false; + } + } + return true; +} + +void omx_time_stamp_reorder::flush_timestamp() +{ + delete_list(); +} + +bool omx_time_stamp_reorder::get_next_timestamp(OMX_BUFFERHEADERTYPE *header, bool is_interlaced) +{ + timestamp *element = NULL,*duplicate = NULL; + bool status = false; + if (!reorder_ts || error || !header) { + if (error || !header) + DEBUG("\n Invalid condition in insert_timestamp %p", header); + return false; + } + if(!phead || !phead->entries_filled) return false; + for(int i=0; i < TIME_SZ; i++) { + if (phead->input_timestamps[i].in_use) { + status = true; + if (!element) + element = &phead->input_timestamps[i]; + else { + if (element->timestamps > phead->input_timestamps[i].timestamps){ + element = &phead->input_timestamps[i]; + duplicate = NULL; + } else if(element->timestamps == phead->input_timestamps[i].timestamps) + duplicate = &phead->input_timestamps[i]; + } + } + } + if (element) { + phead->entries_filled--; + header->nTimeStamp = element->timestamps; + if (print_debug) + DEBUG("Getnext Time stamp %lld", header->nTimeStamp); + element->in_use = false; + } + if(is_interlaced && duplicate) { + phead->entries_filled--; + duplicate->in_use = false; + } + if (!phead->entries_filled) { + if (!update_head()) { + handle_error(); + return false; + } + } + return status; +} diff --git a/mm-video/vidc/vdec/test/decoder_driver_test.c b/mm-video/vidc/vdec/test/decoder_driver_test.c new file mode 100755 index 0000000..3c947d1 --- /dev/null +++ b/mm-video/vidc/vdec/test/decoder_driver_test.c @@ -0,0 +1,1198 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include "decoder_driver_test.h" + +#define DEBUG_PRINT printf +/************************************************************************/ +/* #DEFINES */ +/************************************************************************/ + +#define VOP_START_CODE 0x000001B6 +#define SHORT_HEADER_START_CODE 0x00008000 +#define H264_START_CODE 0x00000001 + +/************************************************************************/ +/* STATIC VARIABLES */ +/************************************************************************/ + +static int Code_type; +static int total_frames = 0; +static unsigned int header_code = 0; +static pthread_mutex_t read_lock; + +static unsigned int read_frame ( unsigned char *dataptr,unsigned int length, + FILE * inputBufferFile + ); +static int Read_Buffer_From_DAT_File( unsigned char *dataptr, unsigned int length, + FILE * inputBufferFile + ); + +static unsigned clp2(unsigned x) +{ + x = x - 1; + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >>16); + return x + 1; +} + +static void* video_thread (void *); +static void* async_thread (void *); + +int main (int argc, char **argv) +{ + struct video_decoder_context *decoder_context = NULL; + char *file_name = NULL; + FILE *file_ptr = NULL; + int temp1 =0,temp2 =0; + int error = 1; + unsigned int i = 0; + + file_name = argv [1]; + file_ptr = fopen (file_name,"rb"); + + if (file_ptr == NULL) + { + DEBUG_PRINT("\n File is not located "); + return -1; + } + + + decoder_context = (struct video_decoder_context *) \ + calloc (sizeof (struct video_decoder_context),1); + if (decoder_context == NULL) + { + return -1; + } + decoder_context->outputBufferFile = NULL; + decoder_context->inputBufferFile = NULL; + decoder_context->video_driver_fd = -1; + decoder_context->inputBufferFile = file_ptr; + + file_ptr = fopen ("/data/output.yuv","wb"); + if (file_ptr == NULL) + { + DEBUG_PRINT("\n File can't be created"); + free (decoder_context); + return -1; + } + decoder_context->outputBufferFile = file_ptr; + + switch (atoi(argv[2])) + { + case 0: + DEBUG_PRINT("\n MPEG4 codec selected"); + decoder_context->decoder_format = VDEC_CODECTYPE_MPEG4; + Code_type = 0; + break; + case 1: + DEBUG_PRINT("\n H.263"); + decoder_context->decoder_format = VDEC_CODECTYPE_H263; + Code_type = 0; + break; + case 2: + DEBUG_PRINT("\n H.264"); + decoder_context->decoder_format = VDEC_CODECTYPE_H264; + Code_type = 1; + break; + default: + DEBUG_PRINT("\n Wrong codec type"); + error = -1; + break; + } + + if (error != -1) + { + temp1 = atoi(argv[3]); + temp2 = atoi(argv[4]); + + if (((temp1%16) != 0) || ((temp2%16) != 0)) + { + error = -1; + } + else + { + decoder_context->video_resoultion.frame_height = temp1; + decoder_context->video_resoultion.frame_width = temp2; + } + } + + switch (atoi(argv[5])) + { + case 0: + DEBUG_PRINT("\n No Sink"); + decoder_context->outputBufferFile = NULL; + break; + } + + if ( error != -1 && (init_decoder (decoder_context) == -1 )) + { + DEBUG_PRINT("\n Init decoder fails "); + error = -1; + } + DEBUG_PRINT("\n Decoder open successfull"); + + + /*Allocate input and output buffers*/ + if (error != -1 && (allocate_buffer (VDEC_BUFFER_TYPE_INPUT, + decoder_context)== -1)) + { + DEBUG_PRINT("\n Error in input Buffer allocation"); + error = -1; + } + + if (error != -1 && (allocate_buffer (VDEC_BUFFER_TYPE_OUTPUT, + decoder_context)== -1)) + { + DEBUG_PRINT("\n Error in output Buffer allocation"); + error = -1; + } + + + if (error != -1 && (start_decoding (decoder_context) == -1)) + { + DEBUG_PRINT("\n Error in start decoding call"); + error = -1; + } + + if (error != -1 && (stop_decoding (decoder_context) == -1)) + { + DEBUG_PRINT("\n Error in stop decoding call"); + error = -1; + } + + DEBUG_PRINT("\n De-init the decoder"); + if ((deinit_decoder (decoder_context) == -1)) + { + error = -1; + } + + + (void)free_buffer (VDEC_BUFFER_TYPE_INPUT,decoder_context); + (void)free_buffer (VDEC_BUFFER_TYPE_OUTPUT,decoder_context); + + if (decoder_context->inputBufferFile != NULL) + { + fclose (decoder_context->inputBufferFile); + } + if (decoder_context->outputBufferFile != NULL) + { + fclose (decoder_context->outputBufferFile); + } + DEBUG_PRINT ("\n Total Number of frames decoded %d",total_frames); + DEBUG_PRINT("\n closing the driver"); + free (decoder_context); + + return error; +} + +int init_decoder ( struct video_decoder_context *init_decode ) +{ + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct video_queue_context *queue_ptr = NULL; +#ifdef MAX_RES_720P + enum vdec_output_fromat output_format = VDEC_YUV_FORMAT_NV12; +#endif +#ifdef MAX_RES_1080P + enum vdec_output_fromat output_format = VDEC_YUV_FORMAT_TILE_4x2; +#endif + + pthread_mutexattr_t init_values; + + DEBUG_PRINT("\n Before calling the open"); + + init_decode->video_driver_fd = open ("/dev/msm_vidc_dec", \ + O_RDWR | O_NONBLOCK); + + + + if (init_decode->video_driver_fd < 0) + { + DEBUG_PRINT("\n Open failed"); + return -1; + } + + + /*Initialize Decoder with codec type and resolution*/ + ioctl_msg.in = &init_decode->decoder_format; + ioctl_msg.out = NULL; + + if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_CODEC, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Set codec type failed"); + return -1; + } + + /*Set the output format*/ + ioctl_msg.in = &output_format; + ioctl_msg.out = NULL; + + if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_OUTPUT_FORMAT, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Set output format failed"); + return -1; + } + + ioctl_msg.in = &init_decode->video_resoultion; + ioctl_msg.out = NULL; + + if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_PICRES, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Set Resolution failed"); + return -1; + } + DEBUG_PRINT("\n After Set Resolution"); + + DEBUG_PRINT("\n Query Input bufffer requirements"); + /*Get the Buffer requirements for input and output ports*/ + + init_decode->input_buffer.buffer_type = VDEC_BUFFER_TYPE_INPUT; + ioctl_msg.in = NULL; + ioctl_msg.out = &init_decode->input_buffer; + + if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_GET_BUFFER_REQ, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Requesting for input buffer requirements failed"); + return -1; + } + + DEBUG_PRINT("\n input Size=%d min count =%d actual count = %d", \ + init_decode->input_buffer.buffer_size,\ + init_decode->input_buffer.mincount,\ + init_decode->input_buffer.actualcount); + + + init_decode->input_buffer.buffer_type = VDEC_BUFFER_TYPE_INPUT; + ioctl_msg.in = &init_decode->input_buffer; + ioctl_msg.out = NULL; + init_decode->input_buffer.actualcount = init_decode->input_buffer.mincount + 2; + + if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_BUFFER_REQ, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Set Buffer Requirements Failed"); + return -1; + } + + + DEBUG_PRINT("\n Query output bufffer requirements"); + init_decode->output_buffer.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + ioctl_msg.in = NULL; + ioctl_msg.out = &init_decode->output_buffer; + + if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_GET_BUFFER_REQ, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Requesting for output buffer requirements failed"); + return -1; + } + + DEBUG_PRINT("\n output Size=%d min count =%d actual count = %d", \ + init_decode->output_buffer.buffer_size,\ + init_decode->output_buffer.mincount,\ + init_decode->output_buffer.actualcount); + + /*Create Queue related data structures*/ + queue_ptr = &init_decode->queue_context; + queue_ptr->commandq_size = 50; + queue_ptr->dataq_size = 50; + + sem_init(&queue_ptr->sem_message,0, 0); + sem_init(&init_decode->sem_synchronize,0, 0); + + pthread_mutexattr_init (&init_values); + pthread_mutex_init (&queue_ptr->mutex,&init_values); + pthread_mutex_init (&read_lock,&init_values); + DEBUG_PRINT("\n create Queues"); + queue_ptr->ptr_cmdq = (struct video_msgq*) \ + calloc (sizeof (struct video_msgq), + queue_ptr->commandq_size); + queue_ptr->ptr_dataq = (struct video_msgq*) \ + calloc (sizeof (struct video_msgq), + queue_ptr->dataq_size + ); + + if ( queue_ptr->ptr_cmdq == NULL || + queue_ptr->ptr_dataq == NULL + ) + { + return -1; + } + DEBUG_PRINT("\n create Threads"); + /*Create two threads*/ + if ( (pthread_create (&init_decode->videothread_id,NULL,video_thread, + init_decode) < 0) || + (pthread_create (&init_decode->asyncthread_id,NULL,async_thread, + init_decode) < 0) + ) + { + return -1; + } + + return 1; +} + + + +int free_buffer ( enum vdec_buffer buffer_dir, + struct video_decoder_context *decode_context + ) +{ + unsigned int buffercount = 0,i=0; + struct vdec_bufferpayload **ptemp = NULL; + + if (decode_context == NULL) + { + return -1; + } + + if (buffer_dir == VDEC_BUFFER_TYPE_INPUT && decode_context->ptr_inputbuffer) + { + buffercount = decode_context->input_buffer.actualcount; + ptemp = decode_context->ptr_inputbuffer; + + for (i=0;ipmem_fd != -1) + { + munmap ( ptemp [i]->bufferaddr,ptemp [i]->mmaped_size); + ptemp [i]->bufferaddr = NULL; + close (ptemp [i]->pmem_fd); + } + free (ptemp [i]); + ptemp [i] = NULL; + } + } + free (decode_context->ptr_inputbuffer); + decode_context->ptr_inputbuffer = NULL; + } + else if ( buffer_dir == VDEC_BUFFER_TYPE_OUTPUT ) + { + buffercount = decode_context->output_buffer.actualcount; + ptemp = decode_context->ptr_outputbuffer; + + if (decode_context->ptr_respbuffer) + { + for (i=0;iptr_respbuffer [i]) + { + free (decode_context->ptr_respbuffer[i]); + decode_context->ptr_respbuffer [i] = NULL; + } + } + free (decode_context->ptr_respbuffer); + decode_context->ptr_respbuffer = NULL; + } + + if (ptemp) + { + for (i=0;ipmem_fd != -1) + { + munmap ( ptemp [i]->bufferaddr,ptemp [i]->mmaped_size); + ptemp [i]->bufferaddr = NULL; + close (ptemp [i]->pmem_fd); + } + free (ptemp [i]); + ptemp [i] = NULL; + } + } + free (ptemp); + decode_context->ptr_outputbuffer = NULL; + } + } + + return 1; +} + +int allocate_buffer ( enum vdec_buffer buffer_dir, + struct video_decoder_context *decode_context + ) +{ + struct vdec_setbuffer_cmd setbuffers; + struct vdec_bufferpayload **ptemp = NULL; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + unsigned int buffercount = 0,i=0,alignedsize=0; + unsigned int buffersize = 0; + + if ( decode_context == NULL) + { + DEBUG_PRINT ("\nallocate_buffer: context is NULL"); + return -1; + } + + if ( buffer_dir == VDEC_BUFFER_TYPE_INPUT ) + { + /*Check if buffers are allocated*/ + if (decode_context->ptr_inputbuffer != NULL) + { + DEBUG_PRINT ("\nallocate_buffer: decode_context->ptr_inputbuffer is set"); + return -1; + } + + buffercount = decode_context->input_buffer.actualcount; + alignedsize = decode_context->input_buffer.alignment; + buffersize = decode_context->input_buffer.buffer_size; + buffersize = (buffersize + alignedsize) & (~alignedsize); + } + else if (buffer_dir == VDEC_BUFFER_TYPE_OUTPUT) + { + /*Check if buffers are allocated*/ + if (decode_context->ptr_outputbuffer != NULL) + { + DEBUG_PRINT ("\nallocate_buffer: Double allcoate output"); + return -1; + } + + buffercount = decode_context->output_buffer.actualcount; + alignedsize = decode_context->output_buffer.alignment; + buffersize = decode_context->output_buffer.buffer_size; + buffersize = (buffersize + alignedsize) & (~alignedsize); + + decode_context->ptr_respbuffer = (struct vdec_output_frameinfo **)\ + calloc (sizeof (struct vdec_output_frameinfo *),buffercount); + + if (decode_context->ptr_respbuffer == NULL) + { + DEBUG_PRINT ("\n Allocate failure ptr_respbuffer"); + return -1; + } + + for (i=0; i< buffercount; i++) + { + decode_context->ptr_respbuffer [i] = (struct vdec_output_frameinfo *)\ + calloc (sizeof (struct vdec_output_frameinfo),buffercount); + if (decode_context->ptr_respbuffer [i] == NULL) + { + DEBUG_PRINT ("\nfailed to allocate vdec_output_frameinfo"); + return -1; + } + } + } + else + { + DEBUG_PRINT ("\nallocate_buffer: Wrong buffer directions"); + return -1; + } + + ptemp = (struct vdec_bufferpayload **)\ + calloc (sizeof (struct vdec_bufferpayload *),buffercount); + + if (ptemp == NULL) + { + DEBUG_PRINT ("\nallocate_buffer: vdec_bufferpayload failure"); + return -1; + } + + + if (buffer_dir == VDEC_BUFFER_TYPE_OUTPUT) + { + DEBUG_PRINT ("\nallocate_buffer: OUT"); + decode_context->ptr_outputbuffer = ptemp; + } + else + { + DEBUG_PRINT ("\nallocate_buffer: IN"); + decode_context->ptr_inputbuffer = ptemp; + } + + /*Allocate buffer headers*/ + for (i=0; i< buffercount; i++) + { + ptemp [i] = (struct vdec_bufferpayload*)\ + calloc (sizeof (struct vdec_bufferpayload),1); + + if (ptemp [i] == NULL) + { + DEBUG_PRINT ("\nallocate_buffer: ptemp [i] calloc failure"); + return -1; + } + + if (buffer_dir == VDEC_BUFFER_TYPE_OUTPUT) + { + decode_context->ptr_respbuffer [i]->client_data = \ + (void *) ptemp [i]; + } + ptemp [i]->pmem_fd = -1; + + } + + for (i=0; i< buffercount; i++) + { + ptemp [i]->pmem_fd = open ("/dev/pmem_adsp",O_RDWR); + + if (ptemp [i]->pmem_fd < 0) + { + DEBUG_PRINT ("\nallocate_buffer: open pmem_adsp failed"); + return -1; + } + + ptemp [i]->bufferaddr = mmap(NULL,clp2(buffersize),PROT_READ|PROT_WRITE, + MAP_SHARED,ptemp [i]->pmem_fd,0); + DEBUG_PRINT ("\n pmem fd = %d virt addr = %p",ptemp [i]->pmem_fd,\ + ptemp [i]->bufferaddr); + if (ptemp [i]->bufferaddr == MAP_FAILED) + { + ptemp [i]->bufferaddr = NULL; + DEBUG_PRINT ("\nallocate_buffer: MMAP failed"); + return -1; + } + ptemp [i]->buffer_len = buffersize; + ptemp [i]->mmaped_size = clp2 (buffersize); + + setbuffers.buffer_type = buffer_dir; + memcpy (&setbuffers.buffer,ptemp [i],sizeof (struct vdec_bufferpayload)); + + ioctl_msg.in = &setbuffers; + ioctl_msg.out = NULL; + + if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_SET_BUFFER, + &ioctl_msg) < 0) + { + DEBUG_PRINT ("\nallocate_buffer: Set Buffer IOCTL failed"); + return -1; + } + + } + DEBUG_PRINT ("\nallocate_buffer: Success"); + return 1; +} + + + +int start_decoding (struct video_decoder_context *decode_context) +{ + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct vdec_input_frameinfo frameinfo; + struct vdec_fillbuffer_cmd fillbuffer; + unsigned int i = 0; + unsigned int data_len =0; + + memset ((unsigned char*)&frameinfo,0,sizeof (struct vdec_input_frameinfo)); + memset ((unsigned char*)&fillbuffer,0,sizeof (struct vdec_fillbuffer_cmd)); + + if (decode_context == NULL) + { + return -1; + } + + if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_CMD_START, + NULL) < 0) + { + DEBUG_PRINT("\n Start failed"); + return -1; + } + + DEBUG_PRINT("\n Start Issued successfully waiting for Start Done"); + /*Wait for Start command response*/ + sem_wait (&decode_context->sem_synchronize); + + /*Push output Buffers*/ + i = 0; + while (i < decode_context->output_buffer.mincount) + { + fillbuffer.buffer.buffer_len = + decode_context->ptr_outputbuffer [i]->buffer_len; + fillbuffer.buffer.bufferaddr = + decode_context->ptr_outputbuffer [i]->bufferaddr; + fillbuffer.buffer.offset = + decode_context->ptr_outputbuffer [i]->offset; + fillbuffer.buffer.pmem_fd = + decode_context->ptr_outputbuffer [i]->pmem_fd; + fillbuffer.client_data = (void *)decode_context->ptr_respbuffer [i]; + DEBUG_PRINT ("\n Client Data on output = %p",fillbuffer.client_data); + ioctl_msg.in = &fillbuffer; + ioctl_msg.out = NULL; + + if (ioctl (decode_context->video_driver_fd, + VDEC_IOCTL_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Decoder frame failed"); + return -1; + } + i++; + } + + + /*push input buffers*/ + i = 0; + while (i < decode_context->input_buffer.mincount) + { + DEBUG_PRINT("\n Read Frame from File"); + data_len = read_frame ( decode_context->ptr_inputbuffer [i]->bufferaddr, + decode_context->ptr_inputbuffer [i]->buffer_len, + decode_context->inputBufferFile); + if (data_len == 0) + { + DEBUG_PRINT("\n Length is zero error"); + return -1; + } + DEBUG_PRINT("\n Read Frame from File szie = %u",data_len); + frameinfo.bufferaddr = + decode_context->ptr_inputbuffer [i]->bufferaddr; + frameinfo.offset = 0; + frameinfo.pmem_fd = decode_context->ptr_inputbuffer [i]->pmem_fd; + frameinfo.pmem_offset = decode_context->ptr_inputbuffer [i]->offset; + frameinfo.datalen = data_len; + frameinfo.client_data = (struct vdec_bufferpayload *)\ + decode_context->ptr_inputbuffer [i]; + /*TODO: Time stamp needs to be updated*/ + ioctl_msg.in = &frameinfo; + ioctl_msg.out = NULL; + + if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_DECODE_FRAME, + &ioctl_msg) < 0) + { + DEBUG_PRINT("\n Decoder frame failed"); + return -1; + } + total_frames++; + i++; + } + DEBUG_PRINT ("\n Wait for EOS"); + /*Wait for EOS or Error condition*/ + sem_wait (&decode_context->sem_synchronize); + DEBUG_PRINT ("\n Reached EOS"); + + return 1; +} + +int stop_decoding (struct video_decoder_context *decode_context) +{ + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + enum vdec_bufferflush flush_dir = VDEC_FLUSH_TYPE_INPUT; + + if (decode_context == NULL) + { + return -1; + } + + ioctl_msg.in = &flush_dir; + ioctl_msg.out = NULL; + + if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_CMD_FLUSH, + &ioctl_msg) < 0) + { + DEBUG_PRINT("\n Flush input failed"); + } + else + { + sem_wait (&decode_context->sem_synchronize); + } + + flush_dir = VDEC_FLUSH_TYPE_OUTPUT; + ioctl_msg.in = &flush_dir; + ioctl_msg.out = NULL; + + if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_CMD_FLUSH, + &ioctl_msg) < 0) + { + DEBUG_PRINT("\n Flush output failed"); + } + else + { + sem_wait (&decode_context->sem_synchronize); + } + + DEBUG_PRINT("\n Stop VDEC_IOCTL_CMD_STOP"); + if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_CMD_STOP, + NULL) < 0) + { + DEBUG_PRINT("\n Stop failed"); + } + else + { + sem_wait (&decode_context->sem_synchronize); + } + return 1; +} + +int deinit_decoder (struct video_decoder_context *init_decode) +{ + if (init_decode == NULL) + { + return -1; + } + + /*Close the driver*/ + if (init_decode->video_driver_fd != -1) + { + close (init_decode->video_driver_fd); + } + + if (init_decode->queue_context.ptr_cmdq) + { + free (init_decode->queue_context.ptr_cmdq); + init_decode->queue_context.ptr_cmdq = NULL; + } + + if (init_decode->queue_context.ptr_dataq) + { + free (init_decode->queue_context.ptr_dataq); + init_decode->queue_context.ptr_dataq = NULL; + } + + sem_destroy (&init_decode->queue_context.sem_message); + sem_destroy (&init_decode->sem_synchronize); + + pthread_mutex_destroy(&init_decode->queue_context.mutex); + pthread_mutex_destroy (&read_lock); + + return 1; +} + +static void* video_thread (void *context) +{ + struct video_decoder_context *decode_context = NULL; + struct video_msgq *queueitem = NULL; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct vdec_input_frameinfo frameinfo; + struct vdec_fillbuffer_cmd fillbuffer; + struct vdec_output_frameinfo *outputbuffer = NULL; + struct vdec_bufferpayload *tempbuffer = NULL; + unsigned int data_len =0; + + + if (context == NULL) + { + DEBUG_PRINT("\n video thread recieved NULL context"); + return NULL; + } + decode_context = (struct video_decoder_context *) context; + + /* Thread function which will accept commands from async thread + * or main thread + */ + while (1) + { + queueitem = queue_get_cmd (&decode_context ->queue_context); + if (queueitem != NULL) + { + switch (queueitem->cmd) + { + case VDEC_MSG_EVT_HW_ERROR: + DEBUG_PRINT("\n FATAL ERROR "); + break; + case VDEC_MSG_RESP_INPUT_FLUSHED: + DEBUG_PRINT("\n Input Buffer Flushed"); + break; + case VDEC_MSG_RESP_OUTPUT_FLUSHED: + DEBUG_PRINT("\n Output buffer Flushed"); + break; + case VDEC_MSG_RESP_START_DONE: + DEBUG_PRINT("\n recived start done command"); + sem_post (&decode_context->sem_synchronize); + break; + + case VDEC_MSG_RESP_STOP_DONE: + DEBUG_PRINT("\n recieved stop done"); + sem_post (&decode_context->sem_synchronize); + break; + + case VDEC_MSG_RESP_INPUT_BUFFER_DONE: + + tempbuffer = (struct vdec_bufferpayload *)queueitem->clientdata; + if (tempbuffer == NULL) + { + DEBUG_PRINT("\n FATAL ERROR input buffer address is bad"); + sem_post (&decode_context->sem_synchronize); + break; + } + data_len = read_frame ( tempbuffer->bufferaddr, + tempbuffer->buffer_len, + decode_context->inputBufferFile + ); + + if (data_len == 0) + { + DEBUG_PRINT ("\n End of stream reached"); + sem_post (&decode_context->sem_synchronize); + break; + } + + frameinfo.bufferaddr = tempbuffer->bufferaddr; + frameinfo.offset = 0; + frameinfo.pmem_fd = tempbuffer->pmem_fd; + frameinfo.pmem_offset = tempbuffer->offset; + frameinfo.datalen = data_len; + frameinfo.client_data = (struct vdec_bufferpayload *)\ + tempbuffer; + /*TODO: Time stamp needs to be updated*/ + ioctl_msg.in = &frameinfo; + ioctl_msg.out = NULL; + total_frames++; + if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_DECODE_FRAME, + &ioctl_msg) < 0) + { + DEBUG_PRINT("\n Decoder frame failed"); + sem_post (&decode_context->sem_synchronize); + } + DEBUG_PRINT("\n Input buffer done send next buffer current value = %d",\ + total_frames); + break; + + case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: + + outputbuffer = (struct vdec_output_frameinfo *)\ + queueitem->clientdata; + DEBUG_PRINT("\n Value of client Data in VT %p",queueitem->clientdata); + if (outputbuffer == NULL || outputbuffer->bufferaddr == NULL || + outputbuffer->client_data == NULL + ) + { + DEBUG_PRINT("\n FATAL ERROR output buffer is bad"); + DEBUG_PRINT("\nValues outputbuffer = %p",outputbuffer); + if (outputbuffer != NULL) + { + DEBUG_PRINT("\nValues outputbuffer->bufferaddr = %p",\ + outputbuffer->bufferaddr); + DEBUG_PRINT("\nValues outputbuffer->client_data = %p",\ + outputbuffer->client_data); + } + sem_post (&decode_context->sem_synchronize); + break; + } + + + if (outputbuffer->len == 0) + { + DEBUG_PRINT("\n Filled Length is zero Close decoding"); + sem_post (&decode_context->sem_synchronize); + break; + } + + if (decode_context->outputBufferFile != NULL) + { + fwrite (outputbuffer->bufferaddr,1,outputbuffer->len, + decode_context->outputBufferFile); + } + + tempbuffer = (struct vdec_bufferpayload *)\ + outputbuffer->client_data; + + DEBUG_PRINT("\n recieved output buffer consume outbuffer"); + DEBUG_PRINT("\nValues outputbuffer->bufferaddr = %p",\ + outputbuffer->bufferaddr); + DEBUG_PRINT ("\n Vir address of allocated buffer %p",\ + tempbuffer->bufferaddr); + fillbuffer.buffer.buffer_len = tempbuffer->buffer_len; + fillbuffer.buffer.bufferaddr = tempbuffer->bufferaddr; + fillbuffer.buffer.offset = tempbuffer->offset; + fillbuffer.buffer.pmem_fd = tempbuffer->pmem_fd; + fillbuffer.client_data = (void *)outputbuffer; + + ioctl_msg.in = &fillbuffer; + ioctl_msg.out = NULL; + + if (ioctl (decode_context->video_driver_fd, + VDEC_IOCTL_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Decoder frame failed"); + return NULL; + } + + break; + + case VDEC_MSG_RESP_FLUSH_INPUT_DONE: + DEBUG_PRINT("\n Flush input complete"); + sem_post (&decode_context->sem_synchronize); + break; + + case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE: + DEBUG_PRINT("\n Flush output complete"); + sem_post (&decode_context->sem_synchronize); + break; + } + + if (queueitem->cmd == VDEC_MSG_RESP_STOP_DONE) + { + DEBUG_PRINT("\n Playback has ended thread will exit"); + return NULL; + } + } + else + { + DEBUG_PRINT("\n Error condition recieved NULL from Queue"); + } + + } +} + +static void* async_thread (void *context) +{ + struct video_decoder_context *decode_context = NULL; + struct vdec_output_frameinfo *outputframe = NULL; + struct video_msgq queueitem ; + struct vdec_msginfo vdec_msg; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + int result = -1; + + if (context == NULL) + { + DEBUG_PRINT("\n aynsc thread recieved NULL context"); + return NULL; + } + decode_context = (struct video_decoder_context *) context; + DEBUG_PRINT("\n Entering the async thread"); + + while (1) + { + ioctl_msg.in = NULL; + + ioctl_msg.out = (void*)&vdec_msg; + DEBUG_PRINT ("\n Sizeof vdec_msginfo = %d ",sizeof (vdec_msg)); + DEBUG_PRINT("\n Address of Vdec msg in async thread %p",\ + ioctl_msg.out); + if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_GET_NEXT_MSG,\ + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Error in ioctl read next msg"); + } + else + { + switch (vdec_msg.msgcode) + { + case VDEC_MSG_RESP_FLUSH_INPUT_DONE: + case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE: + case VDEC_MSG_RESP_START_DONE: + case VDEC_MSG_RESP_STOP_DONE: + case VDEC_MSG_EVT_HW_ERROR: + DEBUG_PRINT("\nioctl read next msg"); + queueitem.cmd = vdec_msg.msgcode; + queueitem.status = vdec_msg.status_code; + queueitem.clientdata = NULL; + break; + + case VDEC_MSG_RESP_INPUT_FLUSHED: + case VDEC_MSG_RESP_INPUT_BUFFER_DONE: + + queueitem.cmd = vdec_msg.msgcode; + queueitem.status = vdec_msg.status_code; + queueitem.clientdata = (void *)\ + vdec_msg.msgdata.input_frame_clientdata; + break; + + case VDEC_MSG_RESP_OUTPUT_FLUSHED: + case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: + queueitem.cmd = vdec_msg.msgcode; + queueitem.status = vdec_msg.status_code; + outputframe = (struct vdec_output_frameinfo *)\ + vdec_msg.msgdata.output_frame.client_data; + DEBUG_PRINT ("\n Client Data value in %p", \ + vdec_msg.msgdata.output_frame.client_data); + outputframe->bufferaddr = vdec_msg.msgdata.output_frame.bufferaddr; + outputframe->framesize.bottom = \ + vdec_msg.msgdata.output_frame.framesize.bottom; + outputframe->framesize.left = \ + vdec_msg.msgdata.output_frame.framesize.left; + outputframe->framesize.right = \ + vdec_msg.msgdata.output_frame.framesize.right; + outputframe->framesize.top = \ + vdec_msg.msgdata.output_frame.framesize.top; + outputframe->framesize = vdec_msg.msgdata.output_frame.framesize; + outputframe->len = vdec_msg.msgdata.output_frame.len; + outputframe->time_stamp = vdec_msg.msgdata.output_frame.time_stamp; + queueitem.clientdata = (void *)outputframe; + DEBUG_PRINT ("\n Client Data value Copy %p",queueitem.clientdata); + break; + + default: + DEBUG_PRINT("\nIn Default of get next message %d",vdec_msg.msgcode); + queueitem.cmd = vdec_msg.msgcode; + queueitem.status = vdec_msg.status_code; + queueitem.clientdata = NULL; + break; + } + result = queue_post_cmdq (&decode_context->queue_context,&queueitem); + while (result == 0) + { + result = queue_post_cmdq (&decode_context->queue_context, + &queueitem); + } + + if (result == -1) + { + DEBUG_PRINT("\n FATAL ERROR WITH Queue"); + } + } + if (vdec_msg.msgcode == VDEC_MSG_RESP_STOP_DONE) + { + /*Thread can exit at this point*/ + return NULL; + } + } +} + + +static unsigned int read_frame (unsigned char *dataptr, unsigned int length, + FILE * inputBufferFile) +{ + + unsigned int readOffset = 0; + int bytes_read = 0; + unsigned int code = 0; + int found = 0; + + DEBUG_PRINT ("\n Inside the readframe"); + + if (dataptr == NULL || length == 0) + { + DEBUG_PRINT ("\n dataptr = %p length = %u",dataptr,length); + return 0; + } + + if (!Code_type) + { + /* Start of Critical Section*/ + pthread_mutex_lock(&read_lock); + do + { + //Start codes are always byte aligned. + bytes_read = fread(&dataptr[readOffset],1, 1,inputBufferFile); + if( !bytes_read) + { + DEBUG_PRINT("\n Bytes read Zero \n"); + break; + } + code <<= 8; + code |= (0x000000FF & dataptr[readOffset]); + //VOP start code comparision + if (readOffset>3) + { + if(!header_code ) + { + if( VOP_START_CODE == code) + { + DEBUG_PRINT ("\n Found VOP Code"); + header_code = VOP_START_CODE; + } + else if ( (0xFFFFFC00 & code) == SHORT_HEADER_START_CODE ) + { + header_code = SHORT_HEADER_START_CODE; + } + } + if ((header_code == VOP_START_CODE) && (code == VOP_START_CODE)) + { + //Seek backwards by 4 + fseek(inputBufferFile, -4, SEEK_CUR); + readOffset-=4; + found = 1; + break; + + } + else if (( header_code == SHORT_HEADER_START_CODE ) && + ( SHORT_HEADER_START_CODE == (code & 0xFFFFFC00))) + { + //Seek backwards by 4 + fseek(inputBufferFile, -4, SEEK_CUR); + readOffset-=4; + found = 1; + break; + } + } + readOffset++; + }while (readOffset < length); + pthread_mutex_unlock(&read_lock); + /* End of Critical Section*/ + if (found == 1) + { + //DEBUG_PRINT ("Found a Frame"); + return (readOffset+1); + } + else + { + //DEBUG_PRINT ("No Frames detected"); + return 0; + } + } + else + { + + readOffset = Read_Buffer_From_DAT_File(dataptr,length,inputBufferFile); + if (total_frames == 0) + { + bytes_read = Read_Buffer_From_DAT_File(&dataptr[readOffset], + (length-readOffset), + inputBufferFile); + readOffset += bytes_read; + } + return (readOffset); + } + +} + +static int Read_Buffer_From_DAT_File(unsigned char *dataptr, unsigned int length, + FILE * inputBufferFile) +{ + + + long frameSize=0; + char temp_buffer[10]; + char temp_byte; + int bytes_read=0; + int i=0; + unsigned char *read_buffer=NULL; + char c = '1'; //initialize to anything except '\0'(0) + char inputFrameSize[12]; + int count =0; char cnt =0; + memset(temp_buffer, 0, sizeof(temp_buffer)); + + while (cnt < 10) + /* Check the input file format, may result in infinite loop */ + { + count = fread(&inputFrameSize[cnt],1,1,inputBufferFile); + if(inputFrameSize[cnt] == '\0' ) + break; + cnt++; + } + inputFrameSize[cnt]='\0'; + frameSize = atoi(inputFrameSize); + //length = 0; + DEBUG_PRINT ("\n Frame Size is %d",frameSize); + + /* get the frame length */ + fseek(inputBufferFile, -1, SEEK_CUR); + bytes_read = fread(dataptr, 1, frameSize, inputBufferFile); + + if(bytes_read == 0 || bytes_read < frameSize ) { + return 0; + } + return bytes_read; +} diff --git a/mm-video/vidc/vdec/test/omx_vdec_test.cpp b/mm-video/vidc/vdec/test/omx_vdec_test.cpp new file mode 100755 index 0000000..071304f --- /dev/null +++ b/mm-video/vidc/vdec/test/omx_vdec_test.cpp @@ -0,0 +1,4152 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/* + An Open max test application .... +*/ + +#define LOG_TAG "OMX-VDEC-TEST" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "OMX_QCOMExtns.h" +#include + +#include + +#ifdef _ANDROID_ +#include + +extern "C"{ +#include +} +#define DEBUG_PRINT +#define DEBUG_PRINT_ERROR ALOGE + +//#define __DEBUG_DIVX__ // Define this macro to print (through logcat) + // the kind of frames packed per buffer and + // timestamps adjustments for divx. + +//#define TEST_TS_FROM_SEI // Define this macro to calculate the timestamps + // from the SEI and VUI data for H264 + +#else +#include +#define strlcpy g_strlcpy + +#define ALOGE(fmt, args...) fprintf(stderr, fmt, ##args) +#define DEBUG_PRINT printf +#define DEBUG_PRINT_ERROR printf +#endif /* _ANDROID_ */ + +#include "OMX_Core.h" +#include "OMX_Component.h" +#include "OMX_QCOMExtns.h" +extern "C" { +#include "queue.h" +} + +#include +#include +#include + +/************************************************************************/ +/* #DEFINES */ +/************************************************************************/ +#define DELAY 66 +#define false 0 +#define true 1 +#define VOP_START_CODE 0x000001B6 +#define SHORT_HEADER_START_CODE 0x00008000 +#define MPEG2_FRAME_START_CODE 0x00000100 +#define MPEG2_SEQ_START_CODE 0x000001B3 +#define VC1_START_CODE 0x00000100 +#define VC1_FRAME_START_CODE 0x0000010D +#define VC1_FRAME_FIELD_CODE 0x0000010C +#define VC1_SEQUENCE_START_CODE 0x0000010F +#define VC1_ENTRY_POINT_START_CODE 0x0000010E +#define NUMBER_OF_ARBITRARYBYTES_READ (4 * 1024) +#define VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC 32 +#define VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC 16 +static int previous_vc1_au = 0; +#define CONFIG_VERSION_SIZE(param) \ + param.nVersion.nVersion = CURRENT_OMX_SPEC_VERSION;\ + param.nSize = sizeof(param); + +#define FAILED(result) (result != OMX_ErrorNone) + +#define SUCCEEDED(result) (result == OMX_ErrorNone) +#define SWAPBYTES(ptrA, ptrB) { char t = *ptrA; *ptrA = *ptrB; *ptrB = t;} +#define SIZE_NAL_FIELD_MAX 4 +#define MDP_DEINTERLACE 0x80000000 + +#define ALLOCATE_BUFFER 0 + +#ifdef MAX_RES_720P +#define PMEM_DEVICE "/dev/pmem_adsp" +#elif MAX_RES_1080P_EBI +#define PMEM_DEVICE "/dev/pmem_adsp" +#elif MAX_RES_1080P +#define PMEM_DEVICE "/dev/pmem_smipool" +#endif + +//#define USE_EXTERN_PMEM_BUF + +/************************************************************************/ +/* GLOBAL DECLARATIONS */ +/************************************************************************/ +#ifdef _ANDROID_ +using namespace android; +#endif + +#ifdef _MSM8974_ +typedef unsigned short int uint16; +const uint16 CRC_INIT = 0xFFFF ; + +const uint16 crc_16_l_table[ 256 ] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +uint16 crc_16_l_step_nv12 (uint16 seed, const void *buf_ptr, + unsigned int byte_len, unsigned int height, unsigned int width) +{ + uint16 crc_16 = ~seed; + char *buf = (char *)buf_ptr; + char *byte_ptr = buf; + int i, j; + const unsigned int width_align = 32; + const unsigned int height_align = 32; + unsigned int stride = (width + width_align -1) & (~(width_align-1)); + unsigned int scan_lines = (height + height_align -1) & (~(height_align-1)); + for (i = 0; i < height; i++) { + for (j = 0; j < stride; j++) { + if (j < width) { + crc_16 = crc_16_l_table[ (crc_16 ^ *byte_ptr) & 0x00ff ] ^ (crc_16 >> 8); + } + byte_ptr++; + } + } + byte_ptr = buf + (scan_lines * stride); + for (i = scan_lines; i < scan_lines + height/2;i++) { + for (j = 0; j < stride; j++) { + if (j < width) { + crc_16 = crc_16_l_table[ (crc_16 ^ *byte_ptr) & 0x00ff ] ^ (crc_16 >> 8); + } + byte_ptr++; + } + } + return( ~crc_16 ); +} +#endif + +typedef enum { + CODEC_FORMAT_H264 = 1, + CODEC_FORMAT_MP4, + CODEC_FORMAT_H263, + CODEC_FORMAT_VC1, + CODEC_FORMAT_DIVX, + CODEC_FORMAT_MPEG2, +#ifdef _MSM8974_ + CODEC_FORMAT_VP8, + CODEC_FORMAT_MAX = CODEC_FORMAT_VP8 +#else + CODEC_FORMAT_MAX = CODEC_FORMAT_MPEG2 +#endif +} codec_format; + +typedef enum { + FILE_TYPE_DAT_PER_AU = 1, + FILE_TYPE_ARBITRARY_BYTES, + FILE_TYPE_COMMON_CODEC_MAX, + + FILE_TYPE_START_OF_H264_SPECIFIC = 10, + FILE_TYPE_264_NAL_SIZE_LENGTH = FILE_TYPE_START_OF_H264_SPECIFIC, + + FILE_TYPE_START_OF_MP4_SPECIFIC = 20, + FILE_TYPE_PICTURE_START_CODE = FILE_TYPE_START_OF_MP4_SPECIFIC, + + FILE_TYPE_START_OF_VC1_SPECIFIC = 30, + FILE_TYPE_RCV = FILE_TYPE_START_OF_VC1_SPECIFIC, + FILE_TYPE_VC1, + + FILE_TYPE_START_OF_DIVX_SPECIFIC = 40, + FILE_TYPE_DIVX_4_5_6 = FILE_TYPE_START_OF_DIVX_SPECIFIC, + FILE_TYPE_DIVX_311, + + FILE_TYPE_START_OF_MPEG2_SPECIFIC = 50, + FILE_TYPE_MPEG2_START_CODE = FILE_TYPE_START_OF_MPEG2_SPECIFIC, + +#ifdef _MSM8974_ + FILE_TYPE_START_OF_VP8_SPECIFIC = 60, + FILE_TYPE_VP8_START_CODE = FILE_TYPE_START_OF_VP8_SPECIFIC, + FILE_TYPE_VP8 +#endif + +} file_type; + +typedef enum { + GOOD_STATE = 0, + PORT_SETTING_CHANGE_STATE, + ERROR_STATE +} test_status; + +typedef enum { + FREE_HANDLE_AT_LOADED = 1, + FREE_HANDLE_AT_IDLE, + FREE_HANDLE_AT_EXECUTING, + FREE_HANDLE_AT_PAUSE +} freeHandle_test; + +struct temp_egl { + int pmem_fd; + int offset; +}; + +static int (*Read_Buffer)(OMX_BUFFERHEADERTYPE *pBufHdr ); + +int inputBufferFileFd; + +FILE * outputBufferFile; +#ifdef _MSM8974_ +FILE * crcFile; +#endif +FILE * seqFile; +int takeYuvLog = 0; +int displayYuv = 0; +int displayWindow = 0; +int realtime_display = 0; + +Queue *etb_queue = NULL; +Queue *fbd_queue = NULL; + +pthread_t ebd_thread_id; +pthread_t fbd_thread_id; +void* ebd_thread(void*); +void* fbd_thread(void*); + +pthread_mutex_t etb_lock; +pthread_mutex_t fbd_lock; +pthread_mutex_t lock; +pthread_cond_t cond; +pthread_mutex_t eos_lock; +pthread_cond_t eos_cond; +pthread_mutex_t enable_lock; + +sem_t etb_sem; +sem_t fbd_sem; +sem_t seq_sem; +sem_t in_flush_sem, out_flush_sem; + +OMX_PARAM_PORTDEFINITIONTYPE portFmt; +OMX_PORT_PARAM_TYPE portParam; +OMX_ERRORTYPE error; +OMX_COLOR_FORMATTYPE color_fmt; +static bool input_use_buffer = false,output_use_buffer = false; +QOMX_VIDEO_DECODER_PICTURE_ORDER picture_order; + +#ifdef MAX_RES_1080P +unsigned int color_fmt_type = 1; +#else +unsigned int color_fmt_type = 0; +#endif + +#define CLR_KEY 0xe8fd +#define COLOR_BLACK_RGBA_8888 0x00000000 +#define FRAMEBUFFER_32 + +static int fb_fd = -1; +static struct fb_var_screeninfo vinfo; +static struct fb_fix_screeninfo finfo; +static struct mdp_overlay overlay, *overlayp; +static struct msmfb_overlay_data ov_front; +static int vid_buf_front_id; +static char tempbuf[16]; +int overlay_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr); +void overlay_set(); +void overlay_unset(); +void render_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr); +int disable_output_port(); +int enable_output_port(); +int output_port_reconfig(); +void free_output_buffers(); +int open_display(); +void close_display(); +/************************************************************************/ +/* GLOBAL INIT */ +/************************************************************************/ +int input_buf_cnt = 0; +int height =0, width =0; +int sliceheight = 0, stride = 0; +int used_ip_buf_cnt = 0; +unsigned free_op_buf_cnt = 0; +volatile int event_is_done = 0; +int ebd_cnt= 0, fbd_cnt = 0; +int bInputEosReached = 0; +int bOutputEosReached = 0; +char in_filename[512]; +#ifdef _MSM8974_ +char crclogname[512]; +#endif +char seq_file_name[512]; +unsigned char seq_enabled = 0; +bool anti_flickering = true; +unsigned char flush_input_progress = 0, flush_output_progress = 0; +unsigned cmd_data = ~(unsigned)0, etb_count = 0; + +char curr_seq_command[100]; +OMX_S64 timeStampLfile = 0; +int fps = 30; +unsigned int timestampInterval = 33333; +codec_format codec_format_option; +file_type file_type_option; +freeHandle_test freeHandle_option; +int nalSize = 0; +int sent_disabled = 0; +int waitForPortSettingsChanged = 1; +test_status currentStatus = GOOD_STATE; +struct timeval t_start = {0, 0}, t_end = {0, 0}; + +//* OMX Spec Version supported by the wrappers. Version = 1.1 */ +const OMX_U32 CURRENT_OMX_SPEC_VERSION = 0x00000101; +OMX_COMPONENTTYPE* dec_handle = 0; + +OMX_BUFFERHEADERTYPE **pInputBufHdrs = NULL; +OMX_BUFFERHEADERTYPE **pOutYUVBufHdrs= NULL; + +static OMX_BOOL use_external_pmem_buf = OMX_FALSE; + +int rcv_v1=0; +static struct temp_egl **p_eglHeaders = NULL; +static unsigned use_buf_virt_addr[32]; + +OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList = NULL; +OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry = NULL; +OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; + + +static int bHdrflag = 0; + +/* Performance related variable*/ +//QPERF_INIT(render_fb); +//QPERF_INIT(client_decode); + +/************************************************************************/ +/* GLOBAL FUNC DECL */ +/************************************************************************/ +int Init_Decoder(); +int Play_Decoder(); +int run_tests(); + +/**************************************************************************/ +/* STATIC DECLARATIONS */ +/**************************************************************************/ +static int video_playback_count = 1; +static int open_video_file (); +static int Read_Buffer_From_DAT_File(OMX_BUFFERHEADERTYPE *pBufHdr ); +static int Read_Buffer_ArbitraryBytes(OMX_BUFFERHEADERTYPE *pBufHdr); +static int Read_Buffer_From_Vop_Start_Code_File(OMX_BUFFERHEADERTYPE *pBufHdr); +static int Read_Buffer_From_Mpeg2_Start_Code(OMX_BUFFERHEADERTYPE *pBufHdr); +static int Read_Buffer_From_Size_Nal(OMX_BUFFERHEADERTYPE *pBufHdr); +static int Read_Buffer_From_RCV_File_Seq_Layer(OMX_BUFFERHEADERTYPE *pBufHdr); +static int Read_Buffer_From_RCV_File(OMX_BUFFERHEADERTYPE *pBufHdr); +#ifdef _MSM8974_ +static int Read_Buffer_From_VP8_File(OMX_BUFFERHEADERTYPE *pBufHdr); +#endif +static int Read_Buffer_From_VC1_File(OMX_BUFFERHEADERTYPE *pBufHdr); +static int Read_Buffer_From_DivX_4_5_6_File(OMX_BUFFERHEADERTYPE *pBufHdr); +static int Read_Buffer_From_DivX_311_File(OMX_BUFFERHEADERTYPE *pBufHdr); + +static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + long bufCntMin, long bufSize); + +static OMX_ERRORTYPE use_input_buffer(OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***bufferHdr, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufcnt); + +static OMX_ERRORTYPE use_output_buffer(OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***bufferHdr, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufcnt); + +static OMX_ERRORTYPE use_output_buffer_multiple_fd(OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***bufferHdr, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufcnt); + +static OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData); +static OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); +static OMX_ERRORTYPE FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent, + OMX_OUT OMX_PTR pAppData, + OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer); + +static void do_freeHandle_and_clean_up(bool isDueToError); + +#ifndef USE_ION +static bool align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size, + OMX_U32 alignment); +#endif +void getFreePmem(); +static int clip2(int x) + { + x = x -1; + x = x | x >> 1; + x = x | x >> 2; + x = x | x >> 4; + x = x | x >> 16; + x = x + 1; + return x; + } +void wait_for_event(void) +{ + DEBUG_PRINT("Waiting for event\n"); + pthread_mutex_lock(&lock); + while (event_is_done == 0) { + pthread_cond_wait(&cond, &lock); + } + event_is_done = 0; + pthread_mutex_unlock(&lock); + DEBUG_PRINT("Running .... get the event\n"); +} + +void event_complete(void ) +{ + pthread_mutex_lock(&lock); + if (event_is_done == 0) { + event_is_done = 1; + pthread_cond_broadcast(&cond); + } + pthread_mutex_unlock(&lock); +} +int get_next_command(FILE *seq_file) +{ + int i = -1; + do{ + i++; + if(fread(&curr_seq_command[i], 1, 1, seq_file) != 1) + return -1; + }while(curr_seq_command[i] != '\n'); + curr_seq_command[i] = 0; + printf("\n cmd_str = %s", curr_seq_command); + return 0; +} + +int process_current_command(const char *seq_command) +{ + char *data_str = NULL; + unsigned int data = 0, bufCnt = 0, i = 0; + int frameSize; + + if(strstr(seq_command, "pause") == seq_command) + { + printf("\n\n $$$$$ PAUSE $$$$$"); + data_str = (char*)seq_command + strlen("pause") + 1; + data = atoi(data_str); + printf("\n After frame number %u", data); + cmd_data = data; + sem_wait(&seq_sem); + if (!bOutputEosReached && !bInputEosReached) + { + printf("\n Sending PAUSE cmd to OMX compt"); + OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StatePause,0); + wait_for_event(); + printf("\n EventHandler for PAUSE DONE"); + } + else + seq_enabled = 0; + } + else if(strstr(seq_command, "sleep") == seq_command) + { + printf("\n\n $$$$$ SLEEP $$$$$"); + data_str = (char*)seq_command + strlen("sleep") + 1; + data = atoi(data_str); + printf("\n Sleep Time = %u ms", data); + usleep(data*1000); + } + else if(strstr(seq_command, "resume") == seq_command) + { + printf("\n\n $$$$$ RESUME $$$$$"); + printf("\n Immediate effect"); + printf("\n Sending RESUME cmd to OMX compt"); + OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateExecuting,0); + wait_for_event(); + printf("\n EventHandler for RESUME DONE"); + } + else if(strstr(seq_command, "flush") == seq_command) + { + printf("\n\n $$$$$ FLUSH $$$$$"); + data_str = (char*)seq_command + strlen("flush") + 1; + data = atoi(data_str); + printf("\n After frame number %u", data); + if (previous_vc1_au) + { + printf("\n Flush not allowed on Field boundary"); + return 0; + } + cmd_data = data; + sem_wait(&seq_sem); + if (!bOutputEosReached && !bInputEosReached) + { + printf("\n Sending FLUSH cmd to OMX compt"); + flush_input_progress = 1; + flush_output_progress = 1; + OMX_SendCommand(dec_handle, OMX_CommandFlush, OMX_ALL, 0); + wait_for_event(); + printf("\n EventHandler for FLUSH DONE"); + printf("\n Post EBD_thread flush sem"); + sem_post(&in_flush_sem); + printf("\n Post FBD_thread flush sem"); + sem_post(&out_flush_sem); + } + else + seq_enabled = 0; + } + else if(strstr(seq_command, "disable_op") == seq_command) + { + printf("\n\n $$$$$ DISABLE OP PORT $$$$$"); + data_str = (char*)seq_command + strlen("disable_op") + 1; + data = atoi(data_str); + printf("\n After frame number %u", data); + cmd_data = data; + sem_wait(&seq_sem); + printf("\n Sending DISABLE OP cmd to OMX compt"); + if (disable_output_port() != 0) + { + printf("\n ERROR: While DISABLE OP..."); + do_freeHandle_and_clean_up(true); + return -1; + } + else + printf("\n EventHandler for DISABLE OP"); + } + else if(strstr(seq_command, "enable_op") == seq_command) + { + printf("\n\n $$$$$ ENABLE OP PORT $$$$$"); + data_str = (char*)seq_command + strlen("enable_op") + 1; + printf("\n Sending ENABLE OP cmd to OMX compt"); + if (enable_output_port() != 0) + { + printf("\n ERROR: While ENABLE OP..."); + do_freeHandle_and_clean_up(true); + return -1; + } + else + printf("\n EventHandler for ENABLE OP"); + } + else + { + printf("\n\n $$$$$ INVALID CMD $$$$$"); + printf("\n seq_command[%s] is invalid", seq_command); + seq_enabled = 0; + } + return 0; +} + +void PrintFramePackArrangement(OMX_QCOM_FRAME_PACK_ARRANGEMENT framePackingArrangement) +{ + printf("id (%d)\n", + framePackingArrangement.id); + printf("cancel_flag (%d)\n", + framePackingArrangement.cancel_flag); + printf("type (%d)\n", + framePackingArrangement.type); + printf("quincunx_sampling_flag (%d)\n", + framePackingArrangement.quincunx_sampling_flag); + printf("content_interpretation_type (%d)\n", + framePackingArrangement.content_interpretation_type); + printf("spatial_flipping_flag (%d)\n", + framePackingArrangement.spatial_flipping_flag); + printf("frame0_flipped_flag (%d)\n", + framePackingArrangement.frame0_flipped_flag); + printf("field_views_flag (%d)\n", + framePackingArrangement.field_views_flag); + printf("current_frame_is_frame0_flag (%d)\n", + framePackingArrangement.current_frame_is_frame0_flag); + printf("frame0_self_contained_flag (%d)\n", + framePackingArrangement.frame0_self_contained_flag); + printf("frame1_self_contained_flag (%d)\n", + framePackingArrangement.frame1_self_contained_flag); + printf("frame0_grid_position_x (%d)\n", + framePackingArrangement.frame0_grid_position_x); + printf("frame0_grid_position_y (%d)\n", + framePackingArrangement.frame0_grid_position_y); + printf("frame1_grid_position_x (%d)\n", + framePackingArrangement.frame1_grid_position_x); + printf("frame1_grid_position_y (%d)\n", + framePackingArrangement.frame1_grid_position_y); + printf("reserved_byte (%d)\n", + framePackingArrangement.reserved_byte); + printf("repetition_period (%d)\n", + framePackingArrangement.repetition_period); + printf("extension_flag (%d)\n", + framePackingArrangement.extension_flag); +} +void* ebd_thread(void* pArg) +{ + while(currentStatus != ERROR_STATE) + { + int readBytes =0; + OMX_BUFFERHEADERTYPE* pBuffer = NULL; + + if(flush_input_progress) + { + DEBUG_PRINT("\n EBD_thread flush wait start"); + sem_wait(&in_flush_sem); + DEBUG_PRINT("\n EBD_thread flush wait complete"); + } + + sem_wait(&etb_sem); + pthread_mutex_lock(&etb_lock); + pBuffer = (OMX_BUFFERHEADERTYPE *) pop(etb_queue); + pthread_mutex_unlock(&etb_lock); + if(pBuffer == NULL) + { + DEBUG_PRINT_ERROR("Error - No etb pBuffer to dequeue\n"); + continue; + } + + pBuffer->nOffset = 0; + if((readBytes = Read_Buffer(pBuffer)) > 0) { + pBuffer->nFilledLen = readBytes; + DEBUG_PRINT("%s: Timestamp sent(%lld)", __FUNCTION__, pBuffer->nTimeStamp); + OMX_EmptyThisBuffer(dec_handle,pBuffer); + etb_count++; + } + else + { + pBuffer->nFlags |= OMX_BUFFERFLAG_EOS; + bInputEosReached = true; + pBuffer->nFilledLen = readBytes; + DEBUG_PRINT("%s: Timestamp sent(%lld)", __FUNCTION__, pBuffer->nTimeStamp); + OMX_EmptyThisBuffer(dec_handle,pBuffer); + DEBUG_PRINT("EBD::Either EOS or Some Error while reading file\n"); + etb_count++; + break; + } + } + return NULL; +} + +void* fbd_thread(void* pArg) +{ + long unsigned act_time = 0, display_time = 0, render_time = 5e3, lipsync = 15e3; + struct timeval t_avsync = {0, 0}, base_avsync = {0, 0}; + float total_time = 0; + int canDisplay = 1, contigous_drop_frame = 0, bytes_written = 0, ret = 0; + OMX_S64 base_timestamp = 0, lastTimestamp = 0; + OMX_BUFFERHEADERTYPE *pBuffer = NULL, *pPrevBuff = NULL; + pthread_mutex_lock(&eos_lock); +#ifdef _MSM8974_ + int stride,scanlines,stride_c,i; +#endif + DEBUG_PRINT("First Inside %s\n", __FUNCTION__); + while(currentStatus != ERROR_STATE && !bOutputEosReached) + { + pthread_mutex_unlock(&eos_lock); + DEBUG_PRINT("Inside %s\n", __FUNCTION__); + if(flush_output_progress) + { + DEBUG_PRINT("\n FBD_thread flush wait start"); + sem_wait(&out_flush_sem); + DEBUG_PRINT("\n FBD_thread flush wait complete"); + } + sem_wait(&fbd_sem); + pthread_mutex_lock(&enable_lock); + if (sent_disabled) + { + pthread_mutex_unlock(&enable_lock); + pthread_mutex_lock(&fbd_lock); + if (free_op_buf_cnt == portFmt.nBufferCountActual) + free_output_buffers(); + pthread_mutex_unlock(&fbd_lock); + pthread_mutex_lock(&eos_lock); + continue; + } + pthread_mutex_unlock(&enable_lock); + if (anti_flickering) + pPrevBuff = pBuffer; + pthread_mutex_lock(&fbd_lock); + pBuffer = (OMX_BUFFERHEADERTYPE *)pop(fbd_queue); + pthread_mutex_unlock(&fbd_lock); + if (pBuffer == NULL) + { + if (anti_flickering) + pBuffer = pPrevBuff; + DEBUG_PRINT("Error - No pBuffer to dequeue\n"); + pthread_mutex_lock(&eos_lock); + continue; + } + else if (pBuffer->nFilledLen > 0) + { + if (!fbd_cnt) + { + gettimeofday(&t_start, NULL); + } + fbd_cnt++; + DEBUG_PRINT("%s: fbd_cnt(%d) Buf(%p) Timestamp(%lld)", + __FUNCTION__, fbd_cnt, pBuffer, pBuffer->nTimeStamp); + canDisplay = 1; + if (realtime_display) + { + if (pBuffer->nTimeStamp != (lastTimestamp + timestampInterval)) + { + DEBUG_PRINT("Unexpected timestamp[%lld]! Expected[%lld]\n", + pBuffer->nTimeStamp, lastTimestamp + timestampInterval); + } + lastTimestamp = pBuffer->nTimeStamp; + gettimeofday(&t_avsync, NULL); + if (!base_avsync.tv_sec && !base_avsync.tv_usec) + { + display_time = 0; + base_avsync = t_avsync; + base_timestamp = pBuffer->nTimeStamp; + DEBUG_PRINT("base_avsync Sec(%lu) uSec(%lu) base_timestamp(%lld)", + base_avsync.tv_sec, base_avsync.tv_usec, base_timestamp); + } + else + { + act_time = (t_avsync.tv_sec - base_avsync.tv_sec) * 1e6 + + t_avsync.tv_usec - base_avsync.tv_usec; + display_time = pBuffer->nTimeStamp - base_timestamp; + DEBUG_PRINT("%s: act_time(%lu) display_time(%lu)", + __FUNCTION__, act_time, display_time); + //Frame rcvd on time + if (((act_time + render_time) >= (display_time - lipsync) && + (act_time + render_time) <= (display_time + lipsync)) || + //Display late frame + (contigous_drop_frame > 5)) + display_time = 0; + else if ((act_time + render_time) < (display_time - lipsync)) + //Delaying early frame + display_time -= (lipsync + act_time + render_time); + else + { + //Dropping late frame + canDisplay = 0; + contigous_drop_frame++; + } + } + } + if (displayYuv && canDisplay) + { + if (display_time) + usleep(display_time); + ret = overlay_fb(pBuffer); + if (ret != 0) + { + printf("\nERROR in overlay_fb, disabling display!"); + close_display(); + displayYuv = 0; + } + usleep(render_time); + contigous_drop_frame = 0; + } + + if (takeYuvLog) + { +#ifdef _MSM8974_ + stride = ((width + 31) & (~31)); + scanlines = ((height+31) & (~31)); + char *temp = (char *) pBuffer->pBuffer; + for (i = 0; i < height; i++) { + bytes_written = fwrite(temp, width, 1, outputBufferFile); + temp += stride; + } + temp = (char *)pBuffer->pBuffer + stride * scanlines; + stride_c = ((width/2 + 31) & (~31))*2; + for(i = 0; i < height/2; i++) { + bytes_written += fwrite(temp, width, 1, outputBufferFile); + temp += stride_c; + } +#else + DEBUG_PRINT_ERROR("NOTE: Buffer: %p, len: %d\n", pBuffer->pBuffer, + pBuffer->nFilledLen); + bytes_written = fwrite((const char *)pBuffer->pBuffer, + pBuffer->nFilledLen,1,outputBufferFile); +#endif + if (bytes_written < 0) { + DEBUG_PRINT("\nFillBufferDone: Failed to write to the file\n"); + } + else { + DEBUG_PRINT("\nFillBufferDone: Wrote %d YUV bytes to the file\n", + bytes_written); + } + } +#ifdef _MSM8974_ + if (crcFile) { + uint16 crc_val; + crc_val = crc_16_l_step_nv12(CRC_INIT, pBuffer->pBuffer, + pBuffer->nFilledLen, height, width); + int num_bytes = fwrite(&crc_val, 1, sizeof(crc_val), crcFile); + if (num_bytes < sizeof(crc_val)) { + printf("Failed to write CRC value into file\n"); + } + } else { + printf("No CRC file available\n"); + } +#endif + if (pBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) + { + OMX_OTHER_EXTRADATATYPE *pExtra; + DEBUG_PRINT(">> BUFFER WITH EXTRA DATA RCVD <<<"); + pExtra = (OMX_OTHER_EXTRADATATYPE *) + ((unsigned)(pBuffer->pBuffer + pBuffer->nOffset + + pBuffer->nFilledLen + 3)&(~3)); + while(pExtra && + (OMX_U8*)pExtra < (pBuffer->pBuffer + pBuffer->nAllocLen) && + pExtra->eType != OMX_ExtraDataNone ) + { + DEBUG_PRINT("ExtraData : pBuf(%p) BufTS(%lld) Type(%x) DataSz(%u)", + pBuffer, pBuffer->nTimeStamp, pExtra->eType, pExtra->nDataSize); + switch (pExtra->eType) + { + case OMX_ExtraDataInterlaceFormat: + { + OMX_STREAMINTERLACEFORMAT *pInterlaceFormat = (OMX_STREAMINTERLACEFORMAT *)pExtra->data; + DEBUG_PRINT("OMX_ExtraDataInterlaceFormat: Buf(%p) TSmp(%lld) IntPtr(%p) Fmt(%x)", + pBuffer->pBuffer, pBuffer->nTimeStamp, + pInterlaceFormat, pInterlaceFormat->nInterlaceFormats); + break; + } + case OMX_ExtraDataFrameInfo: + { + OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)pExtra->data; + DEBUG_PRINT("OMX_ExtraDataFrameInfo: Buf(%p) TSmp(%lld) PicType(%u) IntT(%u) ConMB(%u)", + pBuffer->pBuffer, pBuffer->nTimeStamp, frame_info->ePicType, + frame_info->interlaceType, frame_info->nConcealedMacroblocks); + DEBUG_PRINT(" FrmRate(%u), AspRatioX(%u), AspRatioY(%u) ", + frame_info->nFrameRate, frame_info->aspectRatio.aspectRatioX, + frame_info->aspectRatio.aspectRatioY); + DEBUG_PRINT("PANSCAN numWindows(%d)", frame_info->panScan.numWindows); + for (int i = 0; i < frame_info->panScan.numWindows; i++) + { + DEBUG_PRINT("WINDOW Lft(%d) Tp(%d) Rgt(%d) Bttm(%d)", + frame_info->panScan.window[i].x, + frame_info->panScan.window[i].y, + frame_info->panScan.window[i].dx, + frame_info->panScan.window[i].dy); + } + break; + } + break; + case OMX_ExtraDataConcealMB: + { + OMX_U8 data = 0, *data_ptr = (OMX_U8 *)pExtra->data; + OMX_U32 concealMBnum = 0, bytes_cnt = 0; + while (bytes_cnt < pExtra->nDataSize) + { + data = *data_ptr; + while (data) + { + concealMBnum += (data&0x01); + data >>= 1; + } + data_ptr++; + bytes_cnt++; + } + DEBUG_PRINT("OMX_ExtraDataConcealMB: Buf(%p) TSmp(%lld) ConcealMB(%u)", + pBuffer->pBuffer, pBuffer->nTimeStamp, concealMBnum); + } + break; + default: + DEBUG_PRINT_ERROR("Unknown Extrata!"); + } + if (pExtra->nSize < (pBuffer->nAllocLen - (OMX_U32)pExtra)) + pExtra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) pExtra) + pExtra->nSize); + else + { + DEBUG_PRINT_ERROR("ERROR: Extradata pointer overflow buffer(%p) extra(%p)", + pBuffer, pExtra); + pExtra = NULL; + } + } + } + } + if(pBuffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) + { + DEBUG_PRINT("\n"); + DEBUG_PRINT("***************************************************\n"); + DEBUG_PRINT("FillBufferDone: End Of Sequence Received\n"); + DEBUG_PRINT("***************************************************\n"); + } + if(pBuffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) + { + DEBUG_PRINT("\n"); + DEBUG_PRINT("***************************************************\n"); + DEBUG_PRINT("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received\n"); + DEBUG_PRINT("***************************************************\n"); + } + /********************************************************************/ + /* De-Initializing the open max and relasing the buffers and */ + /* closing the files.*/ + /********************************************************************/ + if (pBuffer->nFlags & OMX_BUFFERFLAG_EOS ) + { + OMX_QCOM_FRAME_PACK_ARRANGEMENT framePackingArrangement; + OMX_GetConfig(dec_handle, + (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement, + &framePackingArrangement); + PrintFramePackArrangement(framePackingArrangement); + + gettimeofday(&t_end, NULL); + total_time = ((float) ((t_end.tv_sec - t_start.tv_sec) * 1e6 + + t_end.tv_usec - t_start.tv_usec))/ 1e6; + //total frames is fbd_cnt - 1 since the start time is + //recorded after the first frame is decoded. + printf("\nAvg decoding frame rate=%f\n", (fbd_cnt - 1)/total_time); + + DEBUG_PRINT("***************************************************\n"); + DEBUG_PRINT("FillBufferDone: End Of Stream Reached\n"); + DEBUG_PRINT("***************************************************\n"); + pthread_mutex_lock(&eos_lock); + bOutputEosReached = true; + break; + } + + pthread_mutex_lock(&enable_lock); + if (flush_output_progress || sent_disabled) + { + pBuffer->nFilledLen = 0; + pBuffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA; + pthread_mutex_lock(&fbd_lock); + if ( pPrevBuff != NULL ) { + push(fbd_queue, (void *)pPrevBuff); + pPrevBuff = NULL; + } + if(push(fbd_queue, (void *)pBuffer) < 0) + { + DEBUG_PRINT_ERROR("Error in enqueueing fbd_data\n"); + } + else + sem_post(&fbd_sem); + pthread_mutex_unlock(&fbd_lock); + } + else + { + if (!anti_flickering) + pPrevBuff = pBuffer; + if (pPrevBuff) + { + pthread_mutex_lock(&fbd_lock); + pthread_mutex_lock(&eos_lock); + if (!bOutputEosReached) + { + if ( OMX_FillThisBuffer(dec_handle, pPrevBuff) == OMX_ErrorNone ) { + free_op_buf_cnt--; + } + } + pthread_mutex_unlock(&eos_lock); + pthread_mutex_unlock(&fbd_lock); + } + } + pthread_mutex_unlock(&enable_lock); + if(cmd_data <= fbd_cnt) + { + sem_post(&seq_sem); + printf("\n Posted seq_sem Frm(%d) Req(%d)", fbd_cnt, cmd_data); + cmd_data = ~(unsigned)0; + } + pthread_mutex_lock(&eos_lock); + } + if(seq_enabled) + { + seq_enabled = 0; + sem_post(&seq_sem); + printf("\n Posted seq_sem in EOS \n"); + } + pthread_cond_broadcast(&eos_cond); + pthread_mutex_unlock(&eos_lock); + return NULL; +} + +OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData) +{ + DEBUG_PRINT("Function %s \n", __FUNCTION__); + + switch(eEvent) { + case OMX_EventCmdComplete: + DEBUG_PRINT("\n OMX_EventCmdComplete \n"); + if(OMX_CommandPortDisable == (OMX_COMMANDTYPE)nData1) + { + DEBUG_PRINT("*********************************************\n"); + DEBUG_PRINT("Recieved DISABLE Event Command Complete[%d]\n",nData2); + DEBUG_PRINT("*********************************************\n"); + } + else if(OMX_CommandPortEnable == (OMX_COMMANDTYPE)nData1) + { + DEBUG_PRINT("*********************************************\n"); + DEBUG_PRINT("Recieved ENABLE Event Command Complete[%d]\n",nData2); + DEBUG_PRINT("*********************************************\n"); + if (currentStatus == PORT_SETTING_CHANGE_STATE) + currentStatus = GOOD_STATE; + pthread_mutex_lock(&enable_lock); + sent_disabled = 0; + pthread_mutex_unlock(&enable_lock); + } + else if(OMX_CommandFlush == (OMX_COMMANDTYPE)nData1) + { + DEBUG_PRINT("*********************************************\n"); + DEBUG_PRINT("Received FLUSH Event Command Complete[%d]\n",nData2); + DEBUG_PRINT("*********************************************\n"); + if (nData2 == 0) + flush_input_progress = 0; + else if (nData2 == 1) + flush_output_progress = 0; + } + if (!flush_input_progress && !flush_output_progress) + event_complete(); + break; + + case OMX_EventError: + printf("*********************************************\n"); + printf("Received OMX_EventError Event Command !\n"); + printf("*********************************************\n"); + currentStatus = ERROR_STATE; + if (OMX_ErrorInvalidState == (OMX_ERRORTYPE)nData1 || + OMX_ErrorHardware == (OMX_ERRORTYPE)nData1) + { + printf("Invalid State or hardware error \n"); + if(event_is_done == 0) + { + DEBUG_PRINT("Event error in the middle of Decode \n"); + pthread_mutex_lock(&eos_lock); + bOutputEosReached = true; + pthread_mutex_unlock(&eos_lock); + if(seq_enabled) + { + seq_enabled = 0; + sem_post(&seq_sem); + printf("\n Posted seq_sem in ERROR"); + } + } + } + if (waitForPortSettingsChanged) + { + waitForPortSettingsChanged = 0; + event_complete(); + } + break; + case OMX_EventPortSettingsChanged: + DEBUG_PRINT("OMX_EventPortSettingsChanged port[%d]\n", nData1); + currentStatus = PORT_SETTING_CHANGE_STATE; + if (waitForPortSettingsChanged) + { + waitForPortSettingsChanged = 0; + event_complete(); + } + else + { + pthread_mutex_lock(&eos_lock); + pthread_cond_broadcast(&eos_cond); + pthread_mutex_unlock(&eos_lock); + } + break; + + case OMX_EventBufferFlag: + DEBUG_PRINT("OMX_EventBufferFlag port[%d] flags[%x]\n", nData1, nData2); + if (nData1 == 1 && (nData2 & OMX_BUFFERFLAG_EOS)) { + pthread_mutex_lock(&eos_lock); + bOutputEosReached = true; + pthread_mutex_unlock(&eos_lock); + if(seq_enabled) + { + seq_enabled = 0; + sem_post(&seq_sem); + printf("\n Posted seq_sem in OMX_EventBufferFlag"); + } + } + else + { + DEBUG_PRINT_ERROR("OMX_EventBufferFlag Event not handled\n"); + } + break; + case OMX_EventIndexsettingChanged: + DEBUG_PRINT("OMX_EventIndexSettingChanged Interlace mode[%x]\n", nData1); + break; + default: + DEBUG_PRINT_ERROR("ERROR - Unknown Event \n"); + break; + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) +{ + int readBytes =0; int bufCnt=0; + OMX_ERRORTYPE result; + + DEBUG_PRINT("Function %s cnt[%d]\n", __FUNCTION__, ebd_cnt); + ebd_cnt++; + + + if(bInputEosReached) { + DEBUG_PRINT("*****EBD:Input EoS Reached************\n"); + return OMX_ErrorNone; + } + + pthread_mutex_lock(&etb_lock); + if(push(etb_queue, (void *) pBuffer) < 0) + { + DEBUG_PRINT_ERROR("Error in enqueue ebd data\n"); + return OMX_ErrorUndefined; + } + pthread_mutex_unlock(&etb_lock); + sem_post(&etb_sem); + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent, + OMX_OUT OMX_PTR pAppData, + OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) +{ + DEBUG_PRINT("Inside %s callback_count[%d] \n", __FUNCTION__, fbd_cnt); + + /* Test app will assume there is a dynamic port setting + * In case that there is no dynamic port setting, OMX will not call event cb, + * instead OMX will send empty this buffer directly and we need to clear an event here + */ + if(waitForPortSettingsChanged) + { + waitForPortSettingsChanged = 0; + if(displayYuv) + overlay_set(); + event_complete(); + } + + pthread_mutex_lock(&fbd_lock); + free_op_buf_cnt++; + if(push(fbd_queue, (void *)pBuffer) < 0) + { + pthread_mutex_unlock(&fbd_lock); + DEBUG_PRINT_ERROR("Error in enqueueing fbd_data\n"); + return OMX_ErrorUndefined; + } + pthread_mutex_unlock(&fbd_lock); + sem_post(&fbd_sem); + + return OMX_ErrorNone; +} + +int main(int argc, char **argv) +{ + int i=0; + int bufCnt=0; + int num=0; + int outputOption = 0; + int test_option = 0; + int pic_order = 0; + OMX_ERRORTYPE result; + sliceheight = height = 144; + stride = width = 176; + + if (argc < 2) + { + printf("To use it: ./mm-vdec-omx-test \n"); + printf("Command line argument is also available\n"); + return -1; + } + + strlcpy(in_filename, argv[1], strlen(argv[1])+1); +#ifdef _MSM8974_ + strlcpy(crclogname, argv[1], strlen(argv[1])+1); + strcat(crclogname, ".crc"); +#endif + if(argc > 2) + { + codec_format_option = (codec_format)atoi(argv[2]); + // file_type, out_op, tst_op, nal_sz, disp_win, rt_dis, (fps), color, pic_order + int param[9] = {2, 1, 1, 0, 0, 0, 0xFF, 0xFF, 0xFF}; + int next_arg = 3, idx = 0; + while (argc > next_arg && idx < 9) + { + if (strlen(argv[next_arg]) > 2) + { + strlcpy(seq_file_name, argv[next_arg],strlen(argv[next_arg]) + 1); + next_arg = argc; + } + else + param[idx++] = atoi(argv[next_arg++]); + } + idx = 0; + file_type_option = (file_type)param[idx++]; + if (codec_format_option == CODEC_FORMAT_H264 && file_type_option == 3) + { + nalSize = param[idx++]; + if (nalSize != 2 && nalSize != 4) + { + printf("Error - Can't pass NAL length size = %d\n", nalSize); + return -1; + } + } + outputOption = param[idx++]; + test_option = param[idx++]; + displayWindow = param[idx++]; + if (displayWindow > 0) + printf("Only entire display window supported! Ignoring value\n"); + realtime_display = param[idx++]; + if (realtime_display) + { + takeYuvLog = 0; + if(param[idx] != 0xFF) + { + fps = param[idx++]; + timestampInterval = 1e6 / fps; + } + } + color_fmt_type = (param[idx] != 0xFF)? param[idx++] : color_fmt_type; + pic_order = (param[idx] != 0xFF)? param[idx++] : 0; + printf("Executing DynPortReconfig QCIF 144 x 176 \n"); + } + else + { + printf("Command line argument is available\n"); + printf("To use it: ./mm-vdec-omx-test \n"); + printf(" \n"); + printf(" \n\n\n"); + printf(" *********************************************\n"); + printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n"); + printf(" *********************************************\n"); + printf(" 1--> H264\n"); + printf(" 2--> MP4\n"); + printf(" 3--> H263\n"); + printf(" 4--> VC1\n"); + printf(" 5--> DivX\n"); + printf(" 6--> MPEG2\n"); +#ifdef _MSM8974_ + printf(" 7--> VP8\n"); +#endif + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&codec_format_option); + fflush(stdin); + if (codec_format_option > CODEC_FORMAT_MAX) + { + printf(" Wrong test case...[%d] \n", codec_format_option); + return -1; + } + printf(" *********************************************\n"); + printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n"); + printf(" *********************************************\n"); + printf(" 1--> PER ACCESS UNIT CLIP (.dat). Clip only available for H264 and Mpeg4\n"); + printf(" 2--> ARBITRARY BYTES (need .264/.264c/.m4v/.263/.rcv/.vc1/.m2v)\n"); + if (codec_format_option == CODEC_FORMAT_H264) + { + printf(" 3--> NAL LENGTH SIZE CLIP (.264c)\n"); + } + else if ( (codec_format_option == CODEC_FORMAT_MP4) || (codec_format_option == CODEC_FORMAT_H263) ) + { + printf(" 3--> MP4 VOP or H263 P0 SHORT HEADER START CODE CLIP (.m4v or .263)\n"); + } + else if (codec_format_option == CODEC_FORMAT_VC1) + { + printf(" 3--> VC1 clip Simple/Main Profile (.rcv)\n"); + printf(" 4--> VC1 clip Advance Profile (.vc1)\n"); + } + else if (codec_format_option == CODEC_FORMAT_DIVX) + { + printf(" 3--> DivX 4, 5, 6 clip (.cmp)\n"); +#ifdef MAX_RES_1080P + printf(" 4--> DivX 3.11 clip \n"); +#endif + } + else if (codec_format_option == CODEC_FORMAT_MPEG2) + { + printf(" 3--> MPEG2 START CODE CLIP (.m2v)\n"); + } +#ifdef _MSM8974_ + else if (codec_format_option == CODEC_FORMAT_VP8) + { + printf(" 61--> VP8 START CODE CLIP (.ivf)\n"); + } +#endif + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&file_type_option); +#ifdef _MSM8974_ + if (codec_format_option == CODEC_FORMAT_VP8) + { + file_type_option = FILE_TYPE_VP8; + } +#endif + fflush(stdin); + if (codec_format_option == CODEC_FORMAT_H264 && file_type_option == 3) + { + printf(" Enter Nal length size [2 or 4] \n"); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&nalSize); + if (nalSize != 2 && nalSize != 4) + { + printf("Error - Can't pass NAL length size = %d\n", nalSize); + return -1; + } + } + + printf(" *********************************************\n"); + printf(" Output buffer option:\n"); + printf(" *********************************************\n"); + printf(" 0 --> No display and no YUV log\n"); + printf(" 1 --> Diplay YUV\n"); + printf(" 2 --> Take YUV log\n"); + printf(" 3 --> Display YUV and take YUV log\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&outputOption); + fflush(stdin); + + printf(" *********************************************\n"); + printf(" ENTER THE TEST CASE YOU WOULD LIKE TO EXECUTE\n"); + printf(" *********************************************\n"); + printf(" 1 --> Play the clip till the end\n"); + printf(" 2 --> Run compliance test. Do NOT expect any display for most option. \n"); + printf(" Please only see \"TEST SUCCESSFULL\" to indicate test pass\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&test_option); + fflush(stdin); + + if (outputOption == 1 || outputOption == 3) + { + printf(" *********************************************\n"); + printf(" ENTER THE PORTION OF DISPLAY TO USE\n"); + printf(" *********************************************\n"); + printf(" 0 --> Entire Screen\n"); + printf(" 1 --> 1/4 th of the screen starting from top left corner to middle \n"); + printf(" 2 --> 1/4 th of the screen starting from middle to top right corner \n"); + printf(" 3 --> 1/4 th of the screen starting from middle to bottom left \n"); + printf(" 4 --> 1/4 th of the screen starting from middle to bottom right \n"); + printf(" Please only see \"TEST SUCCESSFULL\" to indidcate test pass\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&displayWindow); + fflush(stdin); + if(displayWindow > 0) + { + printf(" Curently display window 0 only supported; ignoring other values\n"); + displayWindow = 0; + } + } + + if (outputOption == 1 || outputOption == 3) + { + printf(" *********************************************\n"); + printf(" DO YOU WANT TEST APP TO RENDER in Real time \n"); + printf(" 0 --> NO\n 1 --> YES\n"); + printf(" Warning: For H264, it require one NAL per frame clip.\n"); + printf(" For Arbitrary bytes option, Real time display is not recommended\n"); + printf(" *********************************************\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&realtime_display); + fflush(stdin); + } + + + if (realtime_display) + { + printf(" *********************************************\n"); + printf(" ENTER THE CLIP FPS\n"); + printf(" Exception: Timestamp extracted from clips will be used.\n"); + printf(" *********************************************\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&fps); + fflush(stdin); + timestampInterval = 1000000/fps; + } + + printf(" *********************************************\n"); + printf(" ENTER THE COLOR FORMAT \n"); + printf(" 0 --> Semiplanar \n 1 --> Tile Mode\n"); + printf(" *********************************************\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&color_fmt_type); + fflush(stdin); + + printf(" *********************************************\n"); + printf(" Output picture order option: \n"); + printf(" *********************************************\n"); + printf(" 0 --> Display order\n 1 --> Decode order\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&pic_order); + fflush(stdin); + } + if (file_type_option >= FILE_TYPE_COMMON_CODEC_MAX) + { + switch (codec_format_option) + { + case CODEC_FORMAT_H264: + file_type_option = (file_type)(FILE_TYPE_START_OF_H264_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); + break; + case CODEC_FORMAT_DIVX: + file_type_option = (file_type)(FILE_TYPE_START_OF_DIVX_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); + break; + case CODEC_FORMAT_MP4: + case CODEC_FORMAT_H263: + file_type_option = (file_type)(FILE_TYPE_START_OF_MP4_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); + break; + case CODEC_FORMAT_VC1: + file_type_option = (file_type)(FILE_TYPE_START_OF_VC1_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); + break; + case CODEC_FORMAT_MPEG2: + file_type_option = (file_type)(FILE_TYPE_START_OF_MPEG2_SPECIFIC + file_type_option - FILE_TYPE_COMMON_CODEC_MAX); + break; +#ifdef _MSM8974_ + case CODEC_FORMAT_VP8: + break; +#endif + default: + printf("Error: Unknown code %d\n", codec_format_option); + } + } + + CONFIG_VERSION_SIZE(picture_order); + picture_order.eOutputPictureOrder = QOMX_VIDEO_DISPLAY_ORDER; + if (pic_order == 1) + picture_order.eOutputPictureOrder = QOMX_VIDEO_DECODE_ORDER; + + if (outputOption == 0) + { + displayYuv = 0; + takeYuvLog = 0; + realtime_display = 0; + } + else if (outputOption == 1) + { + displayYuv = 1; + } + else if (outputOption == 2) + { + takeYuvLog = 1; + realtime_display = 0; + } + else if (outputOption == 3) + { + displayYuv = 1; + takeYuvLog = !realtime_display; + } + else + { + printf("Wrong option. Assume you want to see the YUV display\n"); + displayYuv = 1; + } + + if (test_option == 2) + { + printf(" *********************************************\n"); + printf(" ENTER THE COMPLIANCE TEST YOU WOULD LIKE TO EXECUTE\n"); + printf(" *********************************************\n"); + printf(" 1 --> Call Free Handle at the OMX_StateLoaded\n"); + printf(" 2 --> Call Free Handle at the OMX_StateIdle\n"); + printf(" 3 --> Call Free Handle at the OMX_StateExecuting\n"); + printf(" 4 --> Call Free Handle at the OMX_StatePause\n"); + fflush(stdin); + fgets(tempbuf,sizeof(tempbuf),stdin); + sscanf(tempbuf,"%d",&freeHandle_option); + fflush(stdin); + } + else + { + freeHandle_option = (freeHandle_test)0; + } + + printf("Input values: inputfilename[%s]\n", in_filename); + printf("*******************************************************\n"); + pthread_cond_init(&cond, 0); + pthread_cond_init(&eos_cond, 0); + pthread_mutex_init(&eos_lock, 0); + pthread_mutex_init(&lock, 0); + pthread_mutex_init(&etb_lock, 0); + pthread_mutex_init(&fbd_lock, 0); + pthread_mutex_init(&enable_lock, 0); + if (-1 == sem_init(&etb_sem, 0, 0)) + { + printf("Error - sem_init failed %d\n", errno); + } + if (-1 == sem_init(&fbd_sem, 0, 0)) + { + printf("Error - sem_init failed %d\n", errno); + } + if (-1 == sem_init(&seq_sem, 0, 0)) + { + printf("Error - sem_init failed %d\n", errno); + } + if (-1 == sem_init(&in_flush_sem, 0, 0)) + { + printf("Error - sem_init failed %d\n", errno); + } + if (-1 == sem_init(&out_flush_sem, 0, 0)) + { + printf("Error - sem_init failed %d\n", errno); + } + etb_queue = alloc_queue(); + if (etb_queue == NULL) + { + printf("\n Error in Creating etb_queue\n"); + return -1; + } + + fbd_queue = alloc_queue(); + if (fbd_queue == NULL) + { + printf("\n Error in Creating fbd_queue\n"); + free_queue(etb_queue); + return -1; + } + + if(0 != pthread_create(&fbd_thread_id, NULL, fbd_thread, NULL)) + { + printf("\n Error in Creating fbd_thread \n"); + free_queue(etb_queue); + free_queue(fbd_queue); + return -1; + } + + if (displayYuv) + { + if (open_display() != 0) + { + printf("\n Error opening display! Video won't be displayed..."); + displayYuv = 0; + } + } + + run_tests(); + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&lock); + pthread_mutex_destroy(&etb_lock); + pthread_mutex_destroy(&fbd_lock); + pthread_mutex_destroy(&enable_lock); + pthread_cond_destroy(&eos_cond); + pthread_mutex_destroy(&eos_lock); + if (-1 == sem_destroy(&etb_sem)) + { + DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); + } + if (-1 == sem_destroy(&fbd_sem)) + { + DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); + } + if (-1 == sem_destroy(&seq_sem)) + { + DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); + } + if (-1 == sem_destroy(&in_flush_sem)) + { + DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); + } + if (-1 == sem_destroy(&out_flush_sem)) + { + DEBUG_PRINT_ERROR("Error - sem_destroy failed %d\n", errno); + } + if (displayYuv) + close_display(); + return 0; +} + +int run_tests() +{ + int cmd_error = 0; + DEBUG_PRINT("Inside %s\n", __FUNCTION__); + waitForPortSettingsChanged = 1; + + if(file_type_option == FILE_TYPE_DAT_PER_AU) { + Read_Buffer = Read_Buffer_From_DAT_File; + } + else if(file_type_option == FILE_TYPE_ARBITRARY_BYTES) { + Read_Buffer = Read_Buffer_ArbitraryBytes; + } + else if(codec_format_option == CODEC_FORMAT_H264) { + Read_Buffer = Read_Buffer_From_Size_Nal; + } + else if((codec_format_option == CODEC_FORMAT_H263) || + (codec_format_option == CODEC_FORMAT_MP4)) { + Read_Buffer = Read_Buffer_From_Vop_Start_Code_File; + } + else if (codec_format_option == CODEC_FORMAT_MPEG2) { + Read_Buffer = Read_Buffer_From_Mpeg2_Start_Code; + } + else if(file_type_option == FILE_TYPE_DIVX_4_5_6) { + Read_Buffer = Read_Buffer_From_DivX_4_5_6_File; + } +#ifdef MAX_RES_1080P + else if(file_type_option == FILE_TYPE_DIVX_311) { + Read_Buffer = Read_Buffer_From_DivX_311_File; + } +#endif + else if(file_type_option == FILE_TYPE_RCV) { + Read_Buffer = Read_Buffer_From_RCV_File; + } +#ifdef _MSM8974_ + else if(file_type_option == FILE_TYPE_VP8) { + Read_Buffer = Read_Buffer_From_VP8_File; + } +#endif + else if(file_type_option == FILE_TYPE_VC1) { + Read_Buffer = Read_Buffer_From_VC1_File; + } + + DEBUG_PRINT("file_type_option %d!\n", file_type_option); + + switch(file_type_option) + { + case FILE_TYPE_DAT_PER_AU: + case FILE_TYPE_ARBITRARY_BYTES: + case FILE_TYPE_264_NAL_SIZE_LENGTH: + case FILE_TYPE_PICTURE_START_CODE: + case FILE_TYPE_MPEG2_START_CODE: + case FILE_TYPE_RCV: + case FILE_TYPE_VC1: +#ifdef _MSM8974_ + case FILE_TYPE_VP8: +#endif + case FILE_TYPE_DIVX_4_5_6: +#ifdef MAX_RES_1080P + case FILE_TYPE_DIVX_311: +#endif + if(Init_Decoder()!= 0x00) + { + DEBUG_PRINT_ERROR("Error - Decoder Init failed\n"); + return -1; + } + if(Play_Decoder() != 0x00) + { + return -1; + } + break; + default: + DEBUG_PRINT_ERROR("Error - Invalid Entry...%d\n",file_type_option); + break; + } + + anti_flickering = true; + if(strlen(seq_file_name)) + { + seqFile = fopen (seq_file_name, "rb"); + if (seqFile == NULL) + { + DEBUG_PRINT_ERROR("Error - Seq file %s could NOT be opened\n", + seq_file_name); + return -1; + } + else + { + DEBUG_PRINT("Seq file %s is opened \n", seq_file_name); + seq_enabled = 1; + anti_flickering = false; + } + } + + pthread_mutex_lock(&eos_lock); + while (bOutputEosReached == false && cmd_error == 0) + { + if(seq_enabled) + { + pthread_mutex_unlock(&eos_lock); + if(!get_next_command(seqFile)) + cmd_error = process_current_command(curr_seq_command); + else + { + printf("\n Error in get_next_cmd or EOF"); + seq_enabled = 0; + } + pthread_mutex_lock(&eos_lock); + } + else + pthread_cond_wait(&eos_cond, &eos_lock); + + if (currentStatus == PORT_SETTING_CHANGE_STATE) + { + pthread_mutex_unlock(&eos_lock); + cmd_error = output_port_reconfig(); + pthread_mutex_lock(&eos_lock); + } + } + pthread_mutex_unlock(&eos_lock); + + // Wait till EOS is reached... + if(bOutputEosReached) + do_freeHandle_and_clean_up(currentStatus == ERROR_STATE); + return 0; +} + +int Init_Decoder() +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE omxresult; + OMX_U32 total = 0; + char vdecCompNames[50]; + typedef OMX_U8* OMX_U8_PTR; + char *role ="video_decoder"; + + static OMX_CALLBACKTYPE call_back = {&EventHandler, &EmptyBufferDone, &FillBufferDone}; + + int i = 0; + long bufCnt = 0; + + /* Init. the OpenMAX Core */ + DEBUG_PRINT("\nInitializing OpenMAX Core....\n"); + omxresult = OMX_Init(); + + if(OMX_ErrorNone != omxresult) { + DEBUG_PRINT_ERROR("\n Failed to Init OpenMAX core"); + return -1; + } + else { + DEBUG_PRINT_ERROR("\nOpenMAX Core Init Done\n"); + } + + /* Query for video decoders*/ + OMX_GetComponentsOfRole(role, &total, 0); + DEBUG_PRINT("\nTotal components of role=%s :%d", role, total); + + if(total) + { + /* Allocate memory for pointers to component name */ + OMX_U8** vidCompNames = (OMX_U8**)malloc((sizeof(OMX_U8*))*total); + if (vidCompNames == NULL) { + DEBUG_PRINT_ERROR("\nFailed to allocate vidCompNames\n"); + return -1; + } + + for (i = 0; i < total; ++i) { + vidCompNames[i] = (OMX_U8*)malloc(sizeof(OMX_U8)*OMX_MAX_STRINGNAME_SIZE); + if (vidCompNames[i] == NULL) { + DEBUG_PRINT_ERROR("\nFailed to allocate vidCompNames[%d]\n", i); + return -1; + } + } + OMX_GetComponentsOfRole(role, &total, vidCompNames); + DEBUG_PRINT("\nComponents of Role:%s\n", role); + for (i = 0; i < total; ++i) { + DEBUG_PRINT("\nComponent Name [%s]\n",vidCompNames[i]); + free(vidCompNames[i]); + } + free(vidCompNames); + } + else { + DEBUG_PRINT_ERROR("No components found with Role:%s", role); + } + + if (codec_format_option == CODEC_FORMAT_H264) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.avc", 27); + //strlcpy(vdecCompNames, "OMX.SEC.qcom.video.decoder.avc", 31); + } + else if (codec_format_option == CODEC_FORMAT_MP4) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.mpeg4", 29); + } + else if (codec_format_option == CODEC_FORMAT_H263) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.h263", 28); + } + else if (codec_format_option == CODEC_FORMAT_VC1) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.vc1", 27); + } + else if (codec_format_option == CODEC_FORMAT_MPEG2) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.mpeg2", 29); + } + else if (file_type_option == FILE_TYPE_RCV) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.wmv", 27); + } + else if (file_type_option == FILE_TYPE_DIVX_4_5_6) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.divx", 28); + } +#ifdef _MSM8974_ + else if (codec_format_option == CODEC_FORMAT_VP8) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.vp8", 27); + } +#endif +#ifdef MAX_RES_1080P + else if (file_type_option == FILE_TYPE_DIVX_311) + { + strlcpy(vdecCompNames, "OMX.qcom.video.decoder.divx311", 31); + } +#endif + else + { + DEBUG_PRINT_ERROR("Error: Unsupported codec %d\n", codec_format_option); + return -1; + } + + omxresult = OMX_GetHandle((OMX_HANDLETYPE*)(&dec_handle), + (OMX_STRING)vdecCompNames, NULL, &call_back); + if (FAILED(omxresult)) { + DEBUG_PRINT_ERROR("\nFailed to Load the component:%s\n", vdecCompNames); + return -1; + } + else + { + DEBUG_PRINT("\nComponent %s is in LOADED state\n", vdecCompNames); + } + + QOMX_VIDEO_QUERY_DECODER_INSTANCES decoder_instances; + omxresult = OMX_GetConfig(dec_handle, + (OMX_INDEXTYPE)OMX_QcomIndexQueryNumberOfVideoDecInstance, + &decoder_instances); + DEBUG_PRINT("\n Number of decoder instances %d", + decoder_instances.nNumOfInstances); + + /* Get the port information */ + CONFIG_VERSION_SIZE(portParam); + omxresult = OMX_GetParameter(dec_handle, OMX_IndexParamVideoInit, + (OMX_PTR)&portParam); + + if(FAILED(omxresult)) { + DEBUG_PRINT_ERROR("ERROR - Failed to get Port Param\n"); + return -1; + } + else + { + DEBUG_PRINT("portParam.nPorts:%d\n", portParam.nPorts); + DEBUG_PRINT("portParam.nStartPortNumber:%d\n", portParam.nStartPortNumber); + } + + /* Set the compression format on i/p port */ + if (codec_format_option == CODEC_FORMAT_H264) + { + portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; + } + else if (codec_format_option == CODEC_FORMAT_MP4) + { + portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4; + } + else if (codec_format_option == CODEC_FORMAT_H263) + { + portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingH263; + } + else if (codec_format_option == CODEC_FORMAT_VC1) + { + portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV; + } + else if (codec_format_option == CODEC_FORMAT_DIVX) + { + portFmt.format.video.eCompressionFormat = + (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; + } + else if (codec_format_option == CODEC_FORMAT_MPEG2) + { + portFmt.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2; + } + else + { + DEBUG_PRINT_ERROR("Error: Unsupported codec %d\n", codec_format_option); + } + + + return 0; +} + +int Play_Decoder() +{ + OMX_VIDEO_PARAM_PORTFORMATTYPE videoportFmt = {0}; + int i, bufCnt, index = 0; + int frameSize=0; + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE* pBuffer = NULL; + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + + /* open the i/p and o/p files based on the video file format passed */ + if(open_video_file()) { + DEBUG_PRINT_ERROR("Error in opening video file\n"); + return -1; + } + + OMX_QCOM_PARAM_PORTDEFINITIONTYPE inputPortFmt; + memset(&inputPortFmt, 0, sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE)); + CONFIG_VERSION_SIZE(inputPortFmt); + inputPortFmt.nPortIndex = 0; // input port + switch (file_type_option) + { + case FILE_TYPE_DAT_PER_AU: + case FILE_TYPE_PICTURE_START_CODE: + case FILE_TYPE_MPEG2_START_CODE: + case FILE_TYPE_RCV: + case FILE_TYPE_VC1: +#ifdef MAX_RES_1080P + case FILE_TYPE_DIVX_311: +#endif + { + inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame; + break; + } + + case FILE_TYPE_ARBITRARY_BYTES: + case FILE_TYPE_264_NAL_SIZE_LENGTH: + case FILE_TYPE_DIVX_4_5_6: + { + inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Arbitrary; + break; + } +#ifdef _MSM8974_ + case FILE_TYPE_VP8: + { + inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame; + break; + } +#endif + default: + inputPortFmt.nFramePackingFormat = OMX_QCOM_FramePacking_Unspecified; + } + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexPortDefn, + (OMX_PTR)&inputPortFmt); +#ifdef USE_EXTERN_PMEM_BUF + OMX_QCOM_PARAM_PORTDEFINITIONTYPE outPortFmt; + memset(&outPortFmt, 0, sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE)); + CONFIG_VERSION_SIZE(outPortFmt); + outPortFmt.nPortIndex = 1; // output port + outPortFmt.nCacheAttr = OMX_QCOM_CacheAttrNone; + outPortFmt.nMemRegion = OMX_QCOM_MemRegionSMI; + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexPortDefn, + (OMX_PTR)&outPortFmt); + + OMX_QCOM_PLATFORMPRIVATE_EXTN outPltPvtExtn; + memset(&outPltPvtExtn, 0, sizeof(OMX_QCOM_PLATFORMPRIVATE_EXTN)); + CONFIG_VERSION_SIZE(outPltPvtExtn); + outPltPvtExtn.nPortIndex = 1; // output port + outPltPvtExtn.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexPlatformPvt, + (OMX_PTR)&outPltPvtExtn); + use_external_pmem_buf = OMX_TRUE; +#endif + QOMX_ENABLETYPE extra_data; + extra_data.bEnable = OMX_TRUE; +#if 0 + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamInterlaceExtraData, + (OMX_PTR)&extra_data); +#endif +#if 0 + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamConcealMBMapExtraData, + (OMX_PTR)&extra_data); +#endif +#if 1 + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamFrameInfoExtraData, + (OMX_PTR)&extra_data); +#endif +#ifdef TEST_TS_FROM_SEI + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamH264TimeInfo, + (OMX_PTR)&extra_data); +#endif +#if 0 + extra_data.bEnable = OMX_FALSE; + OMX_SetParameter(dec_handle,(OMX_INDEXTYPE)OMX_QcomIndexParamConcealMBMapExtraData, + (OMX_PTR)&extra_data); +#endif + /* Query the decoder outport's min buf requirements */ + CONFIG_VERSION_SIZE(portFmt); + + /* Port for which the Client needs to obtain info */ + portFmt.nPortIndex = portParam.nStartPortNumber; + + OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); + DEBUG_PRINT("\nDec: Min Buffer Count %d\n", portFmt.nBufferCountMin); + DEBUG_PRINT("\nDec: Buffer Size %d\n", portFmt.nBufferSize); + + if(OMX_DirInput != portFmt.eDir) { + printf ("\nDec: Expect Input Port\n"); + return -1; + } +#ifdef MAX_RES_1080P + if( (codec_format_option == CODEC_FORMAT_DIVX) && + (file_type_option == FILE_TYPE_DIVX_311) ) { + + int off; + + if ( read(inputBufferFileFd, &width, 4 ) == -1 ) { + DEBUG_PRINT_ERROR("\nFailed to read width for divx\n"); + return -1; + } + + DEBUG_PRINT("\nWidth for DIVX = %d\n", width); + + if ( read(inputBufferFileFd, &height, 4 ) == -1 ) { + DEBUG_PRINT_ERROR("\nFailed to read height for divx\n"); + return -1; + } + + DEBUG_PRINT("\nHeight for DIVX = %u\n", height); + sliceheight = height; + stride = width; + } +#endif + + bufCnt = 0; + portFmt.format.video.nFrameHeight = height; + portFmt.format.video.nFrameWidth = width; + portFmt.format.video.xFramerate = fps; + OMX_SetParameter(dec_handle,OMX_IndexParamPortDefinition, (OMX_PTR)&portFmt); + OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition, &portFmt); + DEBUG_PRINT("\nDec: New Min Buffer Count %d", portFmt.nBufferCountMin); + CONFIG_VERSION_SIZE(videoportFmt); +#ifdef MAX_RES_720P + if(color_fmt_type == 0) + { + color_fmt = OMX_COLOR_FormatYUV420SemiPlanar; + } + else + { + color_fmt = (OMX_COLOR_FORMATTYPE) + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; + } +#elif _MSM8974_ + color_fmt = OMX_COLOR_FormatYUV420SemiPlanar; +#else + color_fmt = (OMX_COLOR_FORMATTYPE) + QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; +#endif + + while (ret == OMX_ErrorNone) + { + videoportFmt.nPortIndex = 1; + videoportFmt.nIndex = index; + ret = OMX_GetParameter(dec_handle, OMX_IndexParamVideoPortFormat, + (OMX_PTR)&videoportFmt); + + if((ret == OMX_ErrorNone) && (videoportFmt.eColorFormat == + color_fmt)) + { + DEBUG_PRINT("\n Format[%u] supported by OMX Decoder", color_fmt); + break; + } + index++; + } + + if(ret == OMX_ErrorNone) + { + if(OMX_SetParameter(dec_handle, OMX_IndexParamVideoPortFormat, + (OMX_PTR)&videoportFmt) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\n Setting Tile format failed"); + return -1; + } + } + else + { + DEBUG_PRINT_ERROR("\n Error in retrieving supported color formats"); + return -1; + } + picture_order.nPortIndex = 1; + DEBUG_PRINT("\nSet picture order\n"); + if(OMX_SetParameter(dec_handle, + (OMX_INDEXTYPE)OMX_QcomIndexParamVideoDecoderPictureOrder, + (OMX_PTR)&picture_order) != OMX_ErrorNone) + { + printf("\n ERROR: Setting picture order!"); + return -1; + } + DEBUG_PRINT("\nVideo format: W x H (%d x %d)", + portFmt.format.video.nFrameWidth, + portFmt.format.video.nFrameHeight); + if(codec_format_option == CODEC_FORMAT_H264) + { + OMX_VIDEO_CONFIG_NALSIZE naluSize; + naluSize.nNaluBytes = nalSize; + DEBUG_PRINT("\n Nal length is %d index %d",nalSize,OMX_IndexConfigVideoNalSize); + OMX_SetConfig(dec_handle,OMX_IndexConfigVideoNalSize,(OMX_PTR)&naluSize); + DEBUG_PRINT("SETTING THE NAL SIZE to %d\n",naluSize.nNaluBytes); + } + DEBUG_PRINT("\nOMX_SendCommand Decoder -> IDLE\n"); + OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateIdle,0); + + input_buf_cnt = portFmt.nBufferCountActual; + DEBUG_PRINT("Transition to Idle State succesful...\n"); + +#if ALLOCATE_BUFFER + // Allocate buffer on decoder's i/p port + error = Allocate_Buffer(dec_handle, &pInputBufHdrs, portFmt.nPortIndex, + portFmt.nBufferCountActual, portFmt.nBufferSize); + if (error != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Input buffer error\n"); + return -1; + } + else { + DEBUG_PRINT("\nOMX_AllocateBuffer Input buffer success\n"); + } +#else + // Use buffer on decoder's i/p port + input_use_buffer = true; + DEBUG_PRINT_ERROR("\n before OMX_UseBuffer %p", &pInputBufHdrs); + error = use_input_buffer(dec_handle, + &pInputBufHdrs, + portFmt.nPortIndex, + portFmt.nBufferSize, + portFmt.nBufferCountActual); + if (error != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("ERROR - OMX_UseBuffer Input buffer failed"); + return -1; + } + else { + DEBUG_PRINT("OMX_UseBuffer Input buffer success\n"); + } +#endif + portFmt.nPortIndex = portParam.nStartPortNumber+1; + // Port for which the Client needs to obtain info + + OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); + DEBUG_PRINT("nMin Buffer Count=%d", portFmt.nBufferCountMin); + DEBUG_PRINT("nBuffer Size=%d", portFmt.nBufferSize); + if(OMX_DirOutput != portFmt.eDir) { + DEBUG_PRINT_ERROR("Error - Expect Output Port\n"); + return -1; + } + +#ifndef USE_EGL_IMAGE_TEST_APP + if (use_external_pmem_buf) + { + DEBUG_PRINT_ERROR("\n Use External pmem buf: OMX_UseBuffer %p", &pInputBufHdrs); + error = use_output_buffer_multiple_fd(dec_handle, + &pOutYUVBufHdrs, + portFmt.nPortIndex, + portFmt.nBufferSize, + portFmt.nBufferCountActual); + } + else + { + /* Allocate buffer on decoder's o/p port */ + error = Allocate_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex, + portFmt.nBufferCountActual, portFmt.nBufferSize); + } + free_op_buf_cnt = portFmt.nBufferCountActual; + if (error != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Output buffer error\n"); + return -1; + } + else + { + DEBUG_PRINT("OMX_AllocateBuffer Output buffer success\n"); + } +#else + DEBUG_PRINT_ERROR("\n before OMX_UseBuffer %p", &pInputBufHdrs); + error = use_output_buffer(dec_handle, + &pOutYUVBufHdrs, + portFmt.nPortIndex, + portFmt.nBufferSize, + portFmt.nBufferCountActual); + free_op_buf_cnt = portFmt.nBufferCountActual; + if (error != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("ERROR - OMX_UseBuffer Input buffer failed"); + return -1; + } + else { + DEBUG_PRINT("OMX_UseBuffer Input buffer success\n"); + } +#endif + wait_for_event(); + if (currentStatus == ERROR_STATE) + { + do_freeHandle_and_clean_up(true); + return -1; + } + + if (freeHandle_option == FREE_HANDLE_AT_IDLE) + { + OMX_STATETYPE state = OMX_StateInvalid; + OMX_GetState(dec_handle, &state); + if (state == OMX_StateIdle) + { + DEBUG_PRINT("Decoder is in OMX_StateIdle and trying to call OMX_FreeHandle \n"); + do_freeHandle_and_clean_up(false); + } + else + { + DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state); + do_freeHandle_and_clean_up(true); + } + return -1; + } + + + DEBUG_PRINT("OMX_SendCommand Decoder -> Executing\n"); + OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateExecuting,0); + wait_for_event(); + if (currentStatus == ERROR_STATE) + { + do_freeHandle_and_clean_up(true); + return -1; + } + if (pOutYUVBufHdrs == NULL) + { + DEBUG_PRINT_ERROR("Error - pOutYUVBufHdrs is NULL\n"); + return -1; + } + for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { + DEBUG_PRINT("OMX_FillThisBuffer on output buf no.%d\n",bufCnt); + if (pOutYUVBufHdrs[bufCnt] == NULL) + { + DEBUG_PRINT_ERROR("Error - pOutYUVBufHdrs[%d] is NULL\n", bufCnt); + return -1; + } + pOutYUVBufHdrs[bufCnt]->nOutputPortIndex = 1; + pOutYUVBufHdrs[bufCnt]->nFlags &= ~OMX_BUFFERFLAG_EOS; + ret = OMX_FillThisBuffer(dec_handle, pOutYUVBufHdrs[bufCnt]); + if (OMX_ErrorNone != ret) + DEBUG_PRINT_ERROR("Error - OMX_FillThisBuffer failed with result %d\n", ret); + else + { + DEBUG_PRINT("OMX_FillThisBuffer success!\n"); + free_op_buf_cnt--; + } + } + + used_ip_buf_cnt = input_buf_cnt; + + rcv_v1 = 0; + + //QPERF_START(client_decode); + if (codec_format_option == CODEC_FORMAT_VC1) + { + pInputBufHdrs[0]->nOffset = 0; + if(file_type_option == FILE_TYPE_RCV) + { + frameSize = Read_Buffer_From_RCV_File_Seq_Layer(pInputBufHdrs[0]); + pInputBufHdrs[0]->nFilledLen = frameSize; + DEBUG_PRINT("After Read_Buffer_From_RCV_File_Seq_Layer, " + "frameSize %d\n", frameSize); + } + else if(file_type_option == FILE_TYPE_VC1) + { + bHdrflag = 1; + pInputBufHdrs[0]->nFilledLen = Read_Buffer(pInputBufHdrs[0]); + bHdrflag = 0; + DEBUG_PRINT_ERROR("After 1st Read_Buffer for VC1, " + "pInputBufHdrs[0]->nFilledLen %d\n", pInputBufHdrs[0]->nFilledLen); + } + else + { + pInputBufHdrs[0]->nFilledLen = Read_Buffer(pInputBufHdrs[0]); + DEBUG_PRINT("After Read_Buffer pInputBufHdrs[0]->nFilledLen %d\n", + pInputBufHdrs[0]->nFilledLen); + } + + pInputBufHdrs[0]->nInputPortIndex = 0; + pInputBufHdrs[0]->nOffset = 0; + pInputBufHdrs[0]->nFlags = 0; + + ret = OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[0]); + if (ret != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("ERROR - OMX_EmptyThisBuffer failed with result %d\n", ret); + do_freeHandle_and_clean_up(true); + return -1; + } + else + { + etb_count++; + DEBUG_PRINT("OMX_EmptyThisBuffer success!\n"); + } + i = 1; + } + else + { + i = 0; + } + + for (i; i < used_ip_buf_cnt;i++) { + pInputBufHdrs[i]->nInputPortIndex = 0; + pInputBufHdrs[i]->nOffset = 0; + if((frameSize = Read_Buffer(pInputBufHdrs[i])) <= 0 ){ + DEBUG_PRINT("NO FRAME READ\n"); + pInputBufHdrs[i]->nFilledLen = frameSize; + pInputBufHdrs[i]->nInputPortIndex = 0; + pInputBufHdrs[i]->nFlags |= OMX_BUFFERFLAG_EOS;; + bInputEosReached = true; + + OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[i]); + etb_count++; + DEBUG_PRINT("File is small::Either EOS or Some Error while reading file\n"); + break; + } + pInputBufHdrs[i]->nFilledLen = frameSize; + pInputBufHdrs[i]->nInputPortIndex = 0; + pInputBufHdrs[i]->nFlags = 0; +//pBufHdr[bufCnt]->pAppPrivate = this; + DEBUG_PRINT("%s: Timestamp sent(%lld)", __FUNCTION__, pInputBufHdrs[i]->nTimeStamp); + ret = OMX_EmptyThisBuffer(dec_handle, pInputBufHdrs[i]); + if (OMX_ErrorNone != ret) { + DEBUG_PRINT_ERROR("ERROR - OMX_EmptyThisBuffer failed with result %d\n", ret); + do_freeHandle_and_clean_up(true); + return -1; + } + else { + DEBUG_PRINT("OMX_EmptyThisBuffer success!\n"); + etb_count++; + } + } + + if(0 != pthread_create(&ebd_thread_id, NULL, ebd_thread, NULL)) + { + printf("\n Error in Creating fbd_thread \n"); + free_queue(etb_queue); + free_queue(fbd_queue); + return -1; + } + + // wait for event port settings changed event + DEBUG_PRINT("wait_for_event: dyn reconfig"); + wait_for_event(); + DEBUG_PRINT("wait_for_event: dyn reconfig rcvd, currentStatus %d\n", + currentStatus); + if (currentStatus == ERROR_STATE) + { + printf("Error - ERROR_STATE\n"); + do_freeHandle_and_clean_up(true); + return -1; + } + else if (currentStatus == PORT_SETTING_CHANGE_STATE) + { + if (output_port_reconfig() != 0) + return -1; + } + + if (freeHandle_option == FREE_HANDLE_AT_EXECUTING) + { + OMX_STATETYPE state = OMX_StateInvalid; + OMX_GetState(dec_handle, &state); + if (state == OMX_StateExecuting) + { + DEBUG_PRINT("Decoder is in OMX_StateExecuting and trying to call OMX_FreeHandle \n"); + do_freeHandle_and_clean_up(false); + } + else + { + DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state); + do_freeHandle_and_clean_up(true); + } + return -1; + } + else if (freeHandle_option == FREE_HANDLE_AT_PAUSE) + { + OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StatePause,0); + wait_for_event(); + + OMX_STATETYPE state = OMX_StateInvalid; + OMX_GetState(dec_handle, &state); + if (state == OMX_StatePause) + { + DEBUG_PRINT("Decoder is in OMX_StatePause and trying to call OMX_FreeHandle \n"); + do_freeHandle_and_clean_up(false); + } + else + { + DEBUG_PRINT_ERROR("Error - Decoder is in state %d and trying to call OMX_FreeHandle \n", state); + do_freeHandle_and_clean_up(true); + } + return -1; + } + + return 0; +} + +static OMX_ERRORTYPE Allocate_Buffer ( OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + long bufCntMin, long bufSize) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE error=OMX_ErrorNone; + long bufCnt=0; + + DEBUG_PRINT("pBufHdrs = %x,bufCntMin = %d\n", pBufHdrs, bufCntMin); + *pBufHdrs= (OMX_BUFFERHEADERTYPE **) + malloc(sizeof(OMX_BUFFERHEADERTYPE)*bufCntMin); + + for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { + DEBUG_PRINT("OMX_AllocateBuffer No %d \n", bufCnt); + error = OMX_AllocateBuffer(dec_handle, &((*pBufHdrs)[bufCnt]), + nPortIndex, NULL, bufSize); + } + + return error; +} + +static OMX_ERRORTYPE use_input_buffer ( OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufCntMin) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE error=OMX_ErrorNone; + long bufCnt=0; + OMX_U8* pvirt = NULL; + + *pBufHdrs= (OMX_BUFFERHEADERTYPE **) + malloc(sizeof(OMX_BUFFERHEADERTYPE)* bufCntMin); + if(*pBufHdrs == NULL){ + DEBUG_PRINT_ERROR("\n m_inp_heap_ptr Allocation failed "); + return OMX_ErrorInsufficientResources; + } + + for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { + // allocate input buffers + DEBUG_PRINT("OMX_UseBuffer No %d %d \n", bufCnt, bufSize); + pvirt = (OMX_U8*) malloc (bufSize); + if(pvirt == NULL){ + DEBUG_PRINT_ERROR("\n pvirt Allocation failed "); + return OMX_ErrorInsufficientResources; + } + error = OMX_UseBuffer(dec_handle, &((*pBufHdrs)[bufCnt]), + nPortIndex, NULL, bufSize, pvirt); + } + return error; +} + +static OMX_ERRORTYPE use_output_buffer ( OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufCntMin) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE error=OMX_ErrorNone; + long bufCnt=0; + OMX_U8* pvirt = NULL; + + *pBufHdrs= (OMX_BUFFERHEADERTYPE **) + malloc(sizeof(OMX_BUFFERHEADERTYPE)* bufCntMin); + if(*pBufHdrs == NULL){ + DEBUG_PRINT_ERROR("\n m_inp_heap_ptr Allocation failed "); + return OMX_ErrorInsufficientResources; + } + output_use_buffer = true; + p_eglHeaders = (struct temp_egl **) + malloc(sizeof(struct temp_egl *)* bufCntMin); + if (!p_eglHeaders){ + DEBUG_PRINT_ERROR("\n EGL allocation failed"); + return OMX_ErrorInsufficientResources; + } + + for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { + // allocate input buffers + DEBUG_PRINT("OMX_UseBuffer No %d %d \n", bufCnt, bufSize); + p_eglHeaders[bufCnt] = (struct temp_egl*) + malloc(sizeof(struct temp_egl)); + if(!p_eglHeaders[bufCnt]) { + DEBUG_PRINT_ERROR("\n EGL allocation failed"); + return OMX_ErrorInsufficientResources; + } + p_eglHeaders[bufCnt]->pmem_fd = open(PMEM_DEVICE,O_RDWR); + p_eglHeaders[bufCnt]->offset = 0; + if(p_eglHeaders[bufCnt]->pmem_fd < 0) { + DEBUG_PRINT_ERROR("\n open failed %s",PMEM_DEVICE); + return OMX_ErrorInsufficientResources; + } + +#ifndef USE_ION + /* TBD - this commenting is dangerous */ + align_pmem_buffers(p_eglHeaders[bufCnt]->pmem_fd, bufSize, + 8192); +#endif + DEBUG_PRINT_ERROR("\n allocation size %d pmem fd %d",bufSize,p_eglHeaders[bufCnt]->pmem_fd); + pvirt = (unsigned char *)mmap(NULL,bufSize,PROT_READ|PROT_WRITE, + MAP_SHARED,p_eglHeaders[bufCnt]->pmem_fd,0); + DEBUG_PRINT_ERROR("\n Virtaul Address %p Size %d",pvirt,bufSize); + if (pvirt == MAP_FAILED) { + DEBUG_PRINT_ERROR("\n mmap failed for buffers"); + return OMX_ErrorInsufficientResources; + } + use_buf_virt_addr[bufCnt] = (unsigned)pvirt; + error = OMX_UseEGLImage(dec_handle, &((*pBufHdrs)[bufCnt]), + nPortIndex, pvirt,(void *)p_eglHeaders[bufCnt]); + } + return error; +} + +static OMX_ERRORTYPE use_output_buffer_multiple_fd ( OMX_COMPONENTTYPE *dec_handle, + OMX_BUFFERHEADERTYPE ***pBufHdrs, + OMX_U32 nPortIndex, + OMX_U32 bufSize, + long bufCntMin) +{ + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + OMX_ERRORTYPE error=OMX_ErrorNone; + long bufCnt=0; + OMX_U8* pvirt = NULL; + + *pBufHdrs= (OMX_BUFFERHEADERTYPE **) + malloc(sizeof(OMX_BUFFERHEADERTYPE)* bufCntMin); + if(*pBufHdrs == NULL){ + DEBUG_PRINT_ERROR("\n m_inp_heap_ptr Allocation failed "); + return OMX_ErrorInsufficientResources; + } + pPlatformList = (OMX_QCOM_PLATFORM_PRIVATE_LIST *) + malloc(sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST)* bufCntMin); + + if(pPlatformList == NULL){ + DEBUG_PRINT_ERROR("\n pPlatformList Allocation failed "); + return OMX_ErrorInsufficientResources; + } + + pPlatformEntry = (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *) + malloc(sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY)* bufCntMin); + + if(pPlatformEntry == NULL){ + DEBUG_PRINT_ERROR("\n pPlatformEntry Allocation failed "); + return OMX_ErrorInsufficientResources; + } + + pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + malloc(sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO)* bufCntMin); + + if(pPMEMInfo == NULL){ + DEBUG_PRINT_ERROR("\n pPMEMInfo Allocation failed "); + return OMX_ErrorInsufficientResources; + } + + //output_use_buffer = true; + for(bufCnt=0; bufCnt < bufCntMin; ++bufCnt) { + // allocate input buffers + DEBUG_PRINT("OMX_UseBuffer_multiple_fd No %d %d \n", bufCnt, bufSize); + + pPlatformEntry[bufCnt].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM; + pPlatformEntry[bufCnt].entry = &pPMEMInfo[bufCnt]; + // Initialize the Platform List + pPlatformList[bufCnt].nEntries = 1; + pPlatformList[bufCnt].entryList = &pPlatformEntry[bufCnt]; + pPMEMInfo[bufCnt].offset = 0; + pPMEMInfo[bufCnt].pmem_fd = open(PMEM_DEVICE,O_RDWR);; + if(pPMEMInfo[bufCnt].pmem_fd < 0) { + DEBUG_PRINT_ERROR("\n open failed %s",PMEM_DEVICE); + return OMX_ErrorInsufficientResources; + } +#ifndef USE_ION + /* TBD - this commenting is dangerous */ + align_pmem_buffers(pPMEMInfo[bufCnt].pmem_fd, bufSize, + 8192); +#endif + DEBUG_PRINT("\n allocation size %d pmem fd 0x%x",bufSize,pPMEMInfo[bufCnt].pmem_fd); + pvirt = (unsigned char *)mmap(NULL,bufSize,PROT_READ|PROT_WRITE, + MAP_SHARED,pPMEMInfo[bufCnt].pmem_fd,0); + getFreePmem(); + DEBUG_PRINT("\n Virtaul Address %p Size %d pmem_fd=0x%x",pvirt,bufSize,pPMEMInfo[bufCnt].pmem_fd); + if (pvirt == MAP_FAILED) { + DEBUG_PRINT_ERROR("\n mmap failed for buffers"); + return OMX_ErrorInsufficientResources; + } + use_buf_virt_addr[bufCnt] = (unsigned)pvirt; + error = OMX_UseBuffer(dec_handle, &((*pBufHdrs)[bufCnt]), + nPortIndex, &pPlatformList[bufCnt], bufSize, pvirt); + } + return error; +} +static void do_freeHandle_and_clean_up(bool isDueToError) +{ + int bufCnt = 0; + OMX_STATETYPE state = OMX_StateInvalid; + OMX_GetState(dec_handle, &state); + if (state == OMX_StateExecuting || state == OMX_StatePause) + { + DEBUG_PRINT("Requesting transition to Idle"); + OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateIdle, 0); + wait_for_event(); + } + OMX_GetState(dec_handle, &state); + if (state == OMX_StateIdle) + { + DEBUG_PRINT("Requesting transition to Loaded"); + OMX_SendCommand(dec_handle, OMX_CommandStateSet, OMX_StateLoaded, 0); + for(bufCnt=0; bufCnt < input_buf_cnt; ++bufCnt) + { + if (pInputBufHdrs[bufCnt]->pBuffer && input_use_buffer) + { + free(pInputBufHdrs[bufCnt]->pBuffer); + pInputBufHdrs[bufCnt]->pBuffer = NULL; + DEBUG_PRINT_ERROR("\nFree(pInputBufHdrs[%d]->pBuffer)",bufCnt); + } + OMX_FreeBuffer(dec_handle, 0, pInputBufHdrs[bufCnt]); + } + if (pInputBufHdrs) + { + free(pInputBufHdrs); + pInputBufHdrs = NULL; + } + for(bufCnt = 0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { + if (output_use_buffer && p_eglHeaders) { + if(p_eglHeaders[bufCnt]) { + munmap (pOutYUVBufHdrs[bufCnt]->pBuffer, + pOutYUVBufHdrs[bufCnt]->nAllocLen); + close(p_eglHeaders[bufCnt]->pmem_fd); + p_eglHeaders[bufCnt]->pmem_fd = -1; + free(p_eglHeaders[bufCnt]); + p_eglHeaders[bufCnt] = NULL; + } + } + if (use_external_pmem_buf) + { + DEBUG_PRINT("Freeing in external pmem case: buffer=0x%x, pmem_fd=0x%d", + pOutYUVBufHdrs[bufCnt]->pBuffer, + pPMEMInfo[bufCnt].pmem_fd); + if (pOutYUVBufHdrs[bufCnt]->pBuffer) + { + munmap (pOutYUVBufHdrs[bufCnt]->pBuffer, + pOutYUVBufHdrs[bufCnt]->nAllocLen); + } + if (&pPMEMInfo[bufCnt]) + { + close(pPMEMInfo[bufCnt].pmem_fd); + pPMEMInfo[bufCnt].pmem_fd = -1; + } + } + OMX_FreeBuffer(dec_handle, 1, pOutYUVBufHdrs[bufCnt]); + } + if(p_eglHeaders) { + free(p_eglHeaders); + p_eglHeaders = NULL; + } + if (pPMEMInfo) + { + DEBUG_PRINT("Freeing in external pmem case:PMEM"); + free(pPMEMInfo); + pPMEMInfo = NULL; + } + if (pPlatformEntry) + { + DEBUG_PRINT("Freeing in external pmem case:ENTRY"); + free(pPlatformEntry); + pPlatformEntry = NULL; + } + if (pPlatformList) + { + DEBUG_PRINT("Freeing in external pmem case:LIST"); + free(pPlatformList); + pPlatformList = NULL; + } + wait_for_event(); + } + + DEBUG_PRINT("[OMX Vdec Test] - Free handle decoder\n"); + OMX_ERRORTYPE result = OMX_FreeHandle(dec_handle); + if (result != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("[OMX Vdec Test] - OMX_FreeHandle error. Error code: %d\n", result); + } + dec_handle = NULL; + + /* Deinit OpenMAX */ + DEBUG_PRINT("[OMX Vdec Test] - De-initializing OMX \n"); + OMX_Deinit(); + + DEBUG_PRINT("[OMX Vdec Test] - closing all files\n"); + if(inputBufferFileFd != -1) + { + close(inputBufferFileFd); + inputBufferFileFd = -1; + } + + DEBUG_PRINT("[OMX Vdec Test] - after free inputfile\n"); + + if (takeYuvLog && outputBufferFile) { + fclose(outputBufferFile); + outputBufferFile = NULL; + } +#ifdef _MSM8974_ + if (crcFile) { + fclose(crcFile); + crcFile = NULL; + } +#endif + DEBUG_PRINT("[OMX Vdec Test] - after free outputfile\n"); + + if(etb_queue) + { + free_queue(etb_queue); + etb_queue = NULL; + } + DEBUG_PRINT("[OMX Vdec Test] - after free etb_queue \n"); + if(fbd_queue) + { + free_queue(fbd_queue); + fbd_queue = NULL; + } + DEBUG_PRINT("[OMX Vdec Test] - after free iftb_queue\n"); + printf("*****************************************\n"); + if (isDueToError) + printf("************...TEST FAILED...************\n"); + else + printf("**********...TEST SUCCESSFULL...*********\n"); + printf("*****************************************\n"); +} + +static int Read_Buffer_From_DAT_File(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + long frameSize=0; + char temp_buffer[10]; + char temp_byte; + int bytes_read=0; + int i=0; + unsigned char *read_buffer=NULL; + char c = '1'; //initialize to anything except '\0'(0) + char inputFrameSize[12]; + int count =0; char cnt =0; + memset(temp_buffer, 0, sizeof(temp_buffer)); + + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + + while (cnt < 10) + /* Check the input file format, may result in infinite loop */ + { + DEBUG_PRINT("loop[%d] count[%d]\n",cnt,count); + count = read( inputBufferFileFd, &inputFrameSize[cnt], 1); + if(inputFrameSize[cnt] == '\0' ) + break; + cnt++; + } + inputFrameSize[cnt]='\0'; + frameSize = atoi(inputFrameSize); + pBufHdr->nFilledLen = 0; + + /* get the frame length */ + lseek64(inputBufferFileFd, -1, SEEK_CUR); + bytes_read = read(inputBufferFileFd, pBufHdr->pBuffer, frameSize); + + DEBUG_PRINT("Actual frame Size [%d] bytes_read using fread[%d]\n", + frameSize, bytes_read); + + if(bytes_read == 0 || bytes_read < frameSize ) { + DEBUG_PRINT("Bytes read Zero After Read frame Size \n"); + DEBUG_PRINT("Checking VideoPlayback Count:video_playback_count is:%d\n", + video_playback_count); + return 0; + } + pBufHdr->nTimeStamp = timeStampLfile; + timeStampLfile += timestampInterval; + return bytes_read; +} + +static int Read_Buffer_ArbitraryBytes(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + int bytes_read=0; + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + bytes_read = read(inputBufferFileFd, pBufHdr->pBuffer, NUMBER_OF_ARBITRARYBYTES_READ); + if(bytes_read == 0) { + DEBUG_PRINT("Bytes read Zero After Read frame Size \n"); + DEBUG_PRINT("Checking VideoPlayback Count:video_playback_count is:%d\n", + video_playback_count); + return 0; + } +#ifdef TEST_TS_FROM_SEI + if (timeStampLfile == 0) + pBufHdr->nTimeStamp = 0; + else + pBufHdr->nTimeStamp = LLONG_MAX; +#else + pBufHdr->nTimeStamp = timeStampLfile; +#endif + timeStampLfile += timestampInterval; + return bytes_read; +} + +static int Read_Buffer_From_Vop_Start_Code_File(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + unsigned int readOffset = 0; + int bytes_read = 0; + unsigned int code = 0; + pBufHdr->nFilledLen = 0; + static unsigned int header_code = 0; + + DEBUG_PRINT("Inside %s", __FUNCTION__); + + do + { + //Start codes are always byte aligned. + bytes_read = read(inputBufferFileFd, &pBufHdr->pBuffer[readOffset], 1); + if(bytes_read == 0 || bytes_read == -1) + { + DEBUG_PRINT("Bytes read Zero \n"); + break; + } + code <<= 8; + code |= (0x000000FF & pBufHdr->pBuffer[readOffset]); + //VOP start code comparision + if (readOffset>3) + { + if(!header_code ){ + if( VOP_START_CODE == code) + { + header_code = VOP_START_CODE; + } + else if ( (0xFFFFFC00 & code) == SHORT_HEADER_START_CODE ) + { + header_code = SHORT_HEADER_START_CODE; + } + } + if ((header_code == VOP_START_CODE) && (code == VOP_START_CODE)) + { + //Seek backwards by 4 + lseek64(inputBufferFileFd, -4, SEEK_CUR); + readOffset-=3; + break; + } + else if (( header_code == SHORT_HEADER_START_CODE ) && ( SHORT_HEADER_START_CODE == (code & 0xFFFFFC00))) + { + //Seek backwards by 4 + lseek64(inputBufferFileFd, -4, SEEK_CUR); + readOffset-=3; + break; + } + } + readOffset++; + }while (1); + pBufHdr->nTimeStamp = timeStampLfile; + timeStampLfile += timestampInterval; + return readOffset; +} +static int Read_Buffer_From_Mpeg2_Start_Code(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + unsigned int readOffset = 0; + int bytesRead = 0; + unsigned int code = 0; + pBufHdr->nFilledLen = 0; + static unsigned int firstParse = true; + unsigned int seenFrame = false; + + DEBUG_PRINT("Inside %s", __FUNCTION__); + + /* Read one byte at a time. Construct the code every byte in order to + * compare to the start codes. Keep looping until we've read in a complete + * frame, which can be either just a picture start code + picture, or can + * include the sequence header as well + */ + while (1) { + bytesRead = read(inputBufferFileFd, &pBufHdr->pBuffer[readOffset], 1); + + /* Exit the loop if we can't read any more bytes */ + if (bytesRead == 0 || bytesRead == -1) { + break; + } + + /* Construct the code one byte at a time */ + code <<= 8; + code |= (0x000000FF & pBufHdr->pBuffer[readOffset]); + + /* Can't compare the code to MPEG2 start codes until we've read the + * first four bytes + */ + if (readOffset >= 3) { + + /* If this is the first time we're reading from the file, then we + * need to throw away the system start code information at the + * beginning. We can just look for the first sequence header. + */ + if (firstParse) { + if (code == MPEG2_SEQ_START_CODE) { + /* Seek back by 4 bytes and reset code so that we can skip + * down to the common case below. + */ + lseek(inputBufferFileFd, -4, SEEK_CUR); + code = 0; + readOffset -= 3; + firstParse = false; + continue; + } + } + + /* If we have already parsed a frame and we see a sequence header, then + * the sequence header is part of the next frame so we seek back and + * break. + */ + if (code == MPEG2_SEQ_START_CODE) { + if (seenFrame) { + lseek(inputBufferFileFd, -4, SEEK_CUR); + readOffset -= 3; + break; + } + /* If we haven't seen a frame yet, then read in all the data until we + * either see another frame start code or sequence header start code. + */ + } else if (code == MPEG2_FRAME_START_CODE) { + if (!seenFrame) { + seenFrame = true; + } else { + lseek(inputBufferFileFd, -4, SEEK_CUR); + readOffset -= 3; + break; + } + } + } + + readOffset++; + } + + pBufHdr->nTimeStamp = timeStampLfile; + timeStampLfile += timestampInterval; + return readOffset; +} + + +static int Read_Buffer_From_Size_Nal(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + // NAL unit stream processing + char temp_size[SIZE_NAL_FIELD_MAX]; + int i = 0; + int j = 0; + unsigned int size = 0; // Need to make sure that uint32 has SIZE_NAL_FIELD_MAX (4) bytes + int bytes_read = 0; + + // read the "size_nal_field"-byte size field + bytes_read = read(inputBufferFileFd, pBufHdr->pBuffer + pBufHdr->nOffset, nalSize); + if (bytes_read == 0 || bytes_read == -1) + { + DEBUG_PRINT("Failed to read frame or it might be EOF\n"); + return 0; + } + + for (i=0; ipBuffer[pBufHdr->nOffset + j]; + } + size = (unsigned int)(*((unsigned int *)(temp_size))); + + // now read the data + bytes_read = read(inputBufferFileFd, pBufHdr->pBuffer + pBufHdr->nOffset + nalSize, size); + if (bytes_read != size) + { + DEBUG_PRINT_ERROR("Failed to read frame\n"); + } + + pBufHdr->nTimeStamp = timeStampLfile; + timeStampLfile += timestampInterval; + + return bytes_read + nalSize; +} + +static int Read_Buffer_From_RCV_File_Seq_Layer(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + unsigned int readOffset = 0, size_struct_C = 0; + unsigned int startcode = 0; + pBufHdr->nFilledLen = 0; + pBufHdr->nFlags = 0; + + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + + read(inputBufferFileFd, &startcode, 4); + + /* read size of struct C as it need not be 4 always*/ + read(inputBufferFileFd, &size_struct_C, 4); + + /* reseek to beginning of sequence header */ + lseek64(inputBufferFileFd, -8, SEEK_CUR); + + if ((startcode & 0xFF000000) == 0xC5000000) + { + + DEBUG_PRINT("Read_Buffer_From_RCV_File_Seq_Layer size_struct_C: %d\n", size_struct_C); + + readOffset = read(inputBufferFileFd, pBufHdr->pBuffer, VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC + size_struct_C); + + } + else if((startcode & 0xFF000000) == 0x85000000) + { + // .RCV V1 file + + rcv_v1 = 1; + + DEBUG_PRINT("Read_Buffer_From_RCV_File_Seq_Layer size_struct_C: %d\n", size_struct_C); + + readOffset = read(inputBufferFileFd, pBufHdr->pBuffer, VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC + size_struct_C); + + } + else + { + DEBUG_PRINT_ERROR("Error: Unknown VC1 clip format %x\n", startcode); + } + +#if 0 + { + int i=0; + printf("Read_Buffer_From_RCV_File, length %d readOffset %d\n", readOffset, readOffset); + for (i=0; i<36; i++) + { + printf("0x%.2x ", pBufHdr->pBuffer[i]); + if (i%16 == 15) { + printf("\n"); + } + } + printf("\n"); + } +#endif + return readOffset; +} + +static int Read_Buffer_From_RCV_File(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + unsigned int readOffset = 0; + unsigned int len = 0; + unsigned int key = 0; + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + + DEBUG_PRINT("Read_Buffer_From_RCV_File - nOffset %d\n", pBufHdr->nOffset); + if(rcv_v1) + { + /* for the case of RCV V1 format, the frame header is only of 4 bytes and has + only the frame size information */ + readOffset = read(inputBufferFileFd, &len, 4); + DEBUG_PRINT("Read_Buffer_From_RCV_File - framesize %d %x\n", len, len); + + } + else + { + /* for a regular RCV file, 3 bytes comprise the frame size and 1 byte for key*/ + readOffset = read(inputBufferFileFd, &len, 3); + DEBUG_PRINT("Read_Buffer_From_RCV_File - framesize %d %x\n", len, len); + + readOffset = read(inputBufferFileFd, &key, 1); + if ( (key & 0x80) == false) + { + DEBUG_PRINT("Read_Buffer_From_RCV_File - Non IDR frame key %x\n", key); + } + + } + + if(!rcv_v1) + { + /* There is timestamp field only for regular RCV format and not for RCV V1 format*/ + readOffset = read(inputBufferFileFd, &pBufHdr->nTimeStamp, 4); + DEBUG_PRINT("Read_Buffer_From_RCV_File - timeStamp %d\n", pBufHdr->nTimeStamp); + pBufHdr->nTimeStamp *= 1000; + } + else + { + pBufHdr->nTimeStamp = timeStampLfile; + timeStampLfile += timestampInterval; + } + + if(len > pBufHdr->nAllocLen) + { + DEBUG_PRINT_ERROR("Error in sufficient buffer framesize %d, allocalen %d noffset %d\n",len,pBufHdr->nAllocLen, pBufHdr->nOffset); + readOffset = read(inputBufferFileFd, pBufHdr->pBuffer+pBufHdr->nOffset, + pBufHdr->nAllocLen - pBufHdr->nOffset); + + loff_t off = (len - readOffset)*1LL; + lseek64(inputBufferFileFd, off ,SEEK_CUR); + return readOffset; + } + else { + readOffset = read(inputBufferFileFd, pBufHdr->pBuffer+pBufHdr->nOffset, len); + } + if (readOffset != len) + { + DEBUG_PRINT("EOS reach or Reading error %d, %s \n", readOffset, strerror( errno )); + return 0; + } + +#if 0 + { + int i=0; + printf("Read_Buffer_From_RCV_File, length %d readOffset %d\n", len, readOffset); + for (i=0; i<64; i++) + { + printf("0x%.2x ", pBufHdr->pBuffer[i]); + if (i%16 == 15) { + printf("\n"); + } + } + printf("\n"); + } +#endif + + return readOffset; +} + +static int Read_Buffer_From_VC1_File(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + static int timeStampLfile = 0; + OMX_U8 *pBuffer = pBufHdr->pBuffer + pBufHdr->nOffset; + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + unsigned int readOffset = 0; + int bytes_read = 0; + unsigned int code = 0, total_bytes = 0; + int startCode_cnt = 0; + int bSEQflag = 0; + int bEntryflag = 0; + unsigned int SEQbytes = 0; + int numStartcodes = 0; + + numStartcodes = bHdrflag?1:2; + + do + { + if (total_bytes == pBufHdr->nAllocLen) + { + DEBUG_PRINT_ERROR("Buffer overflow!"); + break; + } + //Start codes are always byte aligned. + bytes_read = read(inputBufferFileFd, &pBuffer[readOffset],1 ); + + if(!bytes_read) + { + DEBUG_PRINT("\n Bytes read Zero \n"); + break; + } + total_bytes++; + code <<= 8; + code |= (0x000000FF & pBufHdr->pBuffer[readOffset]); + + if(!bSEQflag && (code == VC1_SEQUENCE_START_CODE)) { + if(startCode_cnt) bSEQflag = 1; + } + + if(!bEntryflag && ( code == VC1_ENTRY_POINT_START_CODE)) { + if(startCode_cnt) bEntryflag = 1; + } + + if(code == VC1_FRAME_START_CODE || code == VC1_FRAME_FIELD_CODE) + { + startCode_cnt++ ; + } + + //VOP start code comparision + if(startCode_cnt == numStartcodes) + { + if (VC1_FRAME_START_CODE == (code & 0xFFFFFFFF) || + VC1_FRAME_FIELD_CODE == (code & 0xFFFFFFFF)) + { + previous_vc1_au = 0; + if(VC1_FRAME_FIELD_CODE == (code & 0xFFFFFFFF)) + { + previous_vc1_au = 1; + } + + if(!bHdrflag && (bSEQflag || bEntryflag)) { + lseek(inputBufferFileFd,-(SEQbytes+4),SEEK_CUR); + readOffset -= (SEQbytes+3); + } + else { + //Seek backwards by 4 + lseek64(inputBufferFileFd, -4, SEEK_CUR); + readOffset-=3; + } + + while(pBufHdr->pBuffer[readOffset-1] == 0) + readOffset--; + + break; + } + } + readOffset++; + if(bSEQflag || bEntryflag) { + SEQbytes++; + } + }while (1); + + pBufHdr->nTimeStamp = timeStampLfile; + timeStampLfile += timestampInterval; + +#if 0 + { + int i=0; + printf("Read_Buffer_From_VC1_File, readOffset %d\n", readOffset); + for (i=0; i<64; i++) + { + printf("0x%.2x ", pBufHdr->pBuffer[i]); + if (i%16 == 15) { + printf("\n"); + } + } + printf("\n"); + } +#endif + + return readOffset; +} + +static int Read_Buffer_From_DivX_4_5_6_File(OMX_BUFFERHEADERTYPE *pBufHdr) +{ +#define MAX_NO_B_FRMS 3 // Number of non-b-frames packed in each buffer +#define N_PREV_FRMS_B 1 // Number of previous non-b-frames packed + // with a set of consecutive b-frames +#define FRM_ARRAY_SIZE (MAX_NO_B_FRMS + N_PREV_FRMS_B) + char *p_buffer = NULL; + unsigned int offset_array[FRM_ARRAY_SIZE]; + int byte_cntr, pckt_end_idx; + unsigned int read_code = 0, bytes_read, byte_pos = 0, frame_type; + unsigned int i, b_frm_idx, b_frames_found = 0, vop_set_cntr = 0; + bool pckt_ready = false; +#ifdef __DEBUG_DIVX__ + char pckt_type[20]; + int pckd_frms = 0; + static unsigned long long int total_bytes = 0; + static unsigned long long int total_frames = 0; +#endif //__DEBUG_DIVX__ + + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + + do { + p_buffer = (char *)pBufHdr->pBuffer + byte_pos; + + bytes_read = read(inputBufferFileFd, p_buffer, NUMBER_OF_ARBITRARYBYTES_READ); + byte_pos += bytes_read; + for (byte_cntr = 0; byte_cntr < bytes_read && !pckt_ready; byte_cntr++) { + read_code <<= 8; + ((char*)&read_code)[0] = p_buffer[byte_cntr]; + if (read_code == VOP_START_CODE) { + if (++byte_cntr < bytes_read) { + frame_type = p_buffer[byte_cntr]; + frame_type &= 0x000000C0; +#ifdef __DEBUG_DIVX__ + switch (frame_type) { + case 0x00: pckt_type[pckd_frms] = 'I'; break; + case 0x40: pckt_type[pckd_frms] = 'P'; break; + case 0x80: pckt_type[pckd_frms] = 'B'; break; + default: pckt_type[pckd_frms] = 'X'; + } + pckd_frms++; +#endif // __DEBUG_DIVX__ + offset_array[vop_set_cntr] = byte_pos - bytes_read + byte_cntr - 4; + if (frame_type == 0x80) { // B Frame found! + if (!b_frames_found) { + // Try to packet N_PREV_FRMS_B previous frames + // with the next consecutive B frames + i = N_PREV_FRMS_B; + while ((vop_set_cntr - i) < 0 && i > 0) i--; + b_frm_idx = vop_set_cntr - i; + if (b_frm_idx > 0) { + pckt_end_idx = b_frm_idx; + pckt_ready = true; +#ifdef __DEBUG_DIVX__ + pckt_type[b_frm_idx] = '\0'; + total_frames += b_frm_idx; +#endif //__DEBUG_DIVX__ + } + } + b_frames_found++; + } else if (b_frames_found) { + pckt_end_idx = vop_set_cntr; + pckt_ready = true; +#ifdef __DEBUG_DIVX__ + pckt_type[pckd_frms - 1] = '\0'; + total_frames += pckd_frms - 1; +#endif //__DEBUG_DIVX__ + } else if (vop_set_cntr == (FRM_ARRAY_SIZE -1)) { + pckt_end_idx = MAX_NO_B_FRMS; + pckt_ready = true; +#ifdef __DEBUG_DIVX__ + pckt_type[pckt_end_idx] = '\0'; + total_frames += pckt_end_idx; +#endif //__DEBUG_DIVX__ + } else + vop_set_cntr++; + } else { + // The vop start code was found in the last 4 bytes, + // seek backwards by 4 to include this start code + // with the next buffer. + lseek64(inputBufferFileFd, -4, SEEK_CUR); + byte_pos -= 4; +#ifdef __DEBUG_DIVX__ + pckd_frms--; +#endif //__DEBUG_DIVX__ + } + } + } + if (pckt_ready) { + loff_t off = (byte_pos - offset_array[pckt_end_idx]); + if ( lseek64(inputBufferFileFd, -1LL*off , SEEK_CUR) == -1 ){ + DEBUG_PRINT_ERROR("lseek64 with offset = %lld failed with errno %d" + ", current position =0x%llx", -1LL*off, + errno, lseek64(inputBufferFileFd, 0, SEEK_CUR)); + } + } + else { + char eofByte; + int ret = read(inputBufferFileFd, &eofByte, 1 ); + if ( ret == 0 ) { + offset_array[vop_set_cntr] = byte_pos; + pckt_end_idx = vop_set_cntr; + pckt_ready = true; +#ifdef __DEBUG_DIVX__ + pckt_type[pckd_frms] = '\0'; + total_frames += pckd_frms; +#endif //__DEBUG_DIVX__ + } + else if (ret == 1){ + if ( lseek64(inputBufferFileFd, -1, SEEK_CUR ) == -1 ){ + DEBUG_PRINT_ERROR("lseek64 failed with errno = %d, " + "current fileposition = %llx", + errno, + lseek64(inputBufferFileFd, 0, SEEK_CUR)); + } + } + else { + DEBUG_PRINT_ERROR("Error when checking for EOF"); + } + } + } while (!pckt_ready); + pBufHdr->nFilledLen = offset_array[pckt_end_idx]; + pBufHdr->nTimeStamp = timeStampLfile; + timeStampLfile += timestampInterval; +#ifdef __DEBUG_DIVX__ + total_bytes += pBufHdr->nFilledLen; + ALOGE("[DivX] Packet: Type[%s] Size[%u] TS[%lld] TB[%llx] NFrms[%lld]\n", + pckt_type, pBufHdr->nFilledLen, pBufHdr->nTimeStamp, + total_bytes, total_frames); +#endif //__DEBUG_DIVX__ + return pBufHdr->nFilledLen; +} + +static int Read_Buffer_From_DivX_311_File(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + static OMX_S64 timeStampLfile = 0; + char *p_buffer = NULL; + bool pkt_ready = false; + unsigned int frame_type = 0; + unsigned int bytes_read = 0; + unsigned int frame_size = 0; + unsigned int num_bytes_size = 4; + unsigned int num_bytes_frame_type = 1; + unsigned int n_offset = pBufHdr->nOffset; + + DEBUG_PRINT("Inside %s \n", __FUNCTION__); + + pBufHdr->nTimeStamp = timeStampLfile; + + if (pBufHdr != NULL) + { + p_buffer = (char *)pBufHdr->pBuffer + pBufHdr->nOffset; + } + else + { + DEBUG_PRINT("\n ERROR:Read_Buffer_From_DivX_311_File: pBufHdr is NULL\n"); + return 0; + } + + if (p_buffer == NULL) + { + DEBUG_PRINT("\n ERROR:Read_Buffer_From_DivX_311_File: p_bufhdr is NULL\n"); + return 0; + } + + //Read first frame based on size + //DivX 311 frame - 4 byte header with size followed by the frame + + bytes_read = read(inputBufferFileFd, &frame_size, num_bytes_size); + + DEBUG_PRINT("Read_Buffer_From_DivX_311_File: Frame size = %d\n", frame_size); + n_offset += read(inputBufferFileFd, p_buffer, frame_size); + + pBufHdr->nTimeStamp = timeStampLfile; + + timeStampLfile += timestampInterval; + + //the packet is ready to be sent + DEBUG_PRINT("\nReturning Read Buffer from Divx 311: TS=[%ld], Offset=[%d]\n", + (long int)pBufHdr->nTimeStamp, + n_offset ); + + return n_offset; +} +#ifdef _MSM8974_ +static int Read_Buffer_From_VP8_File(OMX_BUFFERHEADERTYPE *pBufHdr) +{ + static OMX_S64 timeStampLfile = 0; + char *p_buffer = NULL; + bool pkt_ready = false; + unsigned int frame_type = 0; + unsigned int bytes_read = 0; + unsigned int frame_size = 0; + unsigned int num_bytes_size = 4; + unsigned int num_bytes_frame_type = 1; + unsigned long long time_stamp; + unsigned int n_offset = pBufHdr->nOffset; + static int ivf_header_read; + + if (pBufHdr != NULL) + { + p_buffer = (char *)pBufHdr->pBuffer + pBufHdr->nOffset; + } + else + { + DEBUG_PRINT("\n ERROR:Read_Buffer_From_DivX_311_File: pBufHdr is NULL\n"); + return 0; + } + + if (p_buffer == NULL) + { + DEBUG_PRINT("\n ERROR:Read_Buffer_From_DivX_311_File: p_bufhdr is NULL\n"); + return 0; + } + + if(ivf_header_read == 0) { + bytes_read = read(inputBufferFileFd, p_buffer, 32); + ivf_header_read = 1; + if(p_buffer[0] == 'D' && p_buffer[1] == 'K' && p_buffer[2] == 'I' && p_buffer[3] == 'F') + { + printf(" \n IVF header found \n "); + } else + { + printf(" \n No IVF header found \n "); + lseek(inputBufferFileFd, -32, SEEK_CUR); + } + } + bytes_read = read(inputBufferFileFd, &frame_size, 4); + bytes_read = read(inputBufferFileFd, &time_stamp, 8); + n_offset += read(inputBufferFileFd, p_buffer, frame_size); + pBufHdr->nTimeStamp = time_stamp; + return n_offset; +} +#endif +static int open_video_file () +{ + int error_code = 0; + char outputfilename[512]; + DEBUG_PRINT("Inside %s filename=%s\n", __FUNCTION__, in_filename); + + if ( (inputBufferFileFd = open( in_filename, O_RDONLY | O_LARGEFILE) ) == -1 ){ + DEBUG_PRINT_ERROR("Error - i/p file %s could NOT be opened errno = %d\n", + in_filename, errno); + error_code = -1; + } + else { + DEBUG_PRINT_ERROR("i/p file %s is opened \n", in_filename); + } + + if (takeYuvLog) { + strlcpy(outputfilename, "yuvframes.yuv", 14); + outputBufferFile = fopen (outputfilename, "ab"); + if (outputBufferFile == NULL) + { + DEBUG_PRINT_ERROR("ERROR - o/p file %s could NOT be opened\n", outputfilename); + error_code = -1; + } + else + { + DEBUG_PRINT("O/p file %s is opened \n", outputfilename); + } + } +#ifdef _MSM8974_ + if (!crcFile) { + crcFile = fopen(crclogname, "ab"); + if (!crcFile) { + printf("Failed to open CRC file\n"); + error_code = -1; + } + } +#endif + return error_code; +} + +void swap_byte(char *pByte, int nbyte) +{ + int i=0; + + for (i=0; isrc.width = stride; + overlayp->src.height = sliceheight; +#ifdef MAX_RES_720P + overlayp->src.format = MDP_Y_CRCB_H2V2; + if(color_fmt == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka) + { + overlayp->src.format = MDP_Y_CRCB_H2V2_TILE; + } +#endif +#ifdef MAX_RES_1080P + overlayp->src.format = MDP_Y_CBCR_H2V2_TILE; +#endif + overlayp->src_rect.x = 0; + overlayp->src_rect.y = 0; + overlayp->src_rect.w = width; + overlayp->src_rect.h = height; + + if(width >= vinfo.xres) + { + overlayp->dst_rect.x = 0; + overlayp->dst_rect.w = vinfo.xres; + } + else + { + overlayp->dst_rect.x = (vinfo.xres - width)/2; + overlayp->dst_rect.w = width; + } + + if(height >= vinfo.yres) + { + overlayp->dst_rect.h = (overlayp->dst_rect.w * height)/width; + overlayp->dst_rect.y = 0; + if (overlayp->dst_rect.h < vinfo.yres) + overlayp->dst_rect.y = (vinfo.yres - overlayp->dst_rect.h)/2; + } + else + { + overlayp->dst_rect.y = (vinfo.yres - height)/2; + overlayp->dst_rect.h = height; + } + + overlayp->z_order = 0; + printf("overlayp->dst_rect.x = %u \n", overlayp->dst_rect.x); + printf("overlayp->dst_rect.y = %u \n", overlayp->dst_rect.y); + printf("overlayp->dst_rect.w = %u \n", overlayp->dst_rect.w); + printf("overlayp->dst_rect.h = %u \n", overlayp->dst_rect.h); + + overlayp->alpha = 0x0; + overlayp->transp_mask = 0xFFFFFFFF; + overlayp->flags = 0; + overlayp->is_fg = 0; + + overlayp->id = MSMFB_NEW_REQUEST; + vid_buf_front_id = ioctl(fb_fd, MSMFB_OVERLAY_SET, overlayp); + if (vid_buf_front_id < 0) + { + printf("ERROR: MSMFB_OVERLAY_SET failed! line=%d\n", __LINE__); + } + vid_buf_front_id = overlayp->id; + DEBUG_PRINT("\n vid_buf_front_id = %u", vid_buf_front_id); + drawBG(); + displayYuv = 2; +} + +int overlay_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr) +{ + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; + struct msmfb_overlay_data ov_front; + memset(&ov_front, 0, sizeof(struct msmfb_overlay_data)); +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) + MemoryHeapBase *vheap = NULL; +#endif + + DEBUG_PRINT("overlay_fb:"); + ov_front.id = overlayp->id; + if (pBufHdr->pPlatformPrivate == NULL) + { + ALOGE("overlay_fb: pPlatformPrivate is null"); + return -1; + } + pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) + pBufHdr->pPlatformPrivate)->entryList->entry; + if (pPMEMInfo == NULL) + { + + ALOGE("overlay_fb: pmem_info is null"); + return -1; + } +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) + vheap = (MemoryHeapBase*)pPMEMInfo->pmem_fd; +#endif + +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) + ov_front.data.memory_id = vheap->getHeapID(); +#else + ov_front.data.memory_id = pPMEMInfo->pmem_fd; +#endif + + ov_front.data.offset = pPMEMInfo->offset; + + DEBUG_PRINT("\n ov_front.data.memory_id = %d", ov_front.data.memory_id); + DEBUG_PRINT("\n ov_front.data.offset = %u", ov_front.data.offset); + if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, (void*)&ov_front)) + { + printf("\nERROR! MSMFB_OVERLAY_PLAY failed at frame (Line %d)\n", + __LINE__); + return -1; + } + if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo) < 0) + { + printf("ERROR: FBIOPAN_DISPLAY failed! line=%d\n", __LINE__); + return -1; + } + DEBUG_PRINT("\nMSMFB_OVERLAY_PLAY successfull"); + return 0; +} + +void overlay_unset() +{ + if (ioctl(fb_fd, MSMFB_OVERLAY_UNSET, &vid_buf_front_id)) + { + printf("\nERROR! MSMFB_OVERLAY_UNSET failed! (Line %d)\n", __LINE__); + } +} + +void render_fb(struct OMX_BUFFERHEADERTYPE *pBufHdr) +{ + unsigned int addr = 0; + OMX_OTHER_EXTRADATATYPE *pExtraData = 0; + OMX_QCOM_EXTRADATA_FRAMEINFO *pExtraFrameInfo = 0; + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL; + unsigned int destx, desty,destW, destH; +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) + MemoryHeapBase *vheap = NULL; +#endif + + unsigned int end = (unsigned int)(pBufHdr->pBuffer + pBufHdr->nAllocLen); + + struct mdp_blit_req *e; + union { + char dummy[sizeof(struct mdp_blit_req_list) + + sizeof(struct mdp_blit_req) * 1]; + struct mdp_blit_req_list list; + } img; + + if (fb_fd < 0) + { + DEBUG_PRINT_ERROR("Warning: /dev/fb0 is not opened!\n"); + return; + } + + img.list.count = 1; + e = &img.list.req[0]; + + addr = (unsigned int)(pBufHdr->pBuffer + pBufHdr->nFilledLen); + // align to a 4 byte boundary + addr = (addr + 3) & (~3); + + // read to the end of existing extra data sections + pExtraData = (OMX_OTHER_EXTRADATATYPE*)addr; + + while (addr < end && pExtraData->eType != OMX_ExtraDataFrameInfo) + { + addr += pExtraData->nSize; + pExtraData = (OMX_OTHER_EXTRADATATYPE*)addr; + } + + if (pExtraData->eType != OMX_ExtraDataFrameInfo) + { + DEBUG_PRINT_ERROR("pExtraData->eType %d pExtraData->nSize %d\n",pExtraData->eType,pExtraData->nSize); + } + pExtraFrameInfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)pExtraData->data; + + pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *) + ((OMX_QCOM_PLATFORM_PRIVATE_LIST *) + pBufHdr->pPlatformPrivate)->entryList->entry; +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) + vheap = (MemoryHeapBase *)pPMEMInfo->pmem_fd; +#endif + + + DEBUG_PRINT_ERROR("DecWidth %d DecHeight %d\n",portFmt.format.video.nStride,portFmt.format.video.nSliceHeight); + DEBUG_PRINT_ERROR("DispWidth %d DispHeight %d\n",portFmt.format.video.nFrameWidth,portFmt.format.video.nFrameHeight); + + + + e->src.width = portFmt.format.video.nStride; + e->src.height = portFmt.format.video.nSliceHeight; + e->src.format = MDP_Y_CBCR_H2V2; + e->src.offset = pPMEMInfo->offset; +#if defined(_ANDROID_) && !defined(USE_EGL_IMAGE_TEST_APP) && !defined(USE_EXTERN_PMEM_BUF) + e->src.memory_id = vheap->getHeapID(); +#else + e->src.memory_id = pPMEMInfo->pmem_fd; +#endif + + DEBUG_PRINT_ERROR("pmemOffset %d pmemID %d\n",e->src.offset,e->src.memory_id); + + e->dst.width = vinfo.xres; + e->dst.height = vinfo.yres; + e->dst.format = MDP_RGB_565; + e->dst.offset = 0; + e->dst.memory_id = fb_fd; + + e->transp_mask = 0xffffffff; + DEBUG_PRINT("Frame interlace type %d!\n", pExtraFrameInfo->interlaceType); + if(pExtraFrameInfo->interlaceType != OMX_QCOM_InterlaceFrameProgressive) + { + DEBUG_PRINT("Interlaced Frame!\n"); + e->flags = MDP_DEINTERLACE; + } + else + e->flags = 0; + e->alpha = 0xff; + + switch(displayWindow) + { + case 1: destx = 0; + desty = 0; + destW = vinfo.xres/2; + destH = vinfo.yres/2; + break; + case 2: destx = vinfo.xres/2; + desty = 0; + destW = vinfo.xres/2; + destH = vinfo.yres/2; + break; + + case 3: destx = 0; + desty = vinfo.yres/2; + destW = vinfo.xres/2; + destH = vinfo.yres/2; + break; + case 4: destx = vinfo.xres/2; + desty = vinfo.yres/2; + destW = vinfo.xres/2; + destH = vinfo.yres/2; + break; + case 0: + default: + destx = 0; + desty = 0; + destW = vinfo.xres; + destH = vinfo.yres; + } + + + if(portFmt.format.video.nFrameWidth < destW) + destW = portFmt.format.video.nFrameWidth ; + + + if(portFmt.format.video.nFrameHeight < destH) + destH = portFmt.format.video.nFrameHeight; + + e->dst_rect.x = destx; + e->dst_rect.y = desty; + e->dst_rect.w = destW; + e->dst_rect.h = destH; + + //e->dst_rect.w = 800; + //e->dst_rect.h = 480; + + e->src_rect.x = 0; + e->src_rect.y = 0; + e->src_rect.w = portFmt.format.video.nFrameWidth; + e->src_rect.h = portFmt.format.video.nFrameHeight; + + //e->src_rect.w = portFmt.format.video.nStride; + //e->src_rect.h = portFmt.format.video.nSliceHeight; + + if (ioctl(fb_fd, MSMFB_BLIT, &img)) { + DEBUG_PRINT_ERROR("MSMFB_BLIT ioctl failed!\n"); + return; + } + + if (ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo) < 0) { + DEBUG_PRINT_ERROR("FBIOPAN_DISPLAY failed! line=%d\n", __LINE__); + return; + } + + DEBUG_PRINT("render_fb complete!\n"); +} + +int disable_output_port() +{ + DEBUG_PRINT("DISABLING OP PORT\n"); + pthread_mutex_lock(&enable_lock); + sent_disabled = 1; + // Send DISABLE command + OMX_SendCommand(dec_handle, OMX_CommandPortDisable, 1, 0); + pthread_mutex_unlock(&enable_lock); + // wait for Disable event to come back + wait_for_event(); + if(p_eglHeaders) { + free(p_eglHeaders); + p_eglHeaders = NULL; + } + if (pPMEMInfo) + { + DEBUG_PRINT("Freeing in external pmem case:PMEM"); + free(pPMEMInfo); + pPMEMInfo = NULL; + } + if (pPlatformEntry) + { + DEBUG_PRINT("Freeing in external pmem case:ENTRY"); + free(pPlatformEntry); + pPlatformEntry = NULL; + } + if (pPlatformList) + { + DEBUG_PRINT("Freeing in external pmem case:LIST"); + free(pPlatformList); + pPlatformList = NULL; + } + if (currentStatus == ERROR_STATE) + { + do_freeHandle_and_clean_up(true); + return -1; + } + DEBUG_PRINT("OP PORT DISABLED!\n"); + return 0; +} + +int enable_output_port() +{ + int bufCnt = 0; + OMX_ERRORTYPE ret = OMX_ErrorNone; + DEBUG_PRINT("ENABLING OP PORT\n"); + // Send Enable command + OMX_SendCommand(dec_handle, OMX_CommandPortEnable, 1, 0); +#ifndef USE_EGL_IMAGE_TEST_APP + /* Allocate buffer on decoder's o/p port */ + portFmt.nPortIndex = 1; + if (use_external_pmem_buf) + { + DEBUG_PRINT("Enable op port: calling use_buffer_mult_fd\n"); + error = use_output_buffer_multiple_fd(dec_handle, + &pOutYUVBufHdrs, + portFmt.nPortIndex, + portFmt.nBufferSize, + portFmt.nBufferCountActual); + } + else + { + error = Allocate_Buffer(dec_handle, &pOutYUVBufHdrs, portFmt.nPortIndex, + portFmt.nBufferCountActual, portFmt.nBufferSize); + } + if (error != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("Error - OMX_AllocateBuffer Output buffer error\n"); + return -1; + } + else + { + DEBUG_PRINT("OMX_AllocateBuffer Output buffer success\n"); + free_op_buf_cnt = portFmt.nBufferCountActual; + } +#else + error = use_output_buffer(dec_handle, + &pOutYUVBufHdrs, + portFmt.nPortIndex, + portFmt.nBufferSize, + portFmt.nBufferCountActual); + free_op_buf_cnt = portFmt.nBufferCountActual; + if (error != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("ERROR - OMX_UseBuffer Input buffer failed"); + return -1; + } + else { + DEBUG_PRINT("OMX_UseBuffer Input buffer success\n"); + } + +#endif + // wait for enable event to come back + wait_for_event(); + if (currentStatus == ERROR_STATE) + { + do_freeHandle_and_clean_up(true); + return -1; + } + if (pOutYUVBufHdrs == NULL) + { + DEBUG_PRINT_ERROR("Error - pOutYUVBufHdrs is NULL\n"); + return -1; + } + for(bufCnt=0; bufCnt < portFmt.nBufferCountActual; ++bufCnt) { + DEBUG_PRINT("OMX_FillThisBuffer on output buf no.%d\n",bufCnt); + if (pOutYUVBufHdrs[bufCnt] == NULL) + { + DEBUG_PRINT_ERROR("Error - pOutYUVBufHdrs[%d] is NULL\n", bufCnt); + return -1; + } + pOutYUVBufHdrs[bufCnt]->nOutputPortIndex = 1; + pOutYUVBufHdrs[bufCnt]->nFlags &= ~OMX_BUFFERFLAG_EOS; + ret = OMX_FillThisBuffer(dec_handle, pOutYUVBufHdrs[bufCnt]); + if (OMX_ErrorNone != ret) { + DEBUG_PRINT_ERROR("ERROR - OMX_FillThisBuffer failed with result %d\n", ret); + } + else + { + DEBUG_PRINT("OMX_FillThisBuffer success!\n"); + free_op_buf_cnt--; + } + } + DEBUG_PRINT("OP PORT ENABLED!\n"); + return 0; +} + +int output_port_reconfig() +{ + DEBUG_PRINT("PORT_SETTING_CHANGE_STATE\n"); + if (disable_output_port() != 0) + return -1; + + /* Port for which the Client needs to obtain info */ + portFmt.nPortIndex = 1; + OMX_GetParameter(dec_handle,OMX_IndexParamPortDefinition,&portFmt); + DEBUG_PRINT("Min Buffer Count=%d", portFmt.nBufferCountMin); + DEBUG_PRINT("Buffer Size=%d", portFmt.nBufferSize); + if(OMX_DirOutput != portFmt.eDir) { + DEBUG_PRINT_ERROR("Error - Expect Output Port\n"); + return -1; + } + height = portFmt.format.video.nFrameHeight; + width = portFmt.format.video.nFrameWidth; + stride = portFmt.format.video.nStride; + sliceheight = portFmt.format.video.nSliceHeight; + + if (displayYuv == 2) + { + DEBUG_PRINT("Reconfiguration at middle of playback..."); + close_display(); + if (open_display() != 0) + { + printf("\n Error opening display! Video won't be displayed..."); + displayYuv = 0; + } + } + + if (displayYuv) + overlay_set(); + + if (enable_output_port() != 0) + return -1; + DEBUG_PRINT("PORT_SETTING_CHANGE DONE!\n"); + return 0; +} + +void free_output_buffers() +{ + int index = 0; + OMX_BUFFERHEADERTYPE *pBuffer = (OMX_BUFFERHEADERTYPE *)pop(fbd_queue); + while (pBuffer) { + DEBUG_PRINT("\n pOutYUVBufHdrs %p p_eglHeaders %p output_use_buffer %d", + pOutYUVBufHdrs,p_eglHeaders,output_use_buffer); + if(pOutYUVBufHdrs && p_eglHeaders && output_use_buffer) + { + index = pBuffer - pOutYUVBufHdrs[0]; + DEBUG_PRINT("\n Index of free buffer %d",index); + DEBUG_PRINT("\n Address freed %p size freed %d",pBuffer->pBuffer, + pBuffer->nAllocLen); + munmap((void *)use_buf_virt_addr[index],pBuffer->nAllocLen); + if(p_eglHeaders[index]) + { + close(p_eglHeaders[index]->pmem_fd); + free(p_eglHeaders[index]); + p_eglHeaders[index] = NULL; + } + } + + if (pOutYUVBufHdrs && use_external_pmem_buf) + { + index = pBuffer - pOutYUVBufHdrs[0]; + DEBUG_PRINT("\n Address freed %p size freed %d,virt=0x%x,pmem_fd=0x%x", + pBuffer->pBuffer, + pBuffer->nAllocLen, + use_buf_virt_addr[index], + pPMEMInfo[index].pmem_fd); + munmap((void *)use_buf_virt_addr[index],pBuffer->nAllocLen); + getFreePmem(); + use_buf_virt_addr[index] = -1; + if (&pPMEMInfo[index]) + { + close(pPMEMInfo[index].pmem_fd); + pPMEMInfo[index].pmem_fd = -1; + } + } + DEBUG_PRINT("\n Free output buffer"); + OMX_FreeBuffer(dec_handle, 1, pBuffer); + pBuffer = (OMX_BUFFERHEADERTYPE *)pop(fbd_queue); + } +} + +#ifndef USE_ION +static bool align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size, + OMX_U32 alignment) +{ + struct pmem_allocation allocation; + allocation.size = buffer_size; + allocation.align = clip2(alignment); + + if (allocation.align < 4096) + { + allocation.align = 4096; + } + if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) + { + DEBUG_PRINT_ERROR("\n Aligment failed with pmem driver"); + return false; + } + return true; +} +#endif + +int open_display() +{ +#ifdef _ANDROID_ + DEBUG_PRINT("\n Opening /dev/graphics/fb0"); + fb_fd = open("/dev/graphics/fb0", O_RDWR); +#else + DEBUG_PRINT("\n Opening /dev/fb0"); + fb_fd = open("/dev/fb0", O_RDWR); +#endif + if (fb_fd < 0) { + printf("[omx_vdec_test] - ERROR - can't open framebuffer!\n"); + return -1; + } + + DEBUG_PRINT("\n fb_fd = %d", fb_fd); + if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0) + { + printf("[omx_vdec_test] - ERROR - can't retrieve fscreenInfo!\n"); + close(fb_fd); + return -1; + } + if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) + { + printf("[omx_vdec_test] - ERROR - can't retrieve vscreenInfo!\n"); + close(fb_fd); + return -1; + } + return 0; +} + +void close_display() +{ + overlay_unset(); + close(fb_fd); + fb_fd = -1; +} + +void getFreePmem() +{ +#ifndef USE_ION + int ret = -1; + /*Open pmem device and query free pmem*/ + int pmem_fd = open (PMEM_DEVICE,O_RDWR); + + if(pmem_fd < 0) { + ALOGE("Unable to open pmem device"); + return; + } + struct pmem_freespace fs; + ret = ioctl(pmem_fd, PMEM_GET_FREE_SPACE, &fs); + if(ret) { + ALOGE("IOCTL to query pmem free space failed"); + goto freespace_query_failed; + } + ALOGE("Available free space %lx largest chunk %lx\n", fs.total, fs.largest); +freespace_query_failed: + close(pmem_fd); +#endif +} diff --git a/mm-video/vidc/venc/Android.mk b/mm-video/vidc/venc/Android.mk new file mode 100644 index 0000000..02b6142 --- /dev/null +++ b/mm-video/vidc/venc/Android.mk @@ -0,0 +1,149 @@ +ifneq ($(BUILD_TINY_ANDROID),true) + +ROOT_DIR := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_PATH:= $(ROOT_DIR) + +# --------------------------------------------------------------------------------- +# Common definitons +# --------------------------------------------------------------------------------- + +libmm-venc-def := -g -O3 -Dlrintf=_ffix_r +libmm-venc-def += -D__align=__alignx +libmm-venc-def += -D__alignx\(x\)=__attribute__\(\(__aligned__\(x\)\)\) +libmm-venc-def += -DT_ARM +libmm-venc-def += -Dinline=__inline +libmm-venc-def += -D_ANDROID_ +libmm-venc-def += -UENABLE_DEBUG_LOW +#libmm-venc-def += -DENABLE_DEBUG_HIGH +libmm-venc-def += -DENABLE_DEBUG_ERROR +libmm-venc-def += -UINPUT_BUFFER_LOG +libmm-venc-def += -UOUTPUT_BUFFER_LOG +libmm-venc-def += -USINGLE_ENCODER_INSTANCE +ifeq ($(TARGET_BOARD_PLATFORM),msm8660) +libmm-venc-def += -DMAX_RES_1080P +libmm-venc-def += -UENABLE_GET_SYNTAX_HDR +endif +ifeq ($(TARGET_BOARD_PLATFORM),msm8960) +libmm-venc-def += -DMAX_RES_1080P +libmm-venc-def += -DMAX_RES_1080P_EBI +libmm-venc-def += -UENABLE_GET_SYNTAX_HDR +endif +ifeq ($(TARGET_BOARD_PLATFORM),msm8974) +libmm-venc-def += -DMAX_RES_1080P +libmm-venc-def += -DMAX_RES_1080P_EBI +libOmxVdec-def += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT +libmm-venc-def += -D_MSM8974_ +endif +ifeq ($(TARGET_BOARD_PLATFORM),msm7627a) +libmm-venc-def += -DMAX_RES_720P +endif +ifeq ($(TARGET_BOARD_PLATFORM),msm7x30) +libmm-venc-def += -DMAX_RES_720P +endif +ifeq ($(TARGET_USES_ION),true) +libmm-venc-def += -DUSE_ION +endif +libmm-venc-def += -D_ANDROID_ICS_ +# --------------------------------------------------------------------------------- +# Make the Shared library (libOmxVenc) +# --------------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +libmm-venc-inc := bionic/libc/include +libmm-venc-inc += bionic/libstdc++/include +libmm-venc-inc += $(LOCAL_PATH)/inc +libmm-venc-inc += $(OMX_VIDEO_PATH)/vidc/common/inc +libmm-venc-inc += hardware/qcom/media-legacy/mm-core/inc +#libmm-venc-inc += bionic/libc/kernel/common/linux +libmm-venc-inc += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +libmm-venc-inc += hardware/qcom/media-legacy/libstagefrighthw +libmm-venc-inc += hardware/qcom/display-legacy/libgralloc +libmm-venc-inc += frameworks/native/include/media/hardware +libmm-venc-inc += frameworks/native/include/media/openmax + + +LOCAL_MODULE := libOmxVenc +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libmm-venc-def) +LOCAL_C_INCLUDES := $(libmm-venc-inc) + +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := liblog libutils libbinder libcutils + +LOCAL_SRC_FILES := src/omx_video_base.cpp +LOCAL_SRC_FILES += src/omx_video_encoder.cpp +ifeq ($(TARGET_BOARD_PLATFORM),msm8974) +LOCAL_SRC_FILES += src/video_encoder_device_msm8974.cpp +else +LOCAL_SRC_FILES += src/video_encoder_device.cpp +endif + + +LOCAL_SRC_FILES += ../common/src/extra_data_handler.cpp + +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + +include $(BUILD_SHARED_LIBRARY) + +# ----------------------------------------------------------------------------- +# # Make the apps-test (mm-venc-omx-test720p) +# ----------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +mm-venc-test720p-inc := $(TARGET_OUT_HEADERS)/mm-core +mm-venc-test720p-inc += $(LOCAL_PATH)/inc +mm-venc-test720p-inc += $(OMX_VIDEO_PATH)/vidc/common/inc +mm-venc-test720p-inc += hardware/qcom/media-legacy/mm-core/inc +mm-venc-test720p-inc += hardware/qcom/display-legacy/libgralloc + +LOCAL_MODULE := mm-venc-omx-test720p +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := $(libmm-venc-def) +LOCAL_C_INCLUDES := $(mm-venc-test720p-inc) +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr +LOCAL_PRELINK_MODULE := false +LOCAL_SHARED_LIBRARIES := libmm-omxcore libOmxVenc libbinder + +LOCAL_SRC_FILES := test/venc_test.cpp +LOCAL_SRC_FILES += test/camera_test.cpp +LOCAL_SRC_FILES += test/venc_util.c +LOCAL_SRC_FILES += test/fb_test.c + +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + +include $(BUILD_EXECUTABLE) + +# ----------------------------------------------------------------------------- +# Make the apps-test (mm-video-driver-test) +# ----------------------------------------------------------------------------- + +include $(CLEAR_VARS) + +venc-test-inc += $(LOCAL_PATH)/inc +venc-test-inc += hardware/qcom/display-legacy/libgralloc + +LOCAL_MODULE := mm-video-encdrv-test +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := $(venc-test-inc) +LOCAL_C_INCLUDES += hardware/qcom/media-legacy/mm-core/inc + +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr +LOCAL_PRELINK_MODULE := false + +LOCAL_SRC_FILES := test/video_encoder_test.c +LOCAL_SRC_FILES += test/queue.c + +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + +include $(BUILD_EXECUTABLE) + +endif #BUILD_TINY_ANDROID + +# --------------------------------------------------------------------------------- +# END +# --------------------------------------------------------------------------------- + diff --git a/mm-video/vidc/venc/inc/camera_test.h b/mm-video/vidc/venc/inc/camera_test.h new file mode 100755 index 0000000..f206c61 --- /dev/null +++ b/mm-video/vidc/venc/inc/camera_test.h @@ -0,0 +1,58 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef _CAMERA_TEST_H +#define _CAMERA_TEST_H + +#define EXTERN_C_START extern "C" { +#define EXTERN_C_END } + +#ifdef __cplusplus +EXTERN_C_START +#endif + +typedef void (*CameraPreviewCallback)(int nFD, + int nOffset, + void* pPhys, + void* pVirt, + long long nTimeStamp); + + +int CameraTest_Initialize(int nFrameRate, + int nFrameWidth, + int nFrameHeight, + CameraPreviewCallback pfnPreviewCallback); +int CameraTest_Run(); +int CameraTest_ReleaseFrame(void* pPhys, void* pVirt); +int CameraTest_Exit(); + + +#ifdef __cplusplus +EXTERN_C_END +#endif + +#endif diff --git a/mm-video/vidc/venc/inc/fb_test.h b/mm-video/vidc/venc/inc/fb_test.h new file mode 100755 index 0000000..1ebc76a --- /dev/null +++ b/mm-video/vidc/venc/inc/fb_test.h @@ -0,0 +1,48 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef _FB_TEST_H +#define _FB_TEST_H + +#ifdef __cplusplus +extern "C" { +#endif + + +int FBTest_Initialize(int nFrameWidth, + int nFrameHeight); +int FBTest_DisplayImage(int nPmemFd, int nOffset); +int FBTest_Exit(); + +int FBTest_RunTest(); + +#ifdef __cplusplus +} +#endif + + +#endif // _FB_TEST_H diff --git a/mm-video/vidc/venc/inc/omx_video_base.h b/mm-video/vidc/venc/inc/omx_video_base.h new file mode 100644 index 0000000..ee050ec --- /dev/null +++ b/mm-video/vidc/venc/inc/omx_video_base.h @@ -0,0 +1,570 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#ifndef __OMX_VIDEO_BASE_H__ +#define __OMX_VIDEO_BASE_H__ +/*============================================================================ + O p e n M A X Component + Video Encoder + +*//** @file comx_video_base.h + This module contains the class definition for openMAX decoder component. + +*//*========================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +#define LOG_TAG "OMX-VENC-720p" +#include +#include +#include +#ifdef _ANDROID_ + #include +#ifdef _ANDROID_ICS_ + #include "QComOMXMetadata.h" +#endif +#endif // _ANDROID_ +#include +#include +#include +#include "OMX_Core.h" +#include "OMX_QCOMExtns.h" +#include "qc_omx_component.h" +#include "omx_video_common.h" +#include "extra_data_handler.h" +#include + +#ifdef _ANDROID_ +using namespace android; +// local pmem heap object +class VideoHeap : public MemoryHeapBase +{ +public: + VideoHeap(int fd, size_t size, void* base); + virtual ~VideoHeap() {} +}; + +#include +#ifdef ENABLE_DEBUG_LOW +#define DEBUG_PRINT_LOW ALOGV +#else +#define DEBUG_PRINT_LOW +#endif +#ifdef ENABLE_DEBUG_HIGH +#define DEBUG_PRINT_HIGH ALOGV +#else +#define DEBUG_PRINT_HIGH +#endif +#ifdef ENABLE_DEBUG_ERROR +#define DEBUG_PRINT_ERROR ALOGE +#else +#define DEBUG_PRINT_ERROR +#endif + +#else //_ANDROID_ +#define DEBUG_PRINT_LOW +#define DEBUG_PRINT_HIGH +#define DEBUG_PRINT_ERROR +#endif // _ANDROID_ + +#ifdef _MSM8974_ +#define DEBUG_PRINT_LOW +#define DEBUG_PRINT_HIGH printf +#define DEBUG_PRINT_ERROR printf +#endif + +#ifdef USE_ION + static const char* MEM_DEVICE = "/dev/ion"; + #ifdef MAX_RES_720P + #define MEM_HEAP_ID ION_CAMERA_HEAP_ID + #else + #define MEM_HEAP_ID ION_CP_MM_HEAP_ID + #endif +#elif MAX_RES_720P +static const char* MEM_DEVICE = "/dev/pmem_adsp"; +#elif MAX_RES_1080P_EBI +static const char* MEM_DEVICE = "/dev/pmem_adsp"; +#elif MAX_RES_1080P +static const char* MEM_DEVICE = "/dev/pmem_smipool"; +#else +#error MEM_DEVICE cannot be determined. +#endif + +////////////////////////////////////////////////////////////////////////////// +// Module specific globals +////////////////////////////////////////////////////////////////////////////// + +#define OMX_SPEC_VERSION 0x00000101 + + +////////////////////////////////////////////////////////////////////////////// +// Macros +////////////////////////////////////////////////////////////////////////////// +#define PrintFrameHdr(bufHdr) DEBUG_PRINT("bufHdr %x buf %x size %d TS %d\n",\ + (unsigned) bufHdr,\ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->pBuffer,\ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nFilledLen,\ + (unsigned)((OMX_BUFFERHEADERTYPE *)bufHdr)->nTimeStamp) + +// BitMask Management logic +#define BITS_PER_BYTE 32 +#define BITMASK_SIZE(mIndex) (((mIndex) + BITS_PER_BYTE - 1)/BITS_PER_BYTE) +#define BITMASK_OFFSET(mIndex) ((mIndex)/BITS_PER_BYTE) +#define BITMASK_FLAG(mIndex) (1 << ((mIndex) % BITS_PER_BYTE)) +#define BITMASK_CLEAR(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \ + &= ~(BITMASK_FLAG(mIndex)) +#define BITMASK_SET(mArray,mIndex) (mArray)[BITMASK_OFFSET(mIndex)] \ + |= BITMASK_FLAG(mIndex) +#define BITMASK_PRESENT(mArray,mIndex) ((mArray)[BITMASK_OFFSET(mIndex)] \ + & BITMASK_FLAG(mIndex)) +#define BITMASK_ABSENT(mArray,mIndex) (((mArray)[BITMASK_OFFSET(mIndex)] \ + & BITMASK_FLAG(mIndex)) == 0x0) +#define BITMASK_PRESENT(mArray,mIndex) ((mArray)[BITMASK_OFFSET(mIndex)] \ + & BITMASK_FLAG(mIndex)) +#define BITMASK_ABSENT(mArray,mIndex) (((mArray)[BITMASK_OFFSET(mIndex)] \ + & BITMASK_FLAG(mIndex)) == 0x0) +#ifdef _ANDROID_ICS_ +#define MAX_NUM_INPUT_BUFFERS 32 +#endif +void* message_thread(void *); +// OMX video class +class omx_video: public qc_omx_component +{ +protected: +#ifdef _ANDROID_ICS_ + bool get_syntaxhdr_enable; + bool meta_mode_enable; + encoder_media_buffer_type meta_buffers[MAX_NUM_INPUT_BUFFERS]; + OMX_BUFFERHEADERTYPE meta_buffer_hdr[MAX_NUM_INPUT_BUFFERS]; + bool mUseProxyColorFormat; +#endif +public: + omx_video(); // constructor + virtual ~omx_video(); // destructor + + // virtual int async_message_process (void *context, void* message); + void process_event_cb(void *ctxt,unsigned char id); + + OMX_ERRORTYPE allocate_buffer( + OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes + ); + + + virtual OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE hComp)= 0; + + virtual OMX_ERRORTYPE component_init(OMX_STRING role)= 0; + + virtual OMX_U32 dev_stop(void) = 0; + virtual OMX_U32 dev_pause(void) = 0; + virtual OMX_U32 dev_start(void) = 0; + virtual OMX_U32 dev_flush(unsigned) = 0; + virtual OMX_U32 dev_resume(void) = 0; + virtual OMX_U32 dev_start_done(void) = 0; + virtual OMX_U32 dev_stop_done(void) = 0; + virtual bool dev_use_buf(void *,unsigned,unsigned) = 0; + virtual bool dev_free_buf(void *,unsigned) = 0; + virtual bool dev_empty_buf(void *, void *,unsigned,unsigned) = 0; + virtual bool dev_fill_buf(void *buffer, void *,unsigned,unsigned) = 0; + virtual bool dev_get_buf_req(OMX_U32 *,OMX_U32 *,OMX_U32 *,OMX_U32) = 0; + virtual bool dev_get_seq_hdr(void *, unsigned, unsigned *) = 0; + virtual bool dev_loaded_start(void) = 0; + virtual bool dev_loaded_stop(void) = 0; + virtual bool dev_loaded_start_done(void) = 0; + virtual bool dev_loaded_stop_done(void) = 0; +#ifdef _ANDROID_ICS_ + void omx_release_meta_buffer(OMX_BUFFERHEADERTYPE *buffer); +#endif + OMX_ERRORTYPE component_role_enum( + OMX_HANDLETYPE hComp, + OMX_U8 *role, + OMX_U32 index + ); + + OMX_ERRORTYPE component_tunnel_request( + OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_HANDLETYPE peerComponent, + OMX_U32 peerPort, + OMX_TUNNELSETUPTYPE *tunnelSetup + ); + + OMX_ERRORTYPE empty_this_buffer( + OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer + ); + + + + OMX_ERRORTYPE fill_this_buffer( + OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer + ); + + + OMX_ERRORTYPE free_buffer( + OMX_HANDLETYPE hComp, + OMX_U32 port, + OMX_BUFFERHEADERTYPE *buffer + ); + + OMX_ERRORTYPE get_component_version( + OMX_HANDLETYPE hComp, + OMX_STRING componentName, + OMX_VERSIONTYPE *componentVersion, + OMX_VERSIONTYPE *specVersion, + OMX_UUIDTYPE *componentUUID + ); + + OMX_ERRORTYPE get_config( + OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData + ); + + OMX_ERRORTYPE get_extension_index( + OMX_HANDLETYPE hComp, + OMX_STRING paramName, + OMX_INDEXTYPE *indexType + ); + + OMX_ERRORTYPE get_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + + OMX_ERRORTYPE get_state(OMX_HANDLETYPE hComp, + OMX_STATETYPE *state); + + + + OMX_ERRORTYPE send_command(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + + + OMX_ERRORTYPE set_callbacks(OMX_HANDLETYPE hComp, + OMX_CALLBACKTYPE *callbacks, + OMX_PTR appData); + + virtual OMX_ERRORTYPE set_config(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData) = 0; + + virtual OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData) =0; + + OMX_ERRORTYPE use_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes, + OMX_U8 *buffer); + + + OMX_ERRORTYPE use_EGL_image(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + void * eglImage); + + + + int m_pipe_in; + int m_pipe_out; + + pthread_t msg_thread_id; + pthread_t async_thread_id; + + OMX_U8 m_nkind[128]; + + + //int *input_pmem_fd; + //int *output_pmem_fd; + struct pmem *m_pInput_pmem; + struct pmem *m_pOutput_pmem; +#ifdef USE_ION + struct venc_ion *m_pInput_ion; + struct venc_ion *m_pOutput_ion; +#endif + + + +public: + // Bit Positions + enum flags_bit_positions + { + // Defer transition to IDLE + OMX_COMPONENT_IDLE_PENDING =0x1, + // Defer transition to LOADING + OMX_COMPONENT_LOADING_PENDING =0x2, + // First Buffer Pending + OMX_COMPONENT_FIRST_BUFFER_PENDING =0x3, + // Second Buffer Pending + OMX_COMPONENT_SECOND_BUFFER_PENDING =0x4, + // Defer transition to Enable + OMX_COMPONENT_INPUT_ENABLE_PENDING =0x5, + // Defer transition to Enable + OMX_COMPONENT_OUTPUT_ENABLE_PENDING =0x6, + // Defer transition to Disable + OMX_COMPONENT_INPUT_DISABLE_PENDING =0x7, + // Defer transition to Disable + OMX_COMPONENT_OUTPUT_DISABLE_PENDING =0x8, + //defer flush notification + OMX_COMPONENT_OUTPUT_FLUSH_PENDING =0x9, + OMX_COMPONENT_INPUT_FLUSH_PENDING =0xA, + OMX_COMPONENT_PAUSE_PENDING =0xB, + OMX_COMPONENT_EXECUTE_PENDING =0xC, + OMX_COMPONENT_LOADED_START_PENDING = 0xD, + OMX_COMPONENT_LOADED_STOP_PENDING = 0xF, + + }; + + // Deferred callback identifiers + enum + { + //Event Callbacks from the venc component thread context + OMX_COMPONENT_GENERATE_EVENT = 0x1, + //Buffer Done callbacks from the venc component thread context + OMX_COMPONENT_GENERATE_BUFFER_DONE = 0x2, + //Frame Done callbacks from the venc component thread context + OMX_COMPONENT_GENERATE_FRAME_DONE = 0x3, + //Buffer Done callbacks from the venc component thread context + OMX_COMPONENT_GENERATE_FTB = 0x4, + //Frame Done callbacks from the venc component thread context + OMX_COMPONENT_GENERATE_ETB = 0x5, + //Command + OMX_COMPONENT_GENERATE_COMMAND = 0x6, + //Push-Pending Buffers + OMX_COMPONENT_PUSH_PENDING_BUFS = 0x7, + // Empty Buffer Done callbacks + OMX_COMPONENT_GENERATE_EBD = 0x8, + //Flush Event Callbacks from the venc component thread context + OMX_COMPONENT_GENERATE_EVENT_FLUSH = 0x9, + OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH = 0x0A, + OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH = 0x0B, + OMX_COMPONENT_GENERATE_FBD = 0xc, + OMX_COMPONENT_GENERATE_START_DONE = 0xD, + OMX_COMPONENT_GENERATE_PAUSE_DONE = 0xE, + OMX_COMPONENT_GENERATE_RESUME_DONE = 0xF, + OMX_COMPONENT_GENERATE_STOP_DONE = 0x10, + OMX_COMPONENT_GENERATE_HARDWARE_ERROR = 0x11 + }; + + struct omx_event + { + unsigned param1; + unsigned param2; + unsigned id; + }; + + struct omx_cmd_queue + { + omx_event m_q[OMX_CORE_CONTROL_CMDQ_SIZE]; + unsigned m_read; + unsigned m_write; + unsigned m_size; + + omx_cmd_queue(); + ~omx_cmd_queue(); + bool insert_entry(unsigned p1, unsigned p2, unsigned id); + bool pop_entry(unsigned *p1,unsigned *p2, unsigned *id); + // get msgtype of the first ele from the queue + unsigned get_q_msg_type(); + + }; + + bool allocate_done(void); + bool allocate_input_done(void); + bool allocate_output_done(void); + + OMX_ERRORTYPE free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr); + OMX_ERRORTYPE free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr); + + OMX_ERRORTYPE allocate_input_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes); +#ifdef _ANDROID_ICS_ + OMX_ERRORTYPE allocate_input_meta_buffer(OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_PTR appData, + OMX_U32 bytes); +#endif + OMX_ERRORTYPE allocate_output_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port,OMX_PTR appData, + OMX_U32 bytes); + + OMX_ERRORTYPE use_input_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes, + OMX_U8 *buffer); + + OMX_ERRORTYPE use_output_buffer(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_U32 port, + OMX_PTR appData, + OMX_U32 bytes, + OMX_U8 *buffer); + + bool execute_omx_flush(OMX_U32); + bool execute_output_flush(void); + bool execute_input_flush(void); + OMX_ERRORTYPE empty_buffer_done(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE * buffer); + + OMX_ERRORTYPE fill_buffer_done(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE * buffer); + OMX_ERRORTYPE empty_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + + OMX_ERRORTYPE fill_this_buffer_proxy(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE *buffer); + bool release_done(); + + bool release_output_done(); + bool release_input_done(); + + OMX_ERRORTYPE send_command_proxy(OMX_HANDLETYPE hComp, + OMX_COMMANDTYPE cmd, + OMX_U32 param1, + OMX_PTR cmdData); + bool post_event( unsigned int p1, + unsigned int p2, + unsigned int id + ); + OMX_ERRORTYPE get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType); + inline void omx_report_error () + { + if(m_pCallbacks.EventHandler && !m_error_propogated) + { + m_error_propogated = true; + m_pCallbacks.EventHandler(&m_cmp,m_app_data, + OMX_EventError,OMX_ErrorHardware,0,NULL); + } + } + + void complete_pending_buffer_done_cbs(); + + //************************************************************* + //*******************MEMBER VARIABLES ************************* + //************************************************************* + + pthread_mutex_t m_lock; + sem_t m_cmd_lock; + bool m_error_propogated; + + //sem to handle the minimum procesing of commands + + + // compression format + //OMX_VIDEO_CODINGTYPE eCompressionFormat; + // OMX State + OMX_STATETYPE m_state; + // Application data + OMX_PTR m_app_data; + OMX_BOOL m_use_input_pmem; + OMX_BOOL m_use_output_pmem; + // Application callbacks + OMX_CALLBACKTYPE m_pCallbacks; + OMX_PORT_PARAM_TYPE m_sPortParam; + OMX_VIDEO_PARAM_PROFILELEVELTYPE m_sParamProfileLevel; + OMX_VIDEO_PARAM_PORTFORMATTYPE m_sInPortFormat; + OMX_VIDEO_PARAM_PORTFORMATTYPE m_sOutPortFormat; + OMX_PARAM_PORTDEFINITIONTYPE m_sInPortDef; + OMX_PARAM_PORTDEFINITIONTYPE m_sOutPortDef; + OMX_VIDEO_PARAM_MPEG4TYPE m_sParamMPEG4; + OMX_VIDEO_PARAM_H263TYPE m_sParamH263; + OMX_VIDEO_PARAM_AVCTYPE m_sParamAVC; + OMX_PORT_PARAM_TYPE m_sPortParam_img; + OMX_PORT_PARAM_TYPE m_sPortParam_audio; + OMX_VIDEO_CONFIG_BITRATETYPE m_sConfigBitrate; + OMX_CONFIG_FRAMERATETYPE m_sConfigFramerate; + OMX_VIDEO_PARAM_BITRATETYPE m_sParamBitrate; + OMX_PRIORITYMGMTTYPE m_sPriorityMgmt; + OMX_PARAM_BUFFERSUPPLIERTYPE m_sInBufSupplier; + OMX_PARAM_BUFFERSUPPLIERTYPE m_sOutBufSupplier; + OMX_CONFIG_ROTATIONTYPE m_sConfigFrameRotation; + OMX_CONFIG_INTRAREFRESHVOPTYPE m_sConfigIntraRefreshVOP; + OMX_VIDEO_PARAM_QUANTIZATIONTYPE m_sSessionQuantization; + OMX_VIDEO_PARAM_AVCSLICEFMO m_sAVCSliceFMO; + QOMX_VIDEO_INTRAPERIODTYPE m_sIntraperiod; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE m_sErrorCorrection; + OMX_VIDEO_PARAM_INTRAREFRESHTYPE m_sIntraRefresh; + OMX_U32 m_sExtraData; + OMX_U32 m_sDebugSliceinfo; + + // fill this buffer queue + omx_cmd_queue m_ftb_q; + // Command Q for rest of the events + omx_cmd_queue m_cmd_q; + omx_cmd_queue m_etb_q; + // Input memory pointer + OMX_BUFFERHEADERTYPE *m_inp_mem_ptr; + // Output memory pointer + OMX_BUFFERHEADERTYPE *m_out_mem_ptr; + + bool input_flush_progress; + bool output_flush_progress; + bool input_use_buffer; + bool output_use_buffer; + int pending_input_buffers; + int pending_output_buffers; + + unsigned int m_out_bm_count; + unsigned int m_inp_bm_count; + unsigned int m_flags; + unsigned int m_etb_count; + unsigned int m_fbd_count; +#ifdef _ANDROID_ + // Heap pointer to frame buffers + sp m_heap_ptr; +#endif //_ANDROID_ + // to know whether Event Port Settings change has been triggered or not. + bool m_event_port_settings_sent; + OMX_U8 m_cRole[OMX_MAX_STRINGNAME_SIZE]; + extra_data_handler extra_data_handle; + +private: +#ifdef USE_ION + int alloc_map_ion_memory(int size,struct ion_allocation_data *alloc_data, + struct ion_fd_data *fd_data,int flag); + void free_ion_memory(struct venc_ion *buf_ion_info); +#endif +}; + +#endif // __OMX_VIDEO_BASE_H__ diff --git a/mm-video/vidc/venc/inc/omx_video_common.h b/mm-video/vidc/venc/inc/omx_video_common.h new file mode 100755 index 0000000..92ba24b --- /dev/null +++ b/mm-video/vidc/venc/inc/omx_video_common.h @@ -0,0 +1,85 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ + +#ifndef __OMX_VIDEO_COMMON_H__ +#define __OMX_VIDEO_COMMON_H__ +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#ifdef USE_ION +#include +#endif + +#define OMX_VIDEO_DEC_NUM_INPUT_BUFFERS 2 +#define OMX_VIDEO_DEC_NUM_OUTPUT_BUFFERS 2 + +#ifdef FEATURE_QTV_WVGA_ENABLE +#define OMX_VIDEO_DEC_INPUT_BUFFER_SIZE (256*1024) +#else +#define OMX_VIDEO_DEC_INPUT_BUFFER_SIZE (128*1024) +#endif + +#define OMX_CORE_CONTROL_CMDQ_SIZE 100 +#define OMX_CORE_QCIF_HEIGHT 144 +#define OMX_CORE_QCIF_WIDTH 176 +#define OMX_CORE_VGA_HEIGHT 480 +#define OMX_CORE_VGA_WIDTH 640 +#define OMX_CORE_WVGA_HEIGHT 480 +#define OMX_CORE_WVGA_WIDTH 800 + +enum PortIndexType +{ + PORT_INDEX_IN = 0, + PORT_INDEX_OUT = 1, + PORT_INDEX_BOTH = -1, + PORT_INDEX_NONE = -2 +}; + +struct pmem +{ + void *buffer; + int fd; + unsigned offset; + unsigned size; +}; +#ifdef USE_ION +struct venc_ion +{ + int ion_device_fd; + struct ion_fd_data fd_ion_data; + struct ion_allocation_data ion_alloc_data; +}; +#endif +#endif // __OMX_VIDEO_COMMON_H__ + + + + diff --git a/mm-video/vidc/venc/inc/omx_video_encoder.h b/mm-video/vidc/venc/inc/omx_video_encoder.h new file mode 100755 index 0000000..d0e595b --- /dev/null +++ b/mm-video/vidc/venc/inc/omx_video_encoder.h @@ -0,0 +1,83 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef __OMX_VENC__H +#define __OMX_VENC__H + +#include +#include "omx_video_base.h" +#ifdef _MSM8974_ +#include "video_encoder_device_msm8974.h" +#else +#include "video_encoder_device.h" +#endif + +extern "C" { + OMX_API void * get_omx_component_factory_fn(void); +} + +class omx_venc: public omx_video +{ +public: + omx_venc(); //constructor + ~omx_venc(); //des + static int async_message_process (void *context, void* message); + OMX_ERRORTYPE component_init(OMX_STRING role); + OMX_ERRORTYPE set_parameter(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE paramIndex, + OMX_PTR paramData); + OMX_ERRORTYPE set_config(OMX_HANDLETYPE hComp, + OMX_INDEXTYPE configIndex, + OMX_PTR configData); + OMX_ERRORTYPE component_deinit(OMX_HANDLETYPE hComp); + //OMX strucutres + OMX_U32 m_nVenc_format; + class venc_dev *handle; + +private: + OMX_U32 dev_stop(void); + OMX_U32 dev_pause(void); + OMX_U32 dev_start(void); + OMX_U32 dev_flush(unsigned); + OMX_U32 dev_resume(void); + OMX_U32 dev_start_done(void); + OMX_U32 dev_stop_done(void); + bool dev_use_buf( void *,unsigned,unsigned); + bool dev_free_buf( void *,unsigned); + bool dev_empty_buf(void *, void *,unsigned,unsigned); + bool dev_fill_buf(void *, void *,unsigned,unsigned); + bool dev_get_buf_req(OMX_U32 *,OMX_U32 *,OMX_U32 *,OMX_U32); + bool dev_set_buf_req(OMX_U32 *,OMX_U32 *,OMX_U32 *,OMX_U32); + bool update_profile_level(); + bool dev_get_seq_hdr(void *, unsigned, unsigned *); + bool dev_loaded_start(void); + bool dev_loaded_stop(void); + bool dev_loaded_start_done(void); + bool dev_loaded_stop_done(void); +}; + +#endif //__OMX_VENC__H diff --git a/mm-video/vidc/venc/inc/queue.h b/mm-video/vidc/venc/inc/queue.h new file mode 100755 index 0000000..39c656a --- /dev/null +++ b/mm-video/vidc/venc/inc/queue.h @@ -0,0 +1,80 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef QUEUE_H +#define QUEUE_H + +#include +#include +#include +#include + +/* Message Queue structure */ +struct video_msgq +{ + /* Command to be executed */ + unsigned int cmd; + + unsigned int status; + + /* Client-specific data */ + void *clientdata; +}; + + +/* Thread & Message Queue information */ +struct video_queue_context +{ + /* Message Queue related members */ + pthread_mutex_t mutex; + sem_t sem_message; + int commandq_size; + int dataq_size; + struct video_msgq *ptr_dataq; + struct video_msgq *ptr_cmdq; + int write_dataq ; + int read_dataq; + int write_comq ; + int read_comq ; + +}; + +int check_if_queue_empty ( unsigned int queuetocheck,void* queuecontext ); + +struct video_msgq * queue_get_cmd ( void* queuecontext ); + + + +int queue_post_cmdq ( void *queuecontext, + struct video_msgq *post_msg + ); + +int queue_post_dataq ( void *queuecontext, + struct video_msgq *post_msg + ); + +#endif /* QUEUE_H */ diff --git a/mm-video/vidc/venc/inc/venc_util.h b/mm-video/vidc/venc/inc/venc_util.h new file mode 100755 index 0000000..1062591 --- /dev/null +++ b/mm-video/vidc/venc/inc/venc_util.h @@ -0,0 +1,53 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + V E N C _ U T I L. H + +DESCRIPTION + + +REFERENCES + + +============================================================================*/ + +#ifndef _VENC_UTIL_H +#define _VENC_UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +long long GetTimeStamp(); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mm-video/vidc/venc/inc/video_encoder_device.h b/mm-video/vidc/venc/inc/video_encoder_device.h new file mode 100755 index 0000000..25df71f --- /dev/null +++ b/mm-video/vidc/venc/inc/video_encoder_device.h @@ -0,0 +1,161 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef __OMX_VENC_DEV__ +#define __OMX_VENC_DEV__ + +#include "OMX_Types.h" +#include "OMX_Core.h" +#include "OMX_QCOMExtns.h" +#include "qc_omx_component.h" +#include "omx_video_common.h" +#include +#include +#include +#include +#define TIMEOUT 5000 +#define MAX_RECON_BUFFERS 4 + +void* async_venc_message_thread (void *); + +class venc_dev +{ +public: + venc_dev(class omx_venc *venc_class); //constructor + ~venc_dev(); //des + + bool venc_open(OMX_U32); + void venc_close(); + unsigned venc_stop(void); + unsigned venc_pause(void); + unsigned venc_start(void); + unsigned venc_flush(unsigned); +#ifdef _ANDROID_ICS_ + bool venc_set_meta_mode(bool); +#endif + unsigned venc_resume(void); + unsigned venc_start_done(void); + unsigned venc_stop_done(void); + bool venc_use_buf(void*, unsigned,unsigned); + bool venc_free_buf(void*, unsigned); + bool venc_empty_buf(void *, void *,unsigned,unsigned); + bool venc_fill_buf(void *, void *,unsigned,unsigned); + + bool venc_get_buf_req(unsigned long *,unsigned long *, + unsigned long *,unsigned long); + bool venc_set_buf_req(unsigned long *,unsigned long *, + unsigned long *,unsigned long); + bool venc_set_param(void *,OMX_INDEXTYPE); + bool venc_set_config(void *configData, OMX_INDEXTYPE index); + bool venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel); + bool venc_max_allowed_bitrate_check(OMX_U32 nTargetBitrate); + bool venc_get_seq_hdr(void *, unsigned, unsigned *); + bool venc_loaded_start(void); + bool venc_loaded_stop(void); + bool venc_loaded_start_done(void); + bool venc_loaded_stop_done(void); + OMX_U32 m_nDriver_fd; + bool m_profile_set; + bool m_level_set; + pthread_mutex_t loaded_start_stop_mlock; + pthread_cond_t loaded_start_stop_cond; + + struct recon_buffer { + unsigned char* virtual_address; + int pmem_fd; + int size; + int alignment; + int offset; +#ifdef USE_ION + int ion_device_fd; + struct ion_allocation_data alloc_data; + struct ion_fd_data ion_alloc_fd; +#endif + }; + + recon_buffer recon_buff[MAX_RECON_BUFFERS]; + int recon_buffers_count; + bool m_max_allowed_bitrate_check; + int m_eProfile; + int m_eLevel; + int etb_count; +private: + struct venc_basecfg m_sVenc_cfg; + struct venc_ratectrlcfg rate_ctrl; + struct venc_targetbitrate bitrate; + struct venc_intraperiod intra_period; + struct venc_profile codec_profile; + struct ven_profilelevel profile_level; + struct venc_switch set_param; + struct venc_voptimingcfg time_inc; + struct venc_allocatorproperty m_sInput_buff_property; + struct venc_allocatorproperty m_sOutput_buff_property; + struct venc_sessionqp session_qp; + struct venc_multiclicecfg multislice; + struct venc_entropycfg entropy; + struct venc_dbcfg dbkfilter; + struct venc_intrarefresh intra_refresh; + struct venc_headerextension hec; + struct venc_voptimingcfg voptimecfg; + struct venc_seqheader seqhdr; + + bool venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel); + bool venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames); + bool venc_set_target_bitrate(OMX_U32 nTargetBitrate, OMX_U32 config); + bool venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate); + bool venc_set_session_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp); + bool venc_set_extradata(OMX_U32 extra_data); + bool venc_set_encode_framerate(OMX_U32 encode_framerate, OMX_U32 config); + bool venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh); + bool venc_set_color_format(OMX_COLOR_FORMATTYPE color_format); + bool venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel); + bool venc_set_multislice_cfg(OMX_INDEXTYPE codec, OMX_U32 slicesize); + bool venc_set_entropy_config(OMX_BOOL enable, OMX_U32 i_cabac_level); + bool venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loop_filter); + bool venc_set_intra_refresh (OMX_VIDEO_INTRAREFRESHTYPE intrarefresh, OMX_U32 nMBs); + bool venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* error_resilience); + bool venc_set_voptiming_cfg(OMX_U32 nTimeIncRes); + void venc_config_print(); + bool venc_set_slice_delivery_mode(OMX_BOOL enable); +#ifdef MAX_RES_1080P + OMX_U32 pmem_free(); + OMX_U32 pmem_allocate(OMX_U32 size, OMX_U32 alignment, OMX_U32 count); + OMX_U32 venc_allocate_recon_buffers(); + inline int clip2(int x) + { + x = x -1; + x = x | x >> 1; + x = x | x >> 2; + x = x | x >> 4; + x = x | x >> 16; + x = x + 1; + return x; + } +#endif +}; + +#endif diff --git a/mm-video/vidc/venc/inc/video_encoder_device_msm8974.h b/mm-video/vidc/venc/inc/video_encoder_device_msm8974.h new file mode 100755 index 0000000..adf8fd4 --- /dev/null +++ b/mm-video/vidc/venc/inc/video_encoder_device_msm8974.h @@ -0,0 +1,288 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#ifndef __OMX_VENC_DEV__ +#define __OMX_VENC_DEV__ + +#include "OMX_Types.h" +#include "OMX_Core.h" +#include "OMX_QCOMExtns.h" +#include "qc_omx_component.h" +#include "omx_video_common.h" +#include "omx_video_base.h" +#include "omx_video_encoder.h" +#include +#include +#define TIMEOUT 5*60*1000 +#define MAX_RECON_BUFFERS 4 + +void* async_venc_message_thread (void *); + +struct msm_venc_switch{ + unsigned char status; +}; + +struct msm_venc_allocatorproperty{ + unsigned long mincount; + unsigned long maxcount; + unsigned long actualcount; + unsigned long datasize; + unsigned long suffixsize; + unsigned long alignment; + unsigned long bufpoolid; +}; + +struct msm_venc_basecfg{ + unsigned long input_width; + unsigned long input_height; + unsigned long dvs_width; + unsigned long dvs_height; + unsigned long codectype; + unsigned long fps_num; + unsigned long fps_den; + unsigned long targetbitrate; + unsigned long inputformat; +}; + +struct msm_venc_profile{ + unsigned long profile; +}; +struct msm_venc_profilelevel{ + unsigned long level; +}; + +struct msm_venc_sessionqp{ + unsigned long iframeqp; + unsigned long pframqp; + unsigned long bframqp; +}; + +struct msm_venc_qprange{ + unsigned long maxqp; + unsigned long minqp; +}; +struct msm_venc_intraperiod{ + unsigned long num_pframes; + unsigned long num_bframes; +}; +struct msm_venc_seqheader{ + unsigned char *hdrbufptr; + unsigned long bufsize; + unsigned long hdrlen; +}; + +struct msm_venc_capability{ + unsigned long codec_types; + unsigned long maxframe_width; + unsigned long maxframe_height; + unsigned long maxtarget_bitrate; + unsigned long maxframe_rate; + unsigned long input_formats; + unsigned char dvs; +}; + +struct msm_venc_entropycfg{ + unsigned longentropysel; + unsigned long cabacmodel; +}; + +struct msm_venc_dbcfg{ + unsigned long db_mode; + unsigned long slicealpha_offset; + unsigned long slicebeta_offset; +}; + +struct msm_venc_intrarefresh{ + unsigned long irmode; + unsigned long mbcount; +}; + +struct msm_venc_multiclicecfg{ + unsigned long mslice_mode; + unsigned long mslice_size; +}; + +struct msm_venc_bufferflush{ + unsigned long flush_mode; +}; + +struct msm_venc_ratectrlcfg{ + unsigned long rcmode; +}; + +struct msm_venc_voptimingcfg{ + unsigned long voptime_resolution; +}; +struct msm_venc_framerate{ + unsigned long fps_denominator; + unsigned long fps_numerator; +}; + +struct msm_venc_targetbitrate{ + unsigned long target_bitrate; +}; + + +struct msm_venc_rotation{ + unsigned long rotation; +}; + +struct msm_venc_timeout{ + unsigned long millisec; +}; + +struct msm_venc_headerextension{ + unsigned long header_extension; +}; + +class venc_dev +{ +public: + venc_dev(class omx_venc *venc_class); //constructor + ~venc_dev(); //des + + bool venc_open(OMX_U32); + void venc_close(); + unsigned venc_stop(void); + unsigned venc_pause(void); + unsigned venc_start(void); + unsigned venc_flush(unsigned); +#ifdef _ANDROID_ICS_ + bool venc_set_meta_mode(bool); +#endif + unsigned venc_resume(void); + unsigned venc_start_done(void); + unsigned venc_stop_done(void); + bool venc_use_buf(void*, unsigned,unsigned); + bool venc_free_buf(void*, unsigned); + bool venc_empty_buf(void *, void *,unsigned,unsigned); + bool venc_fill_buf(void *, void *,unsigned,unsigned); + + bool venc_get_buf_req(unsigned long *,unsigned long *, + unsigned long *,unsigned long); + bool venc_set_buf_req(unsigned long *,unsigned long *, + unsigned long *,unsigned long); + bool venc_set_param(void *,OMX_INDEXTYPE); + bool venc_set_config(void *configData, OMX_INDEXTYPE index); + bool venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel); + bool venc_get_seq_hdr(void *, unsigned, unsigned *); + bool venc_loaded_start(void); + bool venc_loaded_stop(void); + bool venc_loaded_start_done(void); + bool venc_loaded_stop_done(void); + OMX_U32 m_nDriver_fd; + bool m_profile_set; + bool m_level_set; + struct recon_buffer { + unsigned char* virtual_address; + int pmem_fd; + int size; + int alignment; + int offset; +#ifdef USE_ION + int ion_device_fd; + struct ion_allocation_data alloc_data; + struct ion_fd_data ion_alloc_fd; +#endif + }; + + recon_buffer recon_buff[MAX_RECON_BUFFERS]; + int recon_buffers_count; + bool m_max_allowed_bitrate_check; + int etb_count; + class omx_venc *venc_handle; +private: + struct msm_venc_basecfg m_sVenc_cfg; + struct msm_venc_ratectrlcfg rate_ctrl; + struct msm_venc_targetbitrate bitrate; + struct msm_venc_intraperiod intra_period; + struct msm_venc_profile codec_profile; + struct msm_venc_profilelevel profile_level; + struct msm_venc_switch set_param; + struct msm_venc_voptimingcfg time_inc; + struct msm_venc_allocatorproperty m_sInput_buff_property; + struct msm_venc_allocatorproperty m_sOutput_buff_property; + struct msm_venc_sessionqp session_qp; + struct msm_venc_multiclicecfg multislice; + struct msm_venc_entropycfg entropy; + struct msm_venc_dbcfg dbkfilter; + struct msm_venc_intrarefresh intra_refresh; + struct msm_venc_headerextension hec; + struct msm_venc_voptimingcfg voptimecfg; + + bool venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel); + bool venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames); + bool venc_set_target_bitrate(OMX_U32 nTargetBitrate, OMX_U32 config); + bool venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate); + bool venc_set_session_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp,OMX_U32 b_frame_qp); + bool venc_set_encode_framerate(OMX_U32 encode_framerate, OMX_U32 config); + bool venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh); + bool venc_set_color_format(OMX_COLOR_FORMATTYPE color_format); + bool venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel); + bool venc_set_multislice_cfg(OMX_INDEXTYPE codec, OMX_U32 slicesize); + bool venc_set_entropy_config(OMX_BOOL enable, OMX_U32 i_cabac_level); + bool venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loop_filter); + bool venc_set_intra_refresh (OMX_VIDEO_INTRAREFRESHTYPE intrarefresh, OMX_U32 nMBs); + bool venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* error_resilience); + bool venc_set_voptiming_cfg(OMX_U32 nTimeIncRes); + void venc_config_print(); +#ifdef MAX_RES_1080P + OMX_U32 pmem_free(); + OMX_U32 pmem_allocate(OMX_U32 size, OMX_U32 alignment, OMX_U32 count); + OMX_U32 venc_allocate_recon_buffers(); + inline int clip2(int x) + { + x = x -1; + x = x | x >> 1; + x = x | x >> 2; + x = x | x >> 4; + x = x | x >> 16; + x = x + 1; + return x; + } +#endif +}; + +enum instance_state { + MSM_VIDC_CORE_UNINIT_DONE = 0x0001, + MSM_VIDC_CORE_INIT, + MSM_VIDC_CORE_INIT_DONE, + MSM_VIDC_OPEN, + MSM_VIDC_OPEN_DONE, + MSM_VIDC_LOAD_RESOURCES, + MSM_VIDC_LOAD_RESOURCES_DONE, + MSM_VIDC_START, + MSM_VIDC_START_DONE, + MSM_VIDC_STOP, + MSM_VIDC_STOP_DONE, + MSM_VIDC_RELEASE_RESOURCES, + MSM_VIDC_RELEASE_RESOURCES_DONE, + MSM_VIDC_CLOSE, + MSM_VIDC_CLOSE_DONE, + MSM_VIDC_CORE_UNINIT, +}; +#endif diff --git a/mm-video/vidc/venc/inc/video_encoder_test.h b/mm-video/vidc/venc/inc/video_encoder_test.h new file mode 100755 index 0000000..1462db0 --- /dev/null +++ b/mm-video/vidc/venc/inc/video_encoder_test.h @@ -0,0 +1,76 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include +#include +#include "queue.h" +#include +#include +#include +#include +#include +#include +#include + +#define INPUT_BUFFER 0 +#define OUTPUT_BUFFER 1 + +struct video_encoder_context +{ + unsigned long input_width; + unsigned long input_height; + unsigned long codectype; + unsigned long fps_num; + unsigned long fps_den; + unsigned long targetbitrate; + unsigned long inputformat; + + struct venc_allocatorproperty input_buffer; + struct venc_allocatorproperty output_buffer; + struct venc_bufferpayload **ptr_inputbuffer; + struct venc_bufferpayload **ptr_outputbuffer; + struct video_queue_context queue_context; + int video_driver_fd; + + FILE * inputBufferFile; + FILE * outputBufferFile; + + pthread_t videothread_id; + pthread_t asyncthread_id; + sem_t sem_synchronize; +}; + +int init_encoder ( struct video_encoder_context *init_decode ); +int allocate_buffer ( unsigned int buffer_dir, + struct video_encoder_context *decode_context + ); +int free_buffer ( unsigned int buffer_dir, + struct video_encoder_context *decode_context + ); +int start_encoding (struct video_encoder_context *decode_context); +int stop_encoding (struct video_encoder_context *decode_context); +int deinit_encoder (struct video_encoder_context *init_decode); diff --git a/mm-video/vidc/venc/src/omx_video_base.cpp b/mm-video/vidc/venc/src/omx_video_base.cpp new file mode 100644 index 0000000..93d03cd --- /dev/null +++ b/mm-video/vidc/venc/src/omx_video_base.cpp @@ -0,0 +1,4339 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + O p e n M A X w r a p p e r s + O p e n M A X C o r e + +*//** @file omx_video_base.cpp + This module contains the implementation of the OpenMAX core & component. + +*//*========================================================================*/ + +////////////////////////////////////////////////////////////////////////////// +// Include Files +////////////////////////////////////////////////////////////////////////////// + +#include +#include "omx_video_base.h" +#include +#include +#include +#include +#include +#ifdef _ANDROID_ICS_ +#include +#include +#endif +#ifndef _ANDROID_ +#include +#define strlcpy g_strlcpy +#endif +#define H264_SUPPORTED_WIDTH (480) +#define H264_SUPPORTED_HEIGHT (368) + +#define MPEG4_SUPPORTED_WIDTH (480) +#define MPEG4_SUPPORTED_HEIGHT (368) + +#define VC1_SP_MP_START_CODE 0xC5000000 +#define VC1_SP_MP_START_CODE_MASK 0xFF000000 +#define VC1_AP_START_CODE 0x00000100 +#define VC1_AP_START_CODE_MASK 0xFFFFFF00 +#define VC1_STRUCT_C_PROFILE_MASK 0xF0 +#define VC1_STRUCT_B_LEVEL_MASK 0xE0000000 +#define VC1_SIMPLE_PROFILE 0 +#define VC1_MAIN_PROFILE 1 +#define VC1_ADVANCE_PROFILE 3 +#define VC1_SIMPLE_PROFILE_LOW_LEVEL 0 +#define VC1_SIMPLE_PROFILE_MED_LEVEL 2 +#define VC1_STRUCT_C_LEN 4 +#define VC1_STRUCT_C_POS 8 +#define VC1_STRUCT_A_POS 12 +#define VC1_STRUCT_B_POS 24 +#define VC1_SEQ_LAYER_SIZE 36 + +typedef struct OMXComponentCapabilityFlagsType +{ + ////////////////// OMX COMPONENT CAPABILITY RELATED MEMBERS + OMX_BOOL iIsOMXComponentMultiThreaded; + OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc; + OMX_BOOL iOMXComponentSupportsExternalInputBufferAlloc; + OMX_BOOL iOMXComponentSupportsMovableInputBuffers; + OMX_BOOL iOMXComponentSupportsPartialFrames; + OMX_BOOL iOMXComponentUsesNALStartCodes; + OMX_BOOL iOMXComponentCanHandleIncompleteFrames; + OMX_BOOL iOMXComponentUsesFullAVCFrames; + +} OMXComponentCapabilityFlagsType; +#define OMX_COMPONENT_CAPABILITY_TYPE_INDEX 0xFF7A347 + +#ifdef OUTPUT_BUFFER_LOG +extern FILE *outputBufferFile1; +#endif + +void* message_thread(void *input) +{ + omx_video* omx = reinterpret_cast(input); + unsigned char id; + int n; + + DEBUG_PRINT_LOW("omx_venc: message thread start\n"); + prctl(PR_SET_NAME, (unsigned long)"VideoEncMsgThread", 0, 0, 0); + while(1) + { + n = read(omx->m_pipe_in, &id, 1); + if(0 == n) + { + break; + } + + if(1 == n) + { + omx->process_event_cb(omx, id); + } +#ifdef QLE_BUILD + if(n < 0) break; +#else + if((n < 0) && (errno != EINTR)) break; +#endif + } + DEBUG_PRINT_LOW("omx_venc: message thread stop\n"); + return 0; +} + +void post_message(omx_video *omx, unsigned char id) +{ + DEBUG_PRINT_LOW("omx_venc: post_message %d\n", id); + write(omx->m_pipe_out, &id, 1); +} + +// omx_cmd_queue destructor +omx_video::omx_cmd_queue::~omx_cmd_queue() +{ + // Nothing to do +} + +// omx cmd queue constructor +omx_video::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) +{ + memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); +} + +// omx cmd queue insert +bool omx_video::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id) +{ + bool ret = true; + if(m_size < OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_q[m_write].id = id; + m_q[m_write].param1 = p1; + m_q[m_write].param2 = p2; + m_write++; + m_size ++; + if(m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_write = 0; + } + } + else + { + ret = false; + DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full\n"); + } + return ret; +} + +// omx cmd queue pop +bool omx_video::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id) +{ + bool ret = true; + if(m_size > 0) + { + *id = m_q[m_read].id; + *p1 = m_q[m_read].param1; + *p2 = m_q[m_read].param2; + // Move the read pointer ahead + ++m_read; + --m_size; + if(m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) + { + m_read = 0; + } + } + else + { + ret = false; + } + return ret; +} + +// Retrieve the first mesg type in the queue +unsigned omx_video::omx_cmd_queue::get_q_msg_type() +{ + return m_q[m_read].id; +} + + + +#ifdef _ANDROID_ +VideoHeap::VideoHeap(int fd, size_t size, void* base) +{ + // dup file descriptor, map once, use pmem + init(dup(fd), base, size, 0 , MEM_DEVICE); +} +#endif // _ANDROID_ + +/* ====================================================================== +FUNCTION + omx_venc::omx_venc + +DESCRIPTION + Constructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_video::omx_video(): m_state(OMX_StateInvalid), + m_app_data(NULL), + m_inp_mem_ptr(NULL), + m_out_mem_ptr(NULL), + m_pInput_pmem(NULL), + m_pOutput_pmem(NULL), +#ifdef USE_ION + m_pInput_ion(NULL), + m_pOutput_ion(NULL), +#endif + pending_input_buffers(0), + pending_output_buffers(0), + m_out_bm_count(0), + m_inp_bm_count(0), + m_flags(0), + m_event_port_settings_sent(false), + output_flush_progress (false), + input_flush_progress (false), + input_use_buffer (false), + output_use_buffer (false), + m_use_input_pmem(OMX_FALSE), + m_use_output_pmem(OMX_FALSE), + m_etb_count(0), + m_fbd_count(0), + m_error_propogated(false) +{ + DEBUG_PRINT_HIGH("\n omx_video(): Inside Constructor()"); + memset(&m_cmp,0,sizeof(m_cmp)); + memset(&m_pCallbacks,0,sizeof(m_pCallbacks)); + + + pthread_mutex_init(&m_lock, NULL); + sem_init(&m_cmd_lock,0,0); +} + + +/* ====================================================================== +FUNCTION + omx_venc::~omx_venc + +DESCRIPTION + Destructor + +PARAMETERS + None + +RETURN VALUE + None. +========================================================================== */ +omx_video::~omx_video() +{ + DEBUG_PRINT_HIGH("\n ~omx_video(): Inside Destructor()"); + if(m_pipe_in) close(m_pipe_in); + if(m_pipe_out) close(m_pipe_out); + DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit\n"); + pthread_join(msg_thread_id,NULL); + DEBUG_PRINT_HIGH("omx_video: Waiting on Async Thread exit\n"); + pthread_join(async_thread_id,NULL); + pthread_mutex_destroy(&m_lock); + sem_destroy(&m_cmd_lock); + DEBUG_PRINT_HIGH("\n m_etb_count = %u, m_fbd_count = %u\n", m_etb_count, + m_fbd_count); + DEBUG_PRINT_HIGH("omx_video: Destructor exit\n"); + DEBUG_PRINT_HIGH("Exiting 7x30 OMX Video Encoder ...\n"); +} + +/* ====================================================================== +FUNCTION + omx_venc::OMXCntrlProcessMsgCb + +DESCRIPTION + IL Client callbacks are generated through this routine. The decoder + provides the thread context for this routine. + +PARAMETERS + ctxt -- Context information related to the self. + id -- Event identifier. This could be any of the following: + 1. Command completion event + 2. Buffer done callback event + 3. Frame done callback event + +RETURN VALUE + None. + +========================================================================== */ +void omx_video::process_event_cb(void *ctxt, unsigned char id) +{ + unsigned p1; // Parameter - 1 + unsigned p2; // Parameter - 2 + unsigned ident; + unsigned qsize=0; // qsize + omx_video *pThis = (omx_video *) ctxt; + + if(!pThis) + { + DEBUG_PRINT_ERROR("ERROR:ProcessMsgCb:Context is incorrect; bailing out\n"); + return; + } + + // Protect the shared queue data structure + do + { + /*Read the message id's from the queue*/ + + pthread_mutex_lock(&pThis->m_lock); + qsize = pThis->m_cmd_q.m_size; + if(qsize) + { + pThis->m_cmd_q.pop_entry(&p1,&p2,&ident); + } + + if(qsize == 0) + { + qsize = pThis->m_ftb_q.m_size; + if(qsize) + { + pThis->m_ftb_q.pop_entry(&p1,&p2,&ident); + } + } + + if(qsize == 0) + { + qsize = pThis->m_etb_q.m_size; + if(qsize) + { + pThis->m_etb_q.pop_entry(&p1,&p2,&ident); + } + } + + pthread_mutex_unlock(&pThis->m_lock); + + /*process message if we have one*/ + if(qsize > 0) + { + id = ident; + switch(id) + { + case OMX_COMPONENT_GENERATE_EVENT: + if(pThis->m_pCallbacks.EventHandler) + { + switch(p1) + { + case OMX_CommandStateSet: + pThis->m_state = (OMX_STATETYPE) p2; + DEBUG_PRINT_LOW("Process -> state set to %d \n", pThis->m_state); + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL); + break; + + case OMX_EventError: + DEBUG_PRINT_ERROR("\nERROR: OMX_EventError: p2 = %d\n", p2); + if(p2 == OMX_ErrorHardware) + { + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventError,OMX_ErrorHardware,0,NULL); + } + else + { + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventError, p2, NULL, NULL ); + + } + break; + + case OMX_CommandPortDisable: + DEBUG_PRINT_LOW("Process -> Port %d set to PORT_STATE_DISABLED" \ + "state \n", p2); + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL ); + break; + case OMX_CommandPortEnable: + DEBUG_PRINT_LOW("Process ->Port %d set PORT_STATE_ENABLED state\n" \ + , p2); + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,\ + OMX_EventCmdComplete, p1, p2, NULL ); + break; + + default: + DEBUG_PRINT_LOW("\n process_event_cb forwarding EventCmdComplete %d \n", p1); + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete, p1, p2, NULL ); + break; + + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: ProcessMsgCb NULL callbacks\n"); + } + break; + + case OMX_COMPONENT_GENERATE_ETB: + if(pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\nERROR: ETBProxy() failed!\n"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_FTB: + if( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\nERROR: FTBProxy() failed!\n"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_COMMAND: + pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\ + (OMX_U32)p2,(OMX_PTR)NULL); + break; + + case OMX_COMPONENT_GENERATE_EBD: + if( pThis->empty_buffer_done(&pThis->m_cmp, + (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\nERROR: empty_buffer_done() failed!\n"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_FBD: + if( pThis->fill_buffer_done(&pThis->m_cmp, + (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) + { + DEBUG_PRINT_ERROR("\nERROR: fill_buffer_done() failed!\n"); + pThis->omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH: + + pThis->input_flush_progress = false; + DEBUG_PRINT_HIGH("\nm_etb_count at i/p flush = %u", m_etb_count); + m_etb_count = 0; + if(pThis->m_pCallbacks.EventHandler) + { + /*Check if we need generate event for Flush done*/ + if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_INPUT_FLUSH_PENDING)) + { + BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING); + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandFlush, + PORT_INDEX_IN,NULL ); + } + else if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_IDLE_PENDING)) + { + if(!pThis->output_flush_progress) + { + DEBUG_PRINT_LOW("\n dev_stop called after input flush complete\n"); + if(dev_stop() != 0) + { + DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed in i/p flush!\n"); + pThis->omx_report_error (); + } + } + } + } + + break; + + case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH: + + pThis->output_flush_progress = false; + DEBUG_PRINT_HIGH("\nm_fbd_count at o/p flush = %u", m_fbd_count); + m_fbd_count = 0; + if(pThis->m_pCallbacks.EventHandler) + { + /*Check if we need generate event for Flush done*/ + if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) + { + BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING); + + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandFlush, + PORT_INDEX_OUT,NULL ); + } + else if(BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) + { + DEBUG_PRINT_LOW("\n dev_stop called after Output flush complete\n"); + if(!pThis->input_flush_progress) + { + if(dev_stop() != 0) + { + DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed in o/p flush!\n"); + pThis->omx_report_error (); + } + } + } + } + break; + + case OMX_COMPONENT_GENERATE_START_DONE: + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE msg"); + + if(pThis->m_pCallbacks.EventHandler) + { + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Success"); + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) + { + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Move to \ + executing"); + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); + pThis->m_state = OMX_StateExecuting; + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateExecuting, NULL); + } + else if(BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_PAUSE_PENDING)) + { + if(dev_pause()) + { + DEBUG_PRINT_ERROR("\nERROR: dev_pause() failed in Start Done!\n"); + pThis->omx_report_error (); + } + } + else if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_LOADED_START_PENDING)) + { + if(dev_loaded_start_done()) + { + DEBUG_PRINT_LOW("successful loaded Start Done!"); + } + else + { + DEBUG_PRINT_ERROR("ERROR: failed in loaded Start Done!"); + pThis->omx_report_error (); + } + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_START_PENDING); + } + else + { + DEBUG_PRINT_LOW("\nERROR: unknown flags=%x\n",pThis->m_flags); + } + } + else + { + DEBUG_PRINT_LOW("\n Event Handler callback is NULL"); + } + break; + + case OMX_COMPONENT_GENERATE_PAUSE_DONE: + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_PAUSE_DONE msg"); + if(pThis->m_pCallbacks.EventHandler) + { + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) + { + //Send the callback now + pThis->complete_pending_buffer_done_cbs(); + DEBUG_PRINT_LOW("omx_video::process_event_cb() Sending PAUSE complete after all pending EBD/FBD\n"); + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING); + pThis->m_state = OMX_StatePause; + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StatePause, NULL); + } + } + + break; + + case OMX_COMPONENT_GENERATE_RESUME_DONE: + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_RESUME_DONE msg"); + if(pThis->m_pCallbacks.EventHandler) + { + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); + pThis->m_state = OMX_StateExecuting; + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateExecuting,NULL); + } + } + + break; + + case OMX_COMPONENT_GENERATE_STOP_DONE: + DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_STOP_DONE msg"); + if(pThis->m_pCallbacks.EventHandler) + { + pThis->complete_pending_buffer_done_cbs(); + if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING); + pThis->m_state = OMX_StateIdle; + pThis->m_pCallbacks.EventHandler(&pThis->m_cmp,pThis->m_app_data, + OMX_EventCmdComplete,OMX_CommandStateSet, + OMX_StateIdle,NULL); + } + else if (BITMASK_PRESENT(&pThis->m_flags, + OMX_COMPONENT_LOADED_STOP_PENDING)) + { + if(dev_loaded_stop_done()) + { + DEBUG_PRINT_LOW("successful loaded Stop Done!"); + } + else + { + DEBUG_PRINT_ERROR("ERROR: failed in loaded Stop Done!"); + pThis->omx_report_error (); + } + BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_STOP_PENDING); + } + else + { + DEBUG_PRINT_LOW("\nERROR: unknown flags=%x\n",pThis->m_flags); + } + } + + break; + + case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: + DEBUG_PRINT_ERROR("\nERROR: OMX_COMPONENT_GENERATE_HARDWARE_ERROR!\n"); + pThis->omx_report_error (); + break; + + default: + DEBUG_PRINT_LOW("\n process_event_cb unknown msg id 0x%02x", id); + break; + } + } + + pthread_mutex_lock(&pThis->m_lock); + qsize = pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size +\ + pThis->m_etb_q.m_size; + + pthread_mutex_unlock(&pThis->m_lock); + + } + while(qsize>0); + DEBUG_PRINT_LOW("\n exited the while loop\n"); + +} + + + + +/* ====================================================================== +FUNCTION + omx_venc::GetComponentVersion + +DESCRIPTION + Returns the component version. + +PARAMETERS + TBD. + +RETURN VALUE + OMX_ErrorNone. + +========================================================================== */ +OMX_ERRORTYPE omx_video::get_component_version +( +OMX_IN OMX_HANDLETYPE hComp, +OMX_OUT OMX_STRING componentName, +OMX_OUT OMX_VERSIONTYPE* componentVersion, +OMX_OUT OMX_VERSIONTYPE* specVersion, +OMX_OUT OMX_UUIDTYPE* componentUUID +) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Get Comp Version in Invalid State\n"); + return OMX_ErrorInvalidState; + } + /* TBD -- Return the proper version */ + if (specVersion) + { + specVersion->nVersion = OMX_SPEC_VERSION; + } + return OMX_ErrorNone; +} +/* ====================================================================== +FUNCTION + omx_venc::SendCommand + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::send_command(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData + ) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if(cmd == OMX_CommandFlush || cmd == OMX_CommandPortDisable || cmd == OMX_CommandPortEnable) + { + if((param1 != PORT_INDEX_IN) && (param1 != PORT_INDEX_OUT) && (param1 != PORT_INDEX_BOTH)) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index\n"); + return OMX_ErrorBadPortIndex; + } + } + if(cmd == OMX_CommandMarkBuffer) + { + if(param1 != PORT_INDEX_IN) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index \n"); + return OMX_ErrorBadPortIndex; + } + if(!cmdData) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->param is null"); + return OMX_ErrorBadParameter; + } + } + + post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); + sem_wait(&m_cmd_lock); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_venc::SendCommand + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_COMMANDTYPE cmd, + OMX_IN OMX_U32 param1, + OMX_IN OMX_PTR cmdData + ) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_STATETYPE eState = (OMX_STATETYPE) param1; + int bFlag = 1; + + if(cmd == OMX_CommandStateSet) + { + /***************************/ + /* Current State is Loaded */ + /***************************/ + if(m_state == OMX_StateLoaded) + { + if(eState == OMX_StateIdle) + { + //if all buffers are allocated or all ports disabled + if(allocate_done() || + ( m_sInPortDef.bEnabled == OMX_FALSE && m_sOutPortDef.bEnabled == OMX_FALSE)) + { + DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle\n"); + } + else + { + DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + /* Requesting transition from Loaded to Loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Loaded\n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Loaded to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->WaitForResources\n"); + } + /* Requesting transition from Loaded to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Executing\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Loaded to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Pause\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Loaded to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->%d Not Handled\n",\ + eState); + eRet = OMX_ErrorBadParameter; + } + } + + /***************************/ + /* Current State is IDLE */ + /***************************/ + else if(m_state == OMX_StateIdle) + { + if(eState == OMX_StateLoaded) + { + if(release_done()) + { + /* + Since error is None , we will post an event at the end + of this function definition + */ + DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded\n"); + if(dev_stop() != 0) + { + DEBUG_PRINT_ERROR("\nERROR: dev_stop() failed at Idle --> Loaded"); + eRet = OMX_ErrorHardware; + } + } + else + { + DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded-Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); + // Skip the event notification + bFlag = 0; + } + } + /* Requesting transition from Idle to Executing */ + else if(eState == OMX_StateExecuting) + { + if( dev_start() ) + { + DEBUG_PRINT_ERROR("\nERROR: dev_start() failed in SCP on Idle --> Exe\n"); + omx_report_error (); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING); + DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing\n"); + bFlag = 0; + } + + dev_start_done(); + } + /* Requesting transition from Idle to Idle */ + else if(eState == OMX_StateIdle) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Idle\n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Idle to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->WaitForResources\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Idle to Pause */ + else if(eState == OMX_StatePause) + { + /*To pause the Video core we need to start the driver*/ + if( dev_start() ) + { + DEBUG_PRINT_ERROR("\nERROR: dev_start() failed in SCP on Idle --> Pause\n"); + omx_report_error (); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); + DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Pause\n"); + bFlag = 0; + } + } + /* Requesting transition from Idle to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + + /******************************/ + /* Current State is Executing */ + /******************************/ + else if(m_state == OMX_StateExecuting) + { + /* Requesting transition from Executing to Idle */ + if(eState == OMX_StateIdle) + { + /* Since error is None , we will post an event + at the end of this function definition + */ + DEBUG_PRINT_LOW("\n OMXCORE-SM: Executing --> Idle \n"); + //here this should be Pause-Idle pending and should be cleared when flush is complete and change the state to Idle + BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); + execute_omx_flush(OMX_ALL); + bFlag = 0; + dev_stop_done(); + } + /* Requesting transition from Executing to Paused */ + else if(eState == OMX_StatePause) + { + + if(dev_pause()) + { + DEBUG_PRINT_ERROR("\nERROR: dev_pause() failed in SCP on Exe --> Pause\n"); + post_event(OMX_EventError,OMX_ErrorHardware,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); + DEBUG_PRINT_LOW("OMXCORE-SM: Executing-->Pause\n"); + bFlag = 0; + } + } + /* Requesting transition from Executing to Loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Loaded \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Executing to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> WaitForResources \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Executing to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Executing \n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Executing to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\nERROR: OMXCORE-SM: Executing --> Invalid \n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is Pause */ + /***************************/ + else if(m_state == OMX_StatePause) + { + /* Requesting transition from Pause to Executing */ + if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_LOW("\n Pause --> Executing \n"); + if( dev_resume() ) + { + post_event(OMX_EventError,OMX_ErrorHardware,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorHardware; + } + else + { + BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING); + DEBUG_PRINT_LOW("OMXCORE-SM: Pause-->Executing\n"); + post_event (NULL, NULL, OMX_COMPONENT_GENERATE_RESUME_DONE); + bFlag = 0; + } + } + /* Requesting transition from Pause to Idle */ + else if(eState == OMX_StateIdle) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_LOW("\n Pause --> Idle \n"); + BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); + execute_omx_flush(OMX_ALL); + bFlag = 0; + } + /* Requesting transition from Pause to loaded */ + else if(eState == OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("\nERROR: Pause --> loaded \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Pause to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("\nERROR: Pause --> WaitForResources \n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from Pause to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("\nERROR: Pause --> Pause \n"); + post_event(OMX_EventError,OMX_ErrorSameState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from Pause to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("\nERROR: Pause --> Invalid \n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Paused --> %d Not Handled\n",eState); + eRet = OMX_ErrorBadParameter; + } + } + /***************************/ + /* Current State is WaitForResources */ + /***************************/ + else if(m_state == OMX_StateWaitForResources) + { + /* Requesting transition from WaitForResources to Loaded */ + if(eState == OMX_StateLoaded) + { + /* Since error is None , we will post an event + at the end of this function definition */ + DEBUG_PRINT_LOW("OMXCORE-SM: WaitForResources-->Loaded\n"); + } + /* Requesting transition from WaitForResources to WaitForResources */ + else if(eState == OMX_StateWaitForResources) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->WaitForResources\n"); + post_event(OMX_EventError,OMX_ErrorSameState, + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorSameState; + } + /* Requesting transition from WaitForResources to Executing */ + else if(eState == OMX_StateExecuting) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Executing\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from WaitForResources to Pause */ + else if(eState == OMX_StatePause) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Pause\n"); + post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorIncorrectStateTransition; + } + /* Requesting transition from WaitForResources to Invalid */ + else if(eState == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Invalid\n"); + post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + /* Requesting transition from WaitForResources to Loaded - + is NOT tested by Khronos TS */ + + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: %d --> %d(Not Handled)\n",m_state,eState); + eRet = OMX_ErrorBadParameter; + } + } + /********************************/ + /* Current State is Invalid */ + /*******************************/ + else if(m_state == OMX_StateInvalid) + { + /* State Transition from Inavlid to any state */ + if(eState == (OMX_StateLoaded || OMX_StateWaitForResources + || OMX_StateIdle || OMX_StateExecuting + || OMX_StatePause || OMX_StateInvalid)) + { + DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Invalid -->Loaded\n"); + post_event(OMX_EventError,OMX_ErrorInvalidState,\ + OMX_COMPONENT_GENERATE_EVENT); + eRet = OMX_ErrorInvalidState; + } + } + else if(cmd == OMX_CommandFlush) + { + if(0 == param1 || OMX_ALL == param1) + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); + } + if(1 == param1 || OMX_ALL == param1) + { + //generate output flush event only. + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING); + } + + execute_omx_flush(param1); + bFlag = 0; + } + else if( cmd == OMX_CommandPortEnable) + { + if(param1 == PORT_INDEX_IN || param1 == OMX_ALL) + { + m_sInPortDef.bEnabled = OMX_TRUE; + + if( (m_state == OMX_StateLoaded && + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || allocate_input_done()) + { + post_event(OMX_CommandPortEnable,PORT_INDEX_IN, + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + if(param1 == PORT_INDEX_OUT || param1 == OMX_ALL) + { + m_sOutPortDef.bEnabled = OMX_TRUE; + + if( (m_state == OMX_StateLoaded && + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + || (allocate_output_done())) + { + post_event(OMX_CommandPortEnable,PORT_INDEX_OUT, + OMX_COMPONENT_GENERATE_EVENT); + + } + else + { + DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending\n"); + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + // Skip the event notification + bFlag = 0; + } + } + } + else if(cmd == OMX_CommandPortDisable) + { + if(param1 == PORT_INDEX_IN || param1 == OMX_ALL) + { + m_sInPortDef.bEnabled = OMX_FALSE; + if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_input_done()) + { + post_event(OMX_CommandPortDisable,PORT_INDEX_IN, + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); + if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + execute_omx_flush(PORT_INDEX_IN); + } + + // Skip the event notification + bFlag = 0; + } + } + if(param1 == PORT_INDEX_OUT || param1 == OMX_ALL) + { + m_sOutPortDef.bEnabled = OMX_FALSE; + + if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) + && release_output_done()) + { + post_event(OMX_CommandPortDisable,PORT_INDEX_OUT,\ + OMX_COMPONENT_GENERATE_EVENT); + } + else + { + BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) + { + execute_omx_flush(PORT_INDEX_OUT); + } + // Skip the event notification + bFlag = 0; + + } + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid Command received other than StateSet (%d)\n",cmd); + eRet = OMX_ErrorNotImplemented; + } + if(eRet == OMX_ErrorNone && bFlag) + { + post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); + } + sem_post(&m_cmd_lock); + return eRet; +} + +/* ====================================================================== +FUNCTION + omx_venc::ExecuteOmxFlush + +DESCRIPTION + Executes the OMX flush. + +PARAMETERS + flushtype - input flush(1)/output flush(0)/ both. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_video::execute_omx_flush(OMX_U32 flushType) +{ + bool bRet = false; + DEBUG_PRINT_LOW("\n execute_omx_flush - %d\n", flushType); + if(flushType == 0 || flushType == OMX_ALL) + { + input_flush_progress = true; + //flush input only + bRet = execute_input_flush(); + } + if(flushType == 1 || flushType == OMX_ALL) + { + //flush output only + output_flush_progress = true; + bRet = execute_output_flush(); + } + return bRet; +} +/*========================================================================= +FUNCTION : execute_output_flush + +DESCRIPTION + Executes the OMX flush at OUTPUT PORT. + +PARAMETERS + None. + +RETURN VALUE + true/false +==========================================================================*/ +bool omx_video::execute_output_flush(void) +{ + unsigned p1 = 0; // Parameter - 1 + unsigned p2 = 0; // Parameter - 2 + unsigned ident = 0; + bool bRet = true; + + /*Generate FBD for all Buffers in the FTBq*/ + DEBUG_PRINT_LOW("\n execute_output_flush\n"); + pthread_mutex_lock(&m_lock); + while(m_ftb_q.m_size) + { + m_ftb_q.pop_entry(&p1,&p2,&ident); + + if(ident == OMX_COMPONENT_GENERATE_FTB ) + { + pending_output_buffers++; + fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); + } + else if(ident == OMX_COMPONENT_GENERATE_FBD) + { + fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); + } + } + + pthread_mutex_unlock(&m_lock); + /*Check if there are buffers with the Driver*/ + if(dev_flush(PORT_INDEX_OUT)) + { + DEBUG_PRINT_ERROR("\nERROR: o/p dev_flush() Failed"); + return false; + } + + return bRet; +} +/*========================================================================= +FUNCTION : execute_input_flush + +DESCRIPTION + Executes the OMX flush at INPUT PORT. + +PARAMETERS + None. + +RETURN VALUE + true/false +==========================================================================*/ +bool omx_video::execute_input_flush(void) +{ + unsigned p1 = 0; // Parameter - 1 + unsigned p2 = 0; // Parameter - 2 + unsigned ident = 0; + bool bRet = true; + + /*Generate EBD for all Buffers in the ETBq*/ + DEBUG_PRINT_LOW("\n execute_input_flush\n"); + + pthread_mutex_lock(&m_lock); + while(m_etb_q.m_size) + { + m_etb_q.pop_entry(&p1,&p2,&ident); + if(ident == OMX_COMPONENT_GENERATE_ETB) + { + pending_input_buffers++; + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); + } + else if(ident == OMX_COMPONENT_GENERATE_EBD) + { + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); + } + } + + pthread_mutex_unlock(&m_lock); + /*Check if there are buffers with the Driver*/ + if(dev_flush(PORT_INDEX_IN)) + { + DEBUG_PRINT_ERROR("\nERROR: i/p dev_flush() Failed"); + return false; + } + + return bRet; +} + + +/* ====================================================================== +FUNCTION + omx_venc::SendCommandEvent + +DESCRIPTION + Send the event to decoder pipe. This is needed to generate the callbacks + in decoder thread context. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +bool omx_video::post_event(unsigned int p1, + unsigned int p2, + unsigned int id) +{ + bool bRet = false; + + + pthread_mutex_lock(&m_lock); + + if( id == OMX_COMPONENT_GENERATE_FTB || \ + (id == OMX_COMPONENT_GENERATE_FRAME_DONE)) + { + m_ftb_q.insert_entry(p1,p2,id); + } + else if((id == OMX_COMPONENT_GENERATE_ETB) \ + || (id == OMX_COMPONENT_GENERATE_EBD)) + { + m_etb_q.insert_entry(p1,p2,id); + } + else + { + m_cmd_q.insert_entry(p1,p2,id); + } + + bRet = true; + DEBUG_PRINT_LOW("\n Value of this pointer in post_event %p",this); + post_message(this, id); + pthread_mutex_unlock(&m_lock); + + return bRet; +} + +/* ====================================================================== +FUNCTION + omx_venc::GetParameter + +DESCRIPTION + OMX Get Parameter method implementation + +PARAMETERS + . + +RETURN VALUE + Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_INOUT OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned int height=0,width = 0; + + DEBUG_PRINT_LOW("get_parameter: \n"); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(paramData == NULL) + { + DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid paramData \n"); + return OMX_ErrorBadParameter; + } + switch(paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition\n"); + if(portDefn->nPortIndex == (OMX_U32) PORT_INDEX_IN) + { + DEBUG_PRINT_LOW("m_sInPortDef: size = %d, min cnt = %d, actual cnt = %d", + m_sInPortDef.nBufferSize, m_sInPortDef.nBufferCountMin, + m_sInPortDef.nBufferCountActual); + memcpy(portDefn, &m_sInPortDef, sizeof(m_sInPortDef)); +#ifdef _ANDROID_ICS_ + if(meta_mode_enable) + { + portDefn->nBufferSize = sizeof(encoder_media_buffer_type); + } + + if (mUseProxyColorFormat) { + portDefn->format.video.eColorFormat = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatAndroidOpaque; + } +#endif + } + else if(portDefn->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + dev_get_buf_req (&m_sOutPortDef.nBufferCountMin, + &m_sOutPortDef.nBufferCountActual, + &m_sOutPortDef.nBufferSize, + m_sOutPortDef.nPortIndex); + DEBUG_PRINT_LOW("m_sOutPortDef: size = %d, min cnt = %d, actual cnt = %d", + m_sOutPortDef.nBufferSize, m_sOutPortDef.nBufferCountMin, + m_sOutPortDef.nBufferCountActual); + memcpy(portDefn, &m_sOutPortDef, sizeof(m_sOutPortDef)); + } + else + { + DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParamType = + (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n"); + + memcpy(portParamType, &m_sPortParam, sizeof(m_sPortParam)); + break; + } + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = + (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat\n"); + + if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) + { + int index = portFmt->nIndex; + if(index > 1) + eRet = OMX_ErrorNoMore; + else { + memcpy(portFmt, &m_sInPortFormat, sizeof(m_sInPortFormat)); +#ifdef _ANDROID_ICS_ + if (index == 1) { + //we support two formats + //index 0 - YUV420SP + //index 1 - opaque which internally maps to YUV420SP. + //this can be extended in the future + portFmt->nIndex = index; //restore index set from client + portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatAndroidOpaque; + } +#endif + } + } + else if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + memcpy(portFmt, &m_sOutPortFormat, sizeof(m_sOutPortFormat)); + } + else + { + DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoBitrate\n"); + + if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + memcpy(pParam, &m_sParamBitrate, sizeof(m_sParamBitrate)); + } + else + { + DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); + eRet = OMX_ErrorBadPortIndex; + } + + break; + } + case OMX_IndexParamVideoMpeg4: + { + OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4\n"); + memcpy(pParam, &m_sParamMPEG4, sizeof(m_sParamMPEG4)); + break; + } + case OMX_IndexParamVideoH263: + { + OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263\n"); + memcpy(pParam, &m_sParamH263, sizeof(m_sParamH263)); + break; + } + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc\n"); + memcpy(pParam, &m_sParamAVC, sizeof(m_sParamAVC)); + break; + } + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported\n"); + eRet = get_supported_profile_level(pParam); + if(eRet) + DEBUG_PRINT_ERROR("Invalid entry returned from get_supported_profile_level %d, %d", + pParam->eProfile, pParam->eLevel); + break; + } + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelCurrent\n"); + memcpy(pParam, &m_sParamProfileLevel, sizeof(m_sParamProfileLevel)); + break; + } + /*Component should support this port definition*/ + case OMX_IndexParamAudioInit: + { + OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit\n"); + memcpy(audioPortParamType, &m_sPortParam_audio, sizeof(m_sPortParam_audio)); + break; + } + /*Component should support this port definition*/ + case OMX_IndexParamImageInit: + { + OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit\n"); + memcpy(imagePortParamType, &m_sPortParam_img, sizeof(m_sPortParam_img)); + break; + + } + /*Component should support this port definition*/ + case OMX_IndexParamOtherInit: + { + DEBUG_PRINT_ERROR("ERROR: get_parameter: OMX_IndexParamOtherInit %08x\n", paramIndex); + eRet =OMX_ErrorUnsupportedIndex; + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *comp_role; + comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; + comp_role->nVersion.nVersion = OMX_SPEC_VERSION; + comp_role->nSize = sizeof(*comp_role); + + DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d\n",paramIndex); + if(NULL != comp_role->cRole) + { + strlcpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Getparameter: OMX_IndexParamStandardComponentRole %d is passed with NULL parameter for role\n",paramIndex); + eRet =OMX_ErrorBadParameter; + } + break; + } + /* Added for parameter test */ + case OMX_IndexParamPriorityMgmt: + { + + OMX_PRIORITYMGMTTYPE *priorityMgmType = (OMX_PRIORITYMGMTTYPE *) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n"); + memcpy(priorityMgmType, &m_sPriorityMgmt, sizeof(m_sPriorityMgmt)); + break; + } + /* Added for parameter test */ + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n"); + if(bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_IN) + { + memcpy(bufferSupplierType, &m_sInBufSupplier, sizeof(m_sInBufSupplier)); + } + else if(bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_OUT) + { + memcpy(bufferSupplierType, &m_sOutBufSupplier, sizeof(m_sOutBufSupplier)); + } + else + { + DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index"); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_IndexParamVideoQuantization: + { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData; + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoQuantization\n"); + memcpy(session_qp, &m_sSessionQuantization, sizeof(m_sSessionQuantization)); + break; + } + + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* errorresilience = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*)paramData; + DEBUG_PRINT_LOW("OMX_IndexParamVideoErrorCorrection\n"); + errorresilience->bEnableHEC = m_sErrorCorrection.bEnableHEC; + errorresilience->bEnableResync = m_sErrorCorrection.bEnableResync; + errorresilience->nResynchMarkerSpacing = m_sErrorCorrection.nResynchMarkerSpacing; + break; + } + case OMX_IndexParamVideoIntraRefresh: + { + OMX_VIDEO_PARAM_INTRAREFRESHTYPE* intrarefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE*)paramData; + DEBUG_PRINT_LOW("OMX_IndexParamVideoIntraRefresh\n"); + DEBUG_PRINT_ERROR("OMX_IndexParamVideoIntraRefresh GET\n"); + intrarefresh->eRefreshMode = m_sIntraRefresh.eRefreshMode; + intrarefresh->nCirMBs = m_sIntraRefresh.nCirMBs; + break; + } + case OMX_QcomIndexPortDefn: + //TODO + break; + case OMX_COMPONENT_CAPABILITY_TYPE_INDEX: + { + OMXComponentCapabilityFlagsType *pParam = reinterpret_cast(paramData); + DEBUG_PRINT_LOW("get_parameter: OMX_COMPONENT_CAPABILITY_TYPE_INDEX\n"); + pParam->iIsOMXComponentMultiThreaded = OMX_TRUE; + pParam->iOMXComponentSupportsExternalOutputBufferAlloc = OMX_FALSE; + pParam->iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; + pParam->iOMXComponentSupportsMovableInputBuffers = OMX_TRUE; + pParam->iOMXComponentUsesNALStartCodes = OMX_TRUE; + pParam->iOMXComponentSupportsPartialFrames = OMX_FALSE; + pParam->iOMXComponentCanHandleIncompleteFrames = OMX_FALSE; + pParam->iOMXComponentUsesFullAVCFrames = OMX_FALSE; + m_use_input_pmem = OMX_TRUE; + DEBUG_PRINT_LOW("Supporting capability index in encoder node"); + break; + } +#ifndef MAX_RES_720P + case OMX_QcomIndexParamIndexExtraDataType: + { + DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamIndexExtraDataType"); + QOMX_INDEXEXTRADATATYPE *pParam = (QOMX_INDEXEXTRADATATYPE *)paramData; + if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoEncoderSliceInfo) + { + if (pParam->nPortIndex == PORT_INDEX_OUT) + { + pParam->bEnabled = + (OMX_BOOL)((m_sExtraData & VEN_EXTRADATA_SLICEINFO) ? 1 : 0); + DEBUG_PRINT_HIGH("Slice Info extradata %d", pParam->bEnabled); + } + else + { + DEBUG_PRINT_ERROR("get_parameter: slice information is " + "valid for output port only"); + eRet =OMX_ErrorUnsupportedIndex; + } + } + else + { + DEBUG_PRINT_ERROR("get_parameter: unsupported index (%x), " + "only slice information extradata is supported", pParam->nIndex); + eRet =OMX_ErrorUnsupportedIndex; + } + break; + } +#endif + case QOMX_IndexParamVideoSyntaxHdr: + { + DEBUG_PRINT_HIGH("QOMX_IndexParamVideoSyntaxHdr"); + QOMX_EXTNINDEX_PARAMTYPE* pParam = + reinterpret_cast(paramData); + if (pParam->pData == NULL) + { + DEBUG_PRINT_ERROR("Error: Data buffer is NULL"); + eRet = OMX_ErrorBadParameter; + break; + } + if (get_syntaxhdr_enable == false) + { + DEBUG_PRINT_ERROR("ERROR: get_parameter: unknown param %08x\n", paramIndex); + eRet =OMX_ErrorUnsupportedIndex; + break; + } + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADED_START_PENDING); + if(dev_loaded_start()) + { + DEBUG_PRINT_LOW("device start successful"); + } + else + { + DEBUG_PRINT_ERROR("device start failed"); + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_LOADED_START_PENDING); + return OMX_ErrorHardware; + } + if(dev_get_seq_hdr(pParam->pData, + (unsigned)(pParam->nSize - sizeof(QOMX_EXTNINDEX_PARAMTYPE)), + (unsigned *)&pParam->nDataSize)) + { + DEBUG_PRINT_HIGH("get syntax header successful (hdrlen = %d)", + pParam->nDataSize); + for (unsigned i = 0; i < pParam->nDataSize; i++) { + DEBUG_PRINT_LOW("Header[%d] = %x", i, *((char *)pParam->pData + i)); + } + } + else + { + DEBUG_PRINT_ERROR("Error returned from GetSyntaxHeader()"); + eRet = OMX_ErrorHardware; + } + BITMASK_SET(&m_flags, OMX_COMPONENT_LOADED_STOP_PENDING); + if(dev_loaded_stop()) + { + DEBUG_PRINT_LOW("device stop successful"); + } + else + { + DEBUG_PRINT_ERROR("device stop failed"); + BITMASK_CLEAR(&m_flags, OMX_COMPONENT_LOADED_STOP_PENDING); + eRet = OMX_ErrorHardware; + } + break; + } + case OMX_IndexParamVideoSliceFMO: + default: + { + DEBUG_PRINT_LOW("ERROR: get_parameter: unknown param %08x\n", paramIndex); + eRet =OMX_ErrorUnsupportedIndex; + break; + } + + } + + return eRet; + +} +/* ====================================================================== +FUNCTION + omx_video::GetConfig + +DESCRIPTION + OMX Get Config Method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_INOUT OMX_PTR configData) +{ + //////////////////////////////////////////////////////////////// + // Supported Config Index Type + // ============================================================= + // OMX_IndexConfigVideoBitrate OMX_VIDEO_CONFIG_BITRATETYPE + // OMX_IndexConfigVideoFramerate OMX_CONFIG_FRAMERATETYPE + // OMX_IndexConfigCommonRotate OMX_CONFIG_ROTATIONTYPE + //////////////////////////////////////////////////////////////// + + if(configData == NULL) + { + DEBUG_PRINT_ERROR("ERROR: param is null"); + return OMX_ErrorBadParameter; + } + + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: can't be in invalid state"); + return OMX_ErrorIncorrectStateOperation; + } + + //@todo need to validate params + switch(configIndex) + { + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast(configData); + memcpy(pParam, &m_sConfigBitrate, sizeof(m_sConfigBitrate)); + break; + } + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast(configData); + memcpy(pParam, &m_sConfigFramerate, sizeof(m_sConfigFramerate)); + break; + } + case OMX_IndexConfigCommonRotate: + { + OMX_CONFIG_ROTATIONTYPE* pParam = reinterpret_cast(configData); + memcpy(pParam, &m_sConfigFrameRotation, sizeof(m_sConfigFrameRotation)); + break; + } + case QOMX_IndexConfigVideoIntraperiod: + { + DEBUG_PRINT_LOW("get_config:QOMX_IndexConfigVideoIntraperiod\n"); + QOMX_VIDEO_INTRAPERIODTYPE* pParam = reinterpret_cast(configData); + memcpy(pParam, &m_sIntraperiod, sizeof(m_sIntraperiod)); + break; + } + default: + DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex); + return OMX_ErrorUnsupportedIndex; + } + return OMX_ErrorNone; + +} + +/* ====================================================================== +FUNCTION + omx_video::GetExtensionIndex + +DESCRIPTION + OMX GetExtensionIndex method implementaion. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::get_extension_index(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_STRING paramName, + OMX_OUT OMX_INDEXTYPE* indexType) +{ + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Get Extension Index in Invalid State\n"); + return OMX_ErrorInvalidState; + } +#ifdef MAX_RES_1080P + if (!strncmp(paramName, "OMX.QCOM.index.param.SliceDeliveryMode", + sizeof("OMX.QCOM.index.param.SliceDeliveryMode") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableSliceDeliveryMode; + return OMX_ErrorNone; + } +#endif +#ifdef _ANDROID_ICS_ + if (!strncmp(paramName, "OMX.google.android.index.storeMetaDataInBuffers",sizeof("OMX.google.android.index.storeMetaDataInBuffers") - 1)) { + *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoEncodeMetaBufferMode; + return OMX_ErrorNone; + } +#endif + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_video::GetState + +DESCRIPTION + Returns the state information back to the caller. + +PARAMETERS + . + +RETURN VALUE + Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_video::get_state(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_STATETYPE* state) +{ + *state = m_state; + DEBUG_PRINT_LOW("get_state: Returning the state %d\n",*state); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_video::ComponentTunnelRequest + +DESCRIPTION + OMX Component Tunnel Request method implementation. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_HANDLETYPE peerComponent, + OMX_IN OMX_U32 peerPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup) +{ + DEBUG_PRINT_ERROR("ERROR: component_tunnel_request Not Implemented\n"); + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_video::UseInputBuffer + +DESCRIPTION + Helper function for Use buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::use_input_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + unsigned i = 0; + unsigned char *buf_addr = NULL; + + DEBUG_PRINT_HIGH("use_input_buffer: port = %d appData = %p bytes = %d buffer = %p",port,appData,bytes,buffer); + if(bytes != m_sInPortDef.nBufferSize) + { + DEBUG_PRINT_ERROR("\nERROR: use_input_buffer: Size Mismatch!! " + "bytes[%d] != Port.nBufferSize[%d]", bytes, m_sInPortDef.nBufferSize); + return OMX_ErrorBadParameter; + } + + if(!m_inp_mem_ptr) + { + input_use_buffer = true; + m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ + calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual); + if(m_inp_mem_ptr == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_inp_mem_ptr"); + return OMX_ErrorInsufficientResources; + } + + + m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual); + if(m_pInput_pmem == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_pmem"); + return OMX_ErrorInsufficientResources; + } +#ifdef USE_ION + m_pInput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sInPortDef.nBufferCountActual); + if(m_pInput_ion == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_ion"); + return OMX_ErrorInsufficientResources; + } +#endif + + for(i=0; i< m_sInPortDef.nBufferCountActual; i++) + { + m_pInput_pmem[i].fd = -1; +#ifdef USE_ION + m_pInput_ion[i].ion_device_fd =-1; + m_pInput_ion[i].fd_ion_data.fd =-1; + m_pInput_ion[i].ion_alloc_data.handle=NULL; +#endif + } + + } + + for(i=0; i< m_sInPortDef.nBufferCountActual; i++) + { + if(BITMASK_ABSENT(&m_inp_bm_count,i)) + { + break; + } + } + + if(i < m_sInPortDef.nBufferCountActual) + { + + *bufferHdr = (m_inp_mem_ptr + i); + BITMASK_SET(&m_inp_bm_count,i); + + (*bufferHdr)->pBuffer = (OMX_U8 *)buffer; + (*bufferHdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE); + (*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION; + (*bufferHdr)->nAllocLen = m_sInPortDef.nBufferSize; + (*bufferHdr)->pAppPrivate = appData; + (*bufferHdr)->nInputPortIndex = PORT_INDEX_IN; + + if(!m_use_input_pmem) + { +#ifdef USE_ION + m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize, + &m_pInput_ion[i].ion_alloc_data, + &m_pInput_ion[i].fd_ion_data,CACHED); + if(m_pInput_ion[i].ion_device_fd < 0) { + DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed"); + return OMX_ErrorInsufficientResources; + } + m_pInput_pmem[i].fd = m_pInput_ion[i].fd_ion_data.fd; +#else + m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + if(m_pInput_pmem[i].fd == 0) + { + m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + } + + if(m_pInput_pmem[i] .fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed"); + return OMX_ErrorInsufficientResources; + } +#endif + m_pInput_pmem[i].size = m_sInPortDef.nBufferSize; + m_pInput_pmem[i].offset = 0; + m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE, + MAP_SHARED,m_pInput_pmem[i].fd,0); + + if(m_pInput_pmem[i].buffer == MAP_FAILED) + { + DEBUG_PRINT_ERROR("\nERROR: mmap() Failed"); + close(m_pInput_pmem[i].fd); +#ifdef USE_ION + free_ion_memory(&m_pInput_ion[i]); +#endif + return OMX_ErrorInsufficientResources; + } + } + else + { + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast((*bufferHdr)->pAppPrivate); + DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%d,offset:0x%x)", pParam->pmem_fd, pParam->offset); + + if(pParam) + { + m_pInput_pmem[i].fd = pParam->pmem_fd; + m_pInput_pmem[i].offset = pParam->offset; + m_pInput_pmem[i].size = m_sInPortDef.nBufferSize; + m_pInput_pmem[i].buffer = (unsigned char *)buffer; + DEBUG_PRINT_LOW("\n DBG:: pParam->pmem_fd = %u, pParam->offset = %u", + pParam->pmem_fd, pParam->offset); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM i/p UseBuffer case"); + return OMX_ErrorBadParameter; + } + } + + DEBUG_PRINT_LOW("\nuse_inp:: bufhdr = %p, pBuffer = %p, m_pInput_pmem[i].buffer = %p", + (*bufferHdr), (*bufferHdr)->pBuffer, m_pInput_pmem[i].buffer); + if( dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN,i) != true) + { + DEBUG_PRINT_ERROR("\nERROR: dev_use_buf() Failed for i/p buf"); + return OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: All buffers are already used, invalid use_buf call for " + "index = %u", i); + eRet = OMX_ErrorInsufficientResources; + } + + return eRet; +} + + + +/* ====================================================================== +FUNCTION + omx_video::UseOutputBuffer + +DESCRIPTION + Helper function for Use buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::use_output_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header + unsigned i= 0; // Temporary counter + unsigned char *buf_addr = NULL; +#ifdef _MSM8974_ + int align_size; +#endif + + DEBUG_PRINT_HIGH("\n Inside use_output_buffer()"); + if(bytes != m_sOutPortDef.nBufferSize) + { + DEBUG_PRINT_ERROR("\nERROR: use_output_buffer: Size Mismatch!! " + "bytes[%d] != Port.nBufferSize[%d]", bytes, m_sOutPortDef.nBufferSize); + return OMX_ErrorBadParameter; + } + + if(!m_out_mem_ptr) + { + output_use_buffer = true; + int nBufHdrSize = 0; + + DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)\n",m_sOutPortDef.nBufferCountActual); + nBufHdrSize = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE); + /* + * Memory for output side involves the following: + * 1. Array of Buffer Headers + * 2. Bitmask array to hold the buffer allocation details + * In order to minimize the memory management entire allocation + * is done in one step. + */ + //OMX Buffer header + m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); + if(m_out_mem_ptr == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_out_mem_ptr"); + return OMX_ErrorInsufficientResources; + } + + m_pOutput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sOutPortDef.nBufferCountActual); + if(m_pOutput_pmem == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pOutput_pmem"); + return OMX_ErrorInsufficientResources; + } +#ifdef USE_ION + m_pOutput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sOutPortDef.nBufferCountActual); + if(m_pOutput_ion == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pOutput_ion"); + return OMX_ErrorInsufficientResources; + } +#endif + if(m_out_mem_ptr) + { + bufHdr = m_out_mem_ptr; + DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p\n",m_out_mem_ptr); + // Settting the entire storage nicely + for(i=0; i < m_sOutPortDef.nBufferCountActual ; i++) + { + bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + bufHdr->nAllocLen = bytes; + bufHdr->nFilledLen = 0; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = PORT_INDEX_OUT; + bufHdr->pBuffer = NULL; + bufHdr++; + m_pOutput_pmem[i].fd = -1; +#ifdef USE_ION + m_pOutput_ion[i].ion_device_fd =-1; + m_pOutput_ion[i].fd_ion_data.fd=-1; + m_pOutput_ion[i].ion_alloc_data.handle =NULL; +#endif + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: Output buf mem alloc failed[0x%x]\n",m_out_mem_ptr); + eRet = OMX_ErrorInsufficientResources; + } + } + + for(i=0; i< m_sOutPortDef.nBufferCountActual; i++) + { + if(BITMASK_ABSENT(&m_out_bm_count,i)) + { + break; + } + } + + if(eRet == OMX_ErrorNone) + { + if(i < m_sOutPortDef.nBufferCountActual) + { + *bufferHdr = (m_out_mem_ptr + i ); + (*bufferHdr)->pBuffer = (OMX_U8 *)buffer; + (*bufferHdr)->pAppPrivate = appData; + BITMASK_SET(&m_out_bm_count,i); + + if(!m_use_output_pmem) + { +#ifdef USE_ION +#ifdef _MSM8974_ + align_size = ((m_sOutPortDef.nBufferSize + 4095)/4096) * 4096; + m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(align_size, + &m_pOutput_ion[i].ion_alloc_data, + &m_pOutput_ion[i].fd_ion_data,UNCACHED); +#else + m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory( + m_sOutPortDef.nBufferSize, + &m_pOutput_ion[i].ion_alloc_data, + &m_pOutput_ion[i].fd_ion_data,CACHED); +#endif + if(m_pOutput_ion[i].ion_device_fd < 0) { + DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed"); + return OMX_ErrorInsufficientResources; + } + m_pOutput_pmem[i].fd = m_pOutput_ion[i].fd_ion_data.fd; +#else + m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + + if(m_pOutput_pmem[i].fd == 0) + { + m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + } + + if(m_pOutput_pmem[i].fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed"); + return OMX_ErrorInsufficientResources; + } +#endif + m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; + m_pOutput_pmem[i].offset = 0; +#ifdef _MSM8974_ + m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,align_size,PROT_READ|PROT_WRITE, + MAP_SHARED,m_pOutput_pmem[i].fd,0); +#else + m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pOutput_pmem[i].size,PROT_READ|PROT_WRITE, + MAP_SHARED,m_pOutput_pmem[i].fd,0); +#endif + if(m_pOutput_pmem[i].buffer == MAP_FAILED) + { + DEBUG_PRINT_ERROR("\nERROR: mmap() Failed"); + close(m_pOutput_pmem[i].fd); +#ifdef USE_ION + free_ion_memory(&m_pOutput_ion[i]); +#endif + return OMX_ErrorInsufficientResources; + } + } + else + { + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast((*bufferHdr)->pAppPrivate); + DEBUG_PRINT_LOW("Inside qcom_ext pParam:0x%x )", pParam); + + if(pParam) + { + DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%d,offset:0x%x)", pParam->pmem_fd, pParam->offset); + m_pOutput_pmem[i].fd = pParam->pmem_fd; + m_pOutput_pmem[i].offset = pParam->offset; + m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; + m_pOutput_pmem[i].buffer = (unsigned char *)buffer; + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM o/p UseBuffer case"); + return OMX_ErrorBadParameter; + } + buf_addr = (unsigned char *)buffer; + } + + DEBUG_PRINT_LOW("\n use_out:: bufhdr = %p, pBuffer = %p, m_pOutput_pmem[i].buffer = %p", + (*bufferHdr), (*bufferHdr)->pBuffer, m_pOutput_pmem[i].buffer); + if(dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT,i) != true) + { + DEBUG_PRINT_ERROR("ERROR: dev_use_buf Failed for o/p buf"); + return OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: All o/p Buffers have been Used, invalid use_buf call for " + "index = %u", i); + eRet = OMX_ErrorInsufficientResources; + } + } + return eRet; +} + + +/* ====================================================================== +FUNCTION + omx_video::UseBuffer + +DESCRIPTION + OMX Use Buffer method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None , if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::use_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes, + OMX_IN OMX_U8* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Use Buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(port == PORT_INDEX_IN) + { + eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + } + else if(port == PORT_INDEX_OUT) + { + eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d\n",(int)port); + eRet = OMX_ErrorBadPortIndex; + } + + if(eRet == OMX_ErrorNone) + { + if(allocate_done()) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); + post_event(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if(port == PORT_INDEX_IN && m_sInPortDef.bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + PORT_INDEX_IN, + OMX_COMPONENT_GENERATE_EVENT); + } + + } + else if(port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + PORT_INDEX_OUT, + OMX_COMPONENT_GENERATE_EVENT); + m_event_port_settings_sent = false; + } + } + } + return eRet; +} + +OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) +{ + unsigned int index = 0; + OMX_U8 *temp_buff ; + + if(bufferHdr == NULL || m_inp_mem_ptr == NULL) + { + DEBUG_PRINT_ERROR("ERROR: free_input: Invalid bufferHdr[%p] or m_inp_mem_ptr[%p]", + bufferHdr, m_inp_mem_ptr); + return OMX_ErrorBadParameter; + } + + index = bufferHdr - m_inp_mem_ptr; +#ifdef _ANDROID_ICS_ + if(meta_mode_enable) + { + if(index < m_sInPortDef.nBufferCountActual) + { + memset(&meta_buffer_hdr[index], 0, sizeof(meta_buffer_hdr[index])); + memset(&meta_buffers[index], 0, sizeof(meta_buffers[index])); + } + return OMX_ErrorNone; + } +#endif + if(index < m_sInPortDef.nBufferCountActual && + dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) + { + DEBUG_PRINT_ERROR("\nERROR: dev_free_buf() Failed for i/p buf"); + } + + if(index < m_sInPortDef.nBufferCountActual && m_pInput_pmem) + { + if(m_pInput_pmem[index].fd > 0 && input_use_buffer == false) + { + DEBUG_PRINT_LOW("\n FreeBuffer:: i/p AllocateBuffer case"); + munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size); + close (m_pInput_pmem[index].fd); +#ifdef USE_ION + free_ion_memory(&m_pInput_ion[index]); +#endif + m_pInput_pmem[index].fd = -1; + } + else if(m_pInput_pmem[index].fd > 0 && (input_use_buffer == true && + m_use_input_pmem == OMX_FALSE)) + { + DEBUG_PRINT_LOW("\n FreeBuffer:: i/p Heap UseBuffer case"); + if(dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) + { + DEBUG_PRINT_ERROR("\nERROR: dev_free_buf() Failed for i/p buf"); + } + munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size); + close (m_pInput_pmem[index].fd); +#ifdef USE_ION + free_ion_memory(&m_pInput_ion[index]); +#endif + m_pInput_pmem[index].fd = -1; + } + else + { + DEBUG_PRINT_LOW("\n FreeBuffer:: fd is invalid or i/p PMEM UseBuffer case"); + } + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_video::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) +{ + unsigned int index = 0; + OMX_U8 *temp_buff ; + + if(bufferHdr == NULL || m_out_mem_ptr == NULL) + { + DEBUG_PRINT_ERROR("ERROR: free_output: Invalid bufferHdr[%p] or m_out_mem_ptr[%p]", + bufferHdr, m_out_mem_ptr); + return OMX_ErrorBadParameter; + } + index = bufferHdr - m_out_mem_ptr; + + if(index < m_sOutPortDef.nBufferCountActual && + dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) + { + DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf"); + } + + if(index < m_sOutPortDef.nBufferCountActual && m_pOutput_pmem) + { + if(m_pOutput_pmem[index].fd > 0 && output_use_buffer == false ) + { + DEBUG_PRINT_LOW("\n FreeBuffer:: o/p AllocateBuffer case"); + munmap (m_pOutput_pmem[index].buffer,m_pOutput_pmem[index].size); + close (m_pOutput_pmem[index].fd); +#ifdef USE_ION + free_ion_memory(&m_pOutput_ion[index]); +#endif + m_pOutput_pmem[index].fd = -1; + } + else if( m_pOutput_pmem[index].fd > 0 && (output_use_buffer == true + && m_use_output_pmem == OMX_FALSE)) + { + DEBUG_PRINT_LOW("\n FreeBuffer:: o/p Heap UseBuffer case"); + if(dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) + { + DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf"); + } + munmap (m_pOutput_pmem[index].buffer,m_pOutput_pmem[index].size); + close (m_pOutput_pmem[index].fd); +#ifdef USE_ION + free_ion_memory(&m_pOutput_ion[index]); +#endif + m_pOutput_pmem[index].fd = -1; + } + else + { + DEBUG_PRINT_LOW("\n FreeBuffer:: fd is invalid or o/p PMEM UseBuffer case"); + } + } + return OMX_ErrorNone; +} +#ifdef _ANDROID_ICS_ +OMX_ERRORTYPE omx_video::allocate_input_meta_buffer( + OMX_BUFFERHEADERTYPE **bufferHdr, + OMX_PTR appData, + OMX_U32 bytes) +{ + unsigned index = 0; + if(!bufferHdr || bytes != sizeof(encoder_media_buffer_type)) + { + DEBUG_PRINT_ERROR("wrong params allocate_input_meta_buffer Hdr %p len %d", + bufferHdr,bytes); + return OMX_ErrorBadParameter; + } + if(!m_inp_mem_ptr) + m_inp_mem_ptr = meta_buffer_hdr; + for(index = 0;((index < m_sInPortDef.nBufferCountActual) && + meta_buffer_hdr[index].pBuffer); index++); + if(index == m_sInPortDef.nBufferCountActual) + { + DEBUG_PRINT_ERROR("All buffers are allocated input_meta_buffer"); + return OMX_ErrorBadParameter; + } + BITMASK_SET(&m_inp_bm_count,index); + *bufferHdr = &meta_buffer_hdr[index]; + memset(&meta_buffer_hdr[index], 0, sizeof(meta_buffer_hdr[index])); + meta_buffer_hdr[index].nSize = sizeof(meta_buffer_hdr[index]); + meta_buffer_hdr[index].nAllocLen = bytes; + meta_buffer_hdr[index].nVersion.nVersion = OMX_SPEC_VERSION; + meta_buffer_hdr[index].nInputPortIndex = PORT_INDEX_IN; + meta_buffer_hdr[index].pBuffer = (OMX_U8*)&meta_buffers[index]; + meta_buffer_hdr[index].pAppPrivate = appData; + return OMX_ErrorNone; +} +#endif +/* ====================================================================== +FUNCTION + omx_venc::AllocateInputBuffer + +DESCRIPTION + Helper function for allocate buffer in the input pin + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::allocate_input_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned i = 0; + + DEBUG_PRINT_HIGH("\n allocate_input_buffer()::"); + if(bytes != m_sInPortDef.nBufferSize) + { + DEBUG_PRINT_ERROR("\nERROR: Buffer size mismatch error: bytes[%u] != nBufferSize[%u]\n", + bytes, m_sInPortDef.nBufferSize); + return OMX_ErrorBadParameter; + } + + if(!m_inp_mem_ptr) + { + DEBUG_PRINT_HIGH("%s: size = %d, actual cnt %d", __FUNCTION__, + m_sInPortDef.nBufferSize, m_sInPortDef.nBufferCountActual); + m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \ + calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual); + if(m_inp_mem_ptr == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_inp_mem_ptr"); + return OMX_ErrorInsufficientResources; + } + + m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual); + + if(m_pInput_pmem == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_pmem"); + return OMX_ErrorInsufficientResources; + } +#ifdef USE_ION + m_pInput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sInPortDef.nBufferCountActual); + if(m_pInput_ion == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pInput_ion"); + return OMX_ErrorInsufficientResources; + } +#endif + for(i=0; i< m_sInPortDef.nBufferCountActual; i++) + { + m_pInput_pmem[i].fd = -1; +#ifdef USE_ION + m_pInput_ion[i].ion_device_fd =-1; + m_pInput_ion[i].fd_ion_data.fd =-1; + m_pInput_ion[i].ion_alloc_data.handle=NULL; +#endif + } + } + + for(i=0; i< m_sInPortDef.nBufferCountActual; i++) + { + if(BITMASK_ABSENT(&m_inp_bm_count,i)) + { + break; + } + } + if(i < m_sInPortDef.nBufferCountActual) + { + + *bufferHdr = (m_inp_mem_ptr + i); + (*bufferHdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE); + (*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION; + (*bufferHdr)->nAllocLen = m_sInPortDef.nBufferSize; + (*bufferHdr)->pAppPrivate = appData; + (*bufferHdr)->nInputPortIndex = PORT_INDEX_IN; + +#ifdef USE_ION + m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize, + &m_pInput_ion[i].ion_alloc_data, + &m_pInput_ion[i].fd_ion_data,CACHED); + if(m_pInput_ion[i].ion_device_fd < 0) { + DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed"); + return OMX_ErrorInsufficientResources; + } + + m_pInput_pmem[i].fd = m_pInput_ion[i].fd_ion_data.fd; +#else + m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + + if(m_pInput_pmem[i].fd == 0) + { + m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + } + + if(m_pInput_pmem[i].fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() Failed\n"); + return OMX_ErrorInsufficientResources; + } +#endif + m_pInput_pmem[i].size = m_sInPortDef.nBufferSize; + m_pInput_pmem[i].offset = 0; + + m_pInput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE, + MAP_SHARED,m_pInput_pmem[i].fd,0); + if(m_pInput_pmem[i].buffer == MAP_FAILED) + { + DEBUG_PRINT_ERROR("\nERROR: mmap FAILED= %d\n", errno); + close(m_pInput_pmem[i].fd); +#ifdef USE_ION + free_ion_memory(&m_pInput_ion[i]); +#endif + return OMX_ErrorInsufficientResources; + } + + (*bufferHdr)->pBuffer = (OMX_U8 *)m_pInput_pmem[i].buffer; + + BITMASK_SET(&m_inp_bm_count,i); + //here change the I/P param here from buf_adr to pmem + if( dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN,i) != true) + { + DEBUG_PRINT_ERROR("\nERROR: dev_use_buf FAILED for i/p buf\n"); + return OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: All i/p buffers are allocated, invalid allocate buf call" + "for index [%d]\n", i); + eRet = OMX_ErrorInsufficientResources; + } + + return eRet; +} + + +/* ====================================================================== +FUNCTION + omx_venc::AllocateOutputBuffer + +DESCRIPTION + Helper fn for AllocateBuffer in the output pin + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything went well. + +========================================================================== */ +OMX_ERRORTYPE omx_video::allocate_output_buffer( + OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header + unsigned i= 0; // Temporary counter +#ifdef _MSM8974_ + int align_size; +#endif + DEBUG_PRINT_HIGH("\n allocate_output_buffer()for %d bytes", bytes); + if(!m_out_mem_ptr) + { + int nBufHdrSize = 0; + DEBUG_PRINT_HIGH("%s: size = %d, actual cnt %d", __FUNCTION__, + m_sOutPortDef.nBufferSize, m_sOutPortDef.nBufferCountActual); + nBufHdrSize = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE); + + /* + * Memory for output side involves the following: + * 1. Array of Buffer Headers + * 2. Bitmask array to hold the buffer allocation details + * In order to minimize the memory management entire allocation + * is done in one step. + */ + m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1); + +#ifdef USE_ION + m_pOutput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sOutPortDef.nBufferCountActual); + if(m_pOutput_ion == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pOutput_ion"); + return OMX_ErrorInsufficientResources; + } +#endif + m_pOutput_pmem = (struct pmem *) calloc(sizeof(struct pmem), m_sOutPortDef.nBufferCountActual); + if(m_pOutput_pmem == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: calloc() Failed for m_pOutput_pmem"); + return OMX_ErrorInsufficientResources; + } + if(m_out_mem_ptr && m_pOutput_pmem) + { + bufHdr = m_out_mem_ptr; + + for(i=0; i < m_sOutPortDef.nBufferCountActual ; i++) + { + bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); + bufHdr->nVersion.nVersion = OMX_SPEC_VERSION; + // Set the values when we determine the right HxW param + bufHdr->nAllocLen = bytes; + bufHdr->nFilledLen = 0; + bufHdr->pAppPrivate = appData; + bufHdr->nOutputPortIndex = PORT_INDEX_OUT; + bufHdr->pBuffer = NULL; + bufHdr++; + m_pOutput_pmem[i].fd = -1; +#ifdef USE_ION + m_pOutput_ion[i].ion_device_fd =-1; + m_pOutput_ion[i].fd_ion_data.fd=-1; + m_pOutput_ion[i].ion_alloc_data.handle =NULL; +#endif + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: calloc() failed for m_out_mem_ptr/m_pOutput_pmem"); + eRet = OMX_ErrorInsufficientResources; + } + } + + DEBUG_PRINT_HIGH("\n actual cnt = %u", m_sOutPortDef.nBufferCountActual); + for(i=0; i< m_sOutPortDef.nBufferCountActual; i++) + { + if(BITMASK_ABSENT(&m_out_bm_count,i)) + { + DEBUG_PRINT_LOW("\n Found a Free Output Buffer %d",i); + break; + } + } + if(eRet == OMX_ErrorNone) + { + if(i < m_sOutPortDef.nBufferCountActual) + { +#ifdef USE_ION +#ifdef _MSM8974_ + align_size = ((m_sOutPortDef.nBufferSize + 4095)/4096) * 4096; + m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(align_size, + &m_pOutput_ion[i].ion_alloc_data, + &m_pOutput_ion[i].fd_ion_data,UNCACHED); +#else + m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sOutPortDef.nBufferSize, + &m_pOutput_ion[i].ion_alloc_data, + &m_pOutput_ion[i].fd_ion_data,CACHED); +#endif + if(m_pOutput_ion[i].ion_device_fd < 0) { + DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed"); + return OMX_ErrorInsufficientResources; + } + + m_pOutput_pmem[i].fd = m_pOutput_ion[i].fd_ion_data.fd; +#else + m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + if(m_pOutput_pmem[i].fd == 0) + { + m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR); + } + + if(m_pOutput_pmem[i].fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: /dev/pmem_adsp open() failed"); + return OMX_ErrorInsufficientResources; + } +#endif + m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize; + m_pOutput_pmem[i].offset = 0; +#ifdef _MSM8974_ + m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,align_size,PROT_READ|PROT_WRITE, + MAP_SHARED,m_pOutput_pmem[i].fd,0); +#else + m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,m_pOutput_pmem[i].size,PROT_READ|PROT_WRITE, + MAP_SHARED,m_pOutput_pmem[i].fd,0); +#endif + if(m_pOutput_pmem[i].buffer == MAP_FAILED) + { + DEBUG_PRINT_ERROR("\nERROR: MMAP_FAILED in o/p alloc buffer"); + close (m_pOutput_pmem[i].fd); +#ifdef USE_ION + free_ion_memory(&m_pOutput_ion[i]); +#endif + return OMX_ErrorInsufficientResources; + } + + *bufferHdr = (m_out_mem_ptr + i ); + (*bufferHdr)->pBuffer = (OMX_U8 *)m_pOutput_pmem[i].buffer; + (*bufferHdr)->pAppPrivate = appData; + + BITMASK_SET(&m_out_bm_count,i); + + if(dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT,i) != true) + { + DEBUG_PRINT_ERROR("\nERROR: dev_use_buf FAILED for o/p buf"); + return OMX_ErrorInsufficientResources; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: All o/p buffers are allocated, invalid allocate buf call" + "for index [%d]\n", i); + } + } + + return eRet; +} + + +// AllocateBuffer -- API Call +/* ====================================================================== +FUNCTION + omx_video::AllocateBuffer + +DESCRIPTION + Returns zero if all the buffers released.. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN OMX_U32 bytes) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type + + DEBUG_PRINT_LOW("\n Allocate buffer of size = %d on port %d \n", bytes, (int)port); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Allocate Buf in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + // What if the client calls again. + if(port == PORT_INDEX_IN) + { +#ifdef _ANDROID_ICS_ + if(meta_mode_enable) + eRet = allocate_input_meta_buffer(bufferHdr,appData,bytes); + else +#endif + eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes); + } + else if(port == PORT_INDEX_OUT) + { + eRet = allocate_output_buffer(hComp,bufferHdr,port,appData,bytes); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d\n",(int)port); + eRet = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done"); + if(eRet == OMX_ErrorNone) + { + if(allocate_done()) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING); + post_event(OMX_CommandStateSet,OMX_StateIdle, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if(port == PORT_INDEX_IN && m_sInPortDef.bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + PORT_INDEX_IN, + OMX_COMPONENT_GENERATE_EVENT); + } + } + if(port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated) + { + if(BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) + { + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING); + post_event(OMX_CommandPortEnable, + PORT_INDEX_OUT, + OMX_COMPONENT_GENERATE_EVENT); + m_event_port_settings_sent = false; + } + } + } + DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d\n",eRet); + return eRet; +} + + +// Free Buffer - API call +/* ====================================================================== +FUNCTION + omx_video::FreeBuffer + +DESCRIPTION + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::free_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 port, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + unsigned int nPortIndex; + + DEBUG_PRINT_LOW("In for decoder free_buffer \n"); + + if(m_state == OMX_StateIdle && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + DEBUG_PRINT_LOW(" free buffer while Component in Loading pending\n"); + } + else if((m_sInPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_IN)|| + (m_sOutPortDef.bEnabled == OMX_FALSE && port == PORT_INDEX_OUT)) + { + DEBUG_PRINT_LOW("Free Buffer while port %d disabled\n", port); + } + else if(m_state == OMX_StateExecuting || m_state == OMX_StatePause) + { + DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,ports need to be disabled\n"); + post_event(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + + return eRet; + } + else + { + DEBUG_PRINT_ERROR("ERROR: Invalid state to free buffer,port lost Buffers\n"); + post_event(OMX_EventError, + OMX_ErrorPortUnpopulated, + OMX_COMPONENT_GENERATE_EVENT); + } + + if(port == PORT_INDEX_IN) + { + // check if the buffer is valid + nPortIndex = buffer - m_inp_mem_ptr; + + DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d, actual cnt %d \n", + nPortIndex, m_sInPortDef.nBufferCountActual); + if(nPortIndex < m_sInPortDef.nBufferCountActual) + { + // Clear the bit associated with it. + BITMASK_CLEAR(&m_inp_bm_count,nPortIndex); + free_input_buffer (buffer); + m_sInPortDef.bPopulated = OMX_FALSE; + + /*Free the Buffer Header*/ + if(release_input_done() +#ifdef _ANDROID_ICS_ + && !meta_mode_enable +#endif + ) + { + input_use_buffer = false; + if(m_inp_mem_ptr) + { + DEBUG_PRINT_LOW("Freeing m_inp_mem_ptr\n"); + free (m_inp_mem_ptr); + m_inp_mem_ptr = NULL; + } + if(m_pInput_pmem) + { + DEBUG_PRINT_LOW("Freeing m_pInput_pmem\n"); + free(m_pInput_pmem); + m_pInput_pmem = NULL; + } +#ifdef USE_ION + if(m_pInput_ion) + { + DEBUG_PRINT_LOW("Freeing m_pInput_ion\n"); + free(m_pInput_ion); + m_pInput_ion = NULL; + } +#endif + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: free_buffer ,Port Index Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + + if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING) + && release_input_done()) + { + DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING); + post_event(OMX_CommandPortDisable, + PORT_INDEX_IN, + OMX_COMPONENT_GENERATE_EVENT); + } + } + else if(port == PORT_INDEX_OUT) + { + // check if the buffer is valid + nPortIndex = buffer - (OMX_BUFFERHEADERTYPE*)m_out_mem_ptr; + + DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d, actual cnt %d \n", + nPortIndex, m_sOutPortDef.nBufferCountActual); + if(nPortIndex < m_sOutPortDef.nBufferCountActual) + { + // Clear the bit associated with it. + BITMASK_CLEAR(&m_out_bm_count,nPortIndex); + m_sOutPortDef.bPopulated = OMX_FALSE; + free_output_buffer (buffer); + + if(release_output_done()) + { + output_use_buffer = false; + if(m_out_mem_ptr) + { + DEBUG_PRINT_LOW("Freeing m_out_mem_ptr\n"); + free (m_out_mem_ptr); + m_out_mem_ptr = NULL; + } + if(m_pOutput_pmem) + { + DEBUG_PRINT_LOW("Freeing m_pOutput_pmem\n"); + free(m_pOutput_pmem); + m_pOutput_pmem = NULL; + } +#ifdef USE_ION + if(m_pOutput_ion) + { + DEBUG_PRINT_LOW("Freeing m_pOutput_ion\n"); + free(m_pOutput_ion); + m_pOutput_ion = NULL; + } +#endif + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: free_buffer , Port Index Invalid\n"); + eRet = OMX_ErrorBadPortIndex; + } + if(BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING) + && release_output_done() ) + { + DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it\n"); + + DEBUG_PRINT_LOW("MOVING TO DISABLED STATE \n"); + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING); + post_event(OMX_CommandPortDisable, + PORT_INDEX_OUT, + OMX_COMPONENT_GENERATE_EVENT); + + } + } + else + { + eRet = OMX_ErrorBadPortIndex; + } + if((eRet == OMX_ErrorNone) && + (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) + { + if(release_done()) + { + if(dev_stop() != 0) + { + DEBUG_PRINT_ERROR("ERROR: dev_stop() FAILED\n"); + eRet = OMX_ErrorHardware; + } + // Send the callback now + BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING); + post_event(OMX_CommandStateSet, OMX_StateLoaded, + OMX_COMPONENT_GENERATE_EVENT); + } + } + + return eRet; +} + + +/* ====================================================================== +FUNCTION + omx_video::EmptyThisBuffer + +DESCRIPTION + This routine is used to push the encoded video frames to + the video decoder. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything went successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_ERRORTYPE ret1 = OMX_ErrorNone; + unsigned int nBufferIndex ; + + DEBUG_PRINT_LOW("\n ETB: buffer = %p, buffer->pBuffer[%p]\n", buffer, buffer->pBuffer); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Empty this buffer in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if (buffer == NULL || (buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) + { + DEBUG_PRINT_ERROR("\nERROR: omx_video::etb--> buffer is null or buffer size is invalid"); + return OMX_ErrorBadParameter; + } + + if(buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT_ERROR("\nERROR: omx_video::etb--> OMX Version Invalid"); + return OMX_ErrorVersionMismatch; + } + + if (buffer->nInputPortIndex != (OMX_U32)PORT_INDEX_IN) + { + DEBUG_PRINT_ERROR("\nERROR: Bad port index to call empty_this_buffer"); + return OMX_ErrorBadPortIndex; + } + if(!m_sInPortDef.bEnabled) + { + DEBUG_PRINT_ERROR("\nERROR: Cannot call empty_this_buffer while I/P port is disabled"); + return OMX_ErrorIncorrectStateOperation; + } + + nBufferIndex = buffer - m_inp_mem_ptr; + + if(nBufferIndex > m_sInPortDef.nBufferCountActual ) + { + DEBUG_PRINT_ERROR("ERROR: ETB: Invalid buffer index[%d]\n", nBufferIndex); + return OMX_ErrorBadParameter; + } + + m_etb_count++; + DEBUG_PRINT_LOW("\n DBG: i/p nTimestamp = %u", (unsigned)buffer->nTimeStamp); + post_event ((unsigned)hComp,(unsigned)buffer,OMX_COMPONENT_GENERATE_ETB); + return OMX_ErrorNone; +} + + +/* ====================================================================== +FUNCTION + omx_video::empty_this_buffer_proxy + +DESCRIPTION + This routine is used to push the encoded video frames to + the video decoder. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything went successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + OMX_U8 *pmem_data_buf = NULL; + int push_cnt = 0; + unsigned nBufIndex = 0; + OMX_ERRORTYPE ret = OMX_ErrorNone; + + DEBUG_PRINT_LOW("\n ETBProxy: buffer->pBuffer[%p]\n", buffer->pBuffer); + + if(buffer == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Invalid buffer[%p]\n", buffer); + return OMX_ErrorBadParameter; + } + + nBufIndex = buffer - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr); + + if(nBufIndex >= m_sInPortDef.nBufferCountActual) + { + DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Invalid bufindex = %u\n", nBufIndex); + return OMX_ErrorBadParameter; + } + + pending_input_buffers++; + if(input_flush_progress == true) + { + post_event ((unsigned int)buffer,0, + OMX_COMPONENT_GENERATE_EBD); + DEBUG_PRINT_ERROR("\nERROR: ETBProxy: Input flush in progress"); + return OMX_ErrorNone; + } +#ifdef _ANDROID_ICS_ + if(meta_mode_enable) + { + encoder_media_buffer_type *media_buffer; + bool met_error = false; + media_buffer = (encoder_media_buffer_type *)meta_buffer_hdr[nBufIndex].pBuffer; + if(media_buffer) + { + if (media_buffer->buffer_type != kMetadataBufferTypeCameraSource && + media_buffer->buffer_type != kMetadataBufferTypeGrallocSource) { + met_error = true; + } else { + if(media_buffer->buffer_type == kMetadataBufferTypeCameraSource) + { + if(media_buffer->meta_handle == NULL) { + met_error = true; + } + else if((media_buffer->meta_handle->numFds != 1 && + media_buffer->meta_handle->numInts != 2)) + { + met_error = true; + } + } + } + } else { + met_error = true; + } + if(met_error) + { + DEBUG_PRINT_ERROR("\nERROR: Unkown source/metahandle in ETB call"); + post_event ((unsigned int)buffer,0,OMX_COMPONENT_GENERATE_EBD); + return OMX_ErrorBadParameter; + } + + struct pmem Input_pmem_info; + if(media_buffer->buffer_type == kMetadataBufferTypeCameraSource) + { + Input_pmem_info.buffer = media_buffer; + Input_pmem_info.fd = media_buffer->meta_handle->data[0]; + Input_pmem_info.offset = media_buffer->meta_handle->data[1]; + Input_pmem_info.size = media_buffer->meta_handle->data[2]; + DEBUG_PRINT_LOW("ETB fd = %d, offset = %d, size = %d",Input_pmem_info.fd, + Input_pmem_info.offset, + Input_pmem_info.size); + + } else { + private_handle_t *handle = (private_handle_t *)media_buffer->meta_handle; + Input_pmem_info.buffer = media_buffer; + Input_pmem_info.fd = handle->fd; + Input_pmem_info.offset = 0; + Input_pmem_info.size = handle->size; + } + if(dev_use_buf(&Input_pmem_info,PORT_INDEX_IN,0) != true) { + DEBUG_PRINT_ERROR("\nERROR: in dev_use_buf"); + post_event ((unsigned int)buffer,0,OMX_COMPONENT_GENERATE_EBD); + return OMX_ErrorBadParameter; + } + } + else if(input_use_buffer && !m_use_input_pmem) +#else + if(input_use_buffer && !m_use_input_pmem) +#endif + { + DEBUG_PRINT_LOW("\n Heap UseBuffer case, so memcpy the data"); + pmem_data_buf = (OMX_U8 *)m_pInput_pmem[nBufIndex].buffer; + + memcpy (pmem_data_buf, (buffer->pBuffer + buffer->nOffset), + buffer->nFilledLen); + DEBUG_PRINT_LOW("memcpy() done in ETBProxy for i/p Heap UseBuf"); + } +#ifdef _MSM8974_ + if(dev_empty_buf(buffer, pmem_data_buf,nBufIndex,m_pInput_pmem[nBufIndex].fd) != true) +#else + if(dev_empty_buf(buffer, pmem_data_buf,0,0) != true) +#endif + { + DEBUG_PRINT_ERROR("\nERROR: ETBProxy: dev_empty_buf failed"); +#ifdef _ANDROID_ICS_ + omx_release_meta_buffer(buffer); +#endif + post_event ((unsigned int)buffer,0,OMX_COMPONENT_GENERATE_EBD); + /*Generate an async error and move to invalid state*/ + pending_input_buffers--; + return OMX_ErrorBadParameter; + } + + return ret; +} + +/* ====================================================================== +FUNCTION + omx_video::FillThisBuffer + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* buffer) +{ + DEBUG_PRINT_LOW("\n FTB: buffer->pBuffer[%p]\n", buffer->pBuffer); + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: FTB in Invalid State\n"); + return OMX_ErrorInvalidState; + } + + if (buffer == NULL ||(buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Invalid buffer or size\n"); + return OMX_ErrorBadParameter; + } + + if(buffer->nVersion.nVersion != OMX_SPEC_VERSION) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->OMX Version Invalid\n"); + return OMX_ErrorVersionMismatch; + } + + if (buffer->nOutputPortIndex != (OMX_U32)PORT_INDEX_OUT) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Bad port index\n"); + return OMX_ErrorBadPortIndex; + } + + if(!m_sOutPortDef.bEnabled) + { + DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->port is disabled\n"); + return OMX_ErrorIncorrectStateOperation; + } + + post_event((unsigned) hComp, (unsigned)buffer,OMX_COMPONENT_GENERATE_FTB); + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_video::fill_this_buffer_proxy + +DESCRIPTION + IL client uses this method to release the frame buffer + after displaying them. + +PARAMETERS + None. + +RETURN VALUE + true/false + +========================================================================== */ +OMX_ERRORTYPE omx_video::fill_this_buffer_proxy( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd) +{ + OMX_U8 *pmem_data_buf = NULL; + OMX_ERRORTYPE nRet = OMX_ErrorNone; + + DEBUG_PRINT_LOW("\n FTBProxy: bufferAdd->pBuffer[%p]\n", bufferAdd->pBuffer); + + if(bufferAdd == NULL || ((bufferAdd - m_out_mem_ptr) >= m_sOutPortDef.nBufferCountActual) ) + { + DEBUG_PRINT_ERROR("\nERROR: FTBProxy: Invalid i/p params\n"); + return OMX_ErrorBadParameter; + } + + pending_output_buffers++; + /*Return back the output buffer to client*/ + if( m_sOutPortDef.bEnabled != OMX_TRUE || output_flush_progress == true) + { + DEBUG_PRINT_LOW("\n o/p port is Disabled or Flush in Progress"); + post_event ((unsigned int)bufferAdd,0, + OMX_COMPONENT_GENERATE_FBD); + return OMX_ErrorNone; + } + + if(output_use_buffer && !m_use_output_pmem) + { + DEBUG_PRINT_LOW("\n Heap UseBuffer case"); + pmem_data_buf = (OMX_U8 *)m_pOutput_pmem[bufferAdd - m_out_mem_ptr].buffer; + } + + if(dev_fill_buf(bufferAdd, pmem_data_buf,(bufferAdd - m_out_mem_ptr),m_pOutput_pmem[bufferAdd - m_out_mem_ptr].fd) != true) + { + DEBUG_PRINT_ERROR("\nERROR: dev_fill_buf() Failed"); + post_event ((unsigned int)bufferAdd,0,OMX_COMPONENT_GENERATE_FBD); + pending_output_buffers--; + return OMX_ErrorBadParameter; + } + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_video::SetCallbacks + +DESCRIPTION + Set the callbacks. + +PARAMETERS + None. + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_video::set_callbacks(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_CALLBACKTYPE* callbacks, + OMX_IN OMX_PTR appData) +{ + + m_pCallbacks = *callbacks; + DEBUG_PRINT_LOW("\n Callbacks Set %p %p %p",m_pCallbacks.EmptyBufferDone,\ + m_pCallbacks.EventHandler,m_pCallbacks.FillBufferDone); + m_app_data = appData; + return OMX_ErrorNotImplemented; +} + + +/* ====================================================================== +FUNCTION + omx_venc::UseEGLImage + +DESCRIPTION + OMX Use EGL Image method implementation . + +PARAMETERS + . + +RETURN VALUE + Not Implemented error. + +========================================================================== */ +OMX_ERRORTYPE omx_video::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp, + OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr, + OMX_IN OMX_U32 port, + OMX_IN OMX_PTR appData, + OMX_IN void* eglImage) +{ + DEBUG_PRINT_ERROR("ERROR: use_EGL_image: Not Implemented \n"); + return OMX_ErrorNotImplemented; +} + +/* ====================================================================== +FUNCTION + omx_venc::ComponentRoleEnum + +DESCRIPTION + OMX Component Role Enum method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything is successful. +========================================================================== */ +OMX_ERRORTYPE omx_video::component_role_enum(OMX_IN OMX_HANDLETYPE hComp, + OMX_OUT OMX_U8* role, + OMX_IN OMX_U32 index) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_encoder.h263",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_encoder.avc",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } +#ifdef _MSM8974_ + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.vp8",OMX_MAX_STRINGNAME_SIZE)) + { + if((0 == index) && role) + { + strlcpy((char *)role, "video_encoder.vp8",OMX_MAX_STRINGNAME_SIZE); + DEBUG_PRINT_LOW("component_role_enum: role %s\n",role); + } + else + { + DEBUG_PRINT_ERROR("\nERROR: No more roles \n"); + eRet = OMX_ErrorNoMore; + } + } +#endif + else + { + DEBUG_PRINT_ERROR("\nERROR: Querying Role on Unknown Component\n"); + eRet = OMX_ErrorInvalidComponentName; + } + return eRet; +} + + + + +/* ====================================================================== +FUNCTION + omx_venc::AllocateDone + +DESCRIPTION + Checks if entire buffer pool is allocated by IL Client or not. + Need this to move to IDLE state. + +PARAMETERS + None. + +RETURN VALUE + true/false. + +========================================================================== */ +bool omx_video::allocate_done(void) +{ + bool bRet = false; + bool bRet_In = false; + bool bRet_Out = false; + + bRet_In = allocate_input_done(); + bRet_Out = allocate_output_done(); + + if(bRet_In && bRet_Out) + { + bRet = true; + } + + return bRet; +} +/* ====================================================================== +FUNCTION + omx_venc::AllocateInputDone + +DESCRIPTION + Checks if I/P buffer pool is allocated by IL Client or not. + +PARAMETERS + None. + +RETURN VALUE + true/false. + +========================================================================== */ +bool omx_video::allocate_input_done(void) +{ + bool bRet = false; + unsigned i=0; + + if(m_inp_mem_ptr == NULL) + { + return bRet; + } + if(m_inp_mem_ptr ) + { + for(;ipBuffer[%p], flags=0x%x", + buffer->pBuffer, buffer->nFlags); + if(buffer == NULL || ((buffer - m_out_mem_ptr) > m_sOutPortDef.nBufferCountActual)) + { + return OMX_ErrorBadParameter; + } + + pending_output_buffers--; + + extra_data_handle.create_extra_data(buffer); + + if (m_sDebugSliceinfo) { + if(buffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) { + DEBUG_PRINT_HIGH("parsing extradata"); + extra_data_handle.parse_extra_data(buffer); + } + } + /* For use buffer we need to copy the data */ + if(m_pCallbacks.FillBufferDone) + { + if(buffer->nFilledLen > 0) + { + m_fbd_count++; + +#ifdef OUTPUT_BUFFER_LOG + if(outputBufferFile1) + { + fwrite((const char *)buffer->pBuffer, buffer->nFilledLen, 1, outputBufferFile1); + } +#endif + } + m_pCallbacks.FillBufferDone (hComp,m_app_data,buffer); + } + else + { + return OMX_ErrorBadParameter; + } + return OMX_ErrorNone; +} + +OMX_ERRORTYPE omx_video::empty_buffer_done(OMX_HANDLETYPE hComp, + OMX_BUFFERHEADERTYPE* buffer) +{ + DEBUG_PRINT_LOW("empty_buffer_done: buffer->pBuffer[%p]", buffer->pBuffer); + if(buffer == NULL || ((buffer - m_inp_mem_ptr) > m_sInPortDef.nBufferCountActual)) + { + return OMX_ErrorBadParameter; + } + + pending_input_buffers--; + + if(m_pCallbacks.EmptyBufferDone) + { + m_pCallbacks.EmptyBufferDone(hComp ,m_app_data, buffer); + } + return OMX_ErrorNone; +} + +void omx_video::complete_pending_buffer_done_cbs() +{ + unsigned p1; + unsigned p2; + unsigned ident; + omx_cmd_queue tmp_q, pending_bd_q; + pthread_mutex_lock(&m_lock); + // pop all pending GENERATE FDB from ftb queue + while (m_ftb_q.m_size) + { + m_ftb_q.pop_entry(&p1,&p2,&ident); + if(ident == OMX_COMPONENT_GENERATE_FBD) + { + pending_bd_q.insert_entry(p1,p2,ident); + } + else + { + tmp_q.insert_entry(p1,p2,ident); + } + } + //return all non GENERATE FDB to ftb queue + while(tmp_q.m_size) + { + tmp_q.pop_entry(&p1,&p2,&ident); + m_ftb_q.insert_entry(p1,p2,ident); + } + // pop all pending GENERATE EDB from etb queue + while (m_etb_q.m_size) + { + m_etb_q.pop_entry(&p1,&p2,&ident); + if(ident == OMX_COMPONENT_GENERATE_EBD) + { + pending_bd_q.insert_entry(p1,p2,ident); + } + else + { + tmp_q.insert_entry(p1,p2,ident); + } + } + //return all non GENERATE FDB to etb queue + while(tmp_q.m_size) + { + tmp_q.pop_entry(&p1,&p2,&ident); + m_etb_q.insert_entry(p1,p2,ident); + } + pthread_mutex_unlock(&m_lock); + // process all pending buffer dones + while(pending_bd_q.m_size) + { + pending_bd_q.pop_entry(&p1,&p2,&ident); + switch(ident) + { + case OMX_COMPONENT_GENERATE_EBD: + if(empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) + { + DEBUG_PRINT_ERROR("\nERROR: empty_buffer_done() failed!\n"); + omx_report_error (); + } + break; + + case OMX_COMPONENT_GENERATE_FBD: + if(fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) + { + DEBUG_PRINT_ERROR("\nERROR: fill_buffer_done() failed!\n"); + omx_report_error (); + } + break; + } + } +} + +#ifdef MAX_RES_720P +OMX_ERRORTYPE omx_video::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(!profileLevelType) + return OMX_ErrorBadParameter; + + if(profileLevelType->nPortIndex == 1) { + if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; + } + else if (profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; + } + else if(profileLevelType->nProfileIndex == 2) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; + } + else + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", + profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_H263Level70; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else if(profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n", profileLevelType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%d, Level:%d\n", + profileLevelType->eProfile,profileLevelType->eLevel); + return eRet; +} +#endif + +#ifdef MAX_RES_1080P +OMX_ERRORTYPE omx_video::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + if(!profileLevelType) + return OMX_ErrorBadParameter; + + if(profileLevelType->nPortIndex == 1) { + if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + + } + else if (profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + } + else if(profileLevelType->nProfileIndex == 2) + { + profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; + profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; + } + else + { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", + profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; + profileLevelType->eLevel = OMX_VIDEO_H263Level70; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + else if(m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4) + { + if (profileLevelType->nProfileIndex == 0) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else if(profileLevelType->nProfileIndex == 1) + { + profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); + eRet = OMX_ErrorNoMore; + } + } + } + else + { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n", profileLevelType->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%d, Level:%d\n", + profileLevelType->eProfile,profileLevelType->eLevel); + return eRet; +} +#endif + +#ifdef USE_ION +int omx_video::alloc_map_ion_memory(int size,struct ion_allocation_data *alloc_data, + struct ion_fd_data *fd_data,int flag) +{ + struct venc_ion buf_ion_info; + int ion_device_fd =-1,rc=0,ion_dev_flags = 0; + if (size <=0 || !alloc_data || !fd_data) { + DEBUG_PRINT_ERROR("\nInvalid input to alloc_map_ion_memory"); + return -EINVAL; + } + if(flag == CACHED) { + ion_dev_flags = O_RDONLY; + } else if(flag == UNCACHED) { + ion_dev_flags = O_RDONLY | O_DSYNC; + } + ion_device_fd = open (MEM_DEVICE,ion_dev_flags); + if(ion_device_fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: ION Device open() Failed"); + return ion_device_fd; + } + alloc_data->len = size; + alloc_data->align = 4096; +#ifdef MAX_RES_720P + alloc_data->len = (size + (alloc_data->align - 1)) & ~(alloc_data->align - 1); + alloc_data->flags = ION_HEAP(MEM_HEAP_ID); +#else + alloc_data->flags = (ION_HEAP(MEM_HEAP_ID) | + ION_HEAP(ION_IOMMU_HEAP_ID)); +#endif + rc = ioctl(ion_device_fd,ION_IOC_ALLOC,alloc_data); + if(rc || !alloc_data->handle) { + DEBUG_PRINT_ERROR("\n ION ALLOC memory failed "); + alloc_data->handle =NULL; + close(ion_device_fd); + ion_device_fd = -1; + return ion_device_fd; + } + fd_data->handle = alloc_data->handle; + rc = ioctl(ion_device_fd,ION_IOC_MAP,fd_data); + if(rc) { + DEBUG_PRINT_ERROR("\n ION MAP failed "); + buf_ion_info.ion_alloc_data = *alloc_data; + buf_ion_info.ion_device_fd = ion_device_fd; + buf_ion_info.fd_ion_data = *fd_data; + free_ion_memory(&buf_ion_info); + fd_data->fd =-1; + ion_device_fd =-1; + } + return ion_device_fd; +} + +void omx_video::free_ion_memory(struct venc_ion *buf_ion_info) +{ + if (!buf_ion_info) { + DEBUG_PRINT_ERROR("\n Invalid input to free_ion_memory"); + return; + } + if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE, + &buf_ion_info->ion_alloc_data.handle)) { + DEBUG_PRINT_ERROR("\n ION free failed "); + return; + } + close(buf_ion_info->ion_device_fd); + buf_ion_info->ion_alloc_data.handle = NULL; + buf_ion_info->ion_device_fd = -1; + buf_ion_info->fd_ion_data.fd = -1; +} +#endif + +#ifdef _ANDROID_ICS_ +void omx_video::omx_release_meta_buffer(OMX_BUFFERHEADERTYPE *buffer) +{ + if(buffer && meta_mode_enable) + { + encoder_media_buffer_type *media_ptr; + struct pmem Input_pmem; + bool meta_error = false; + media_ptr = (encoder_media_buffer_type *) buffer->pBuffer; + if(media_ptr && media_ptr->meta_handle) + { + if(media_ptr->buffer_type == kMetadataBufferTypeCameraSource && + media_ptr->meta_handle->numFds == 1 && + media_ptr->meta_handle->numInts == 2) { + Input_pmem.fd = media_ptr->meta_handle->data[0]; + Input_pmem.buffer = media_ptr; + Input_pmem.size = media_ptr->meta_handle->data[2]; + Input_pmem.offset = media_ptr->meta_handle->data[1]; + DEBUG_PRINT_LOW("EBD fd = %d, offset = %d, size = %d",Input_pmem.fd, + Input_pmem.offset, + Input_pmem.size); + } else if(media_ptr->buffer_type == kMetadataBufferTypeGrallocSource) { + private_handle_t *handle = (private_handle_t *)media_ptr->meta_handle; + Input_pmem.buffer = media_ptr; + Input_pmem.fd = handle->fd; + Input_pmem.offset = 0; + Input_pmem.size = handle->size; + } else { + meta_error = true; + DEBUG_PRINT_ERROR(" Meta Error set in EBD"); + } + if(!meta_error) + meta_error = !dev_free_buf(&Input_pmem,PORT_INDEX_IN); + if(meta_error) + { + DEBUG_PRINT_ERROR(" Warning dev_free_buf failed flush value is %d", + input_flush_progress); + } + } + } +} +#endif diff --git a/mm-video/vidc/venc/src/omx_video_encoder.cpp b/mm-video/vidc/venc/src/omx_video_encoder.cpp new file mode 100644 index 0000000..6f77c0b --- /dev/null +++ b/mm-video/vidc/venc/src/omx_video_encoder.cpp @@ -0,0 +1,1676 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include "omx_video_encoder.h" +#include +#include "video_encoder_device.h" +#include +#ifdef _ANDROID_ICS_ +#include +#endif +#ifdef _ANDROID_ +#include +#endif +#ifndef _ANDROID_ +#include +#define strlcpy g_strlcpy +#endif +/*---------------------------------------------------------------------------- +* Preprocessor Definitions and Constants +* -------------------------------------------------------------------------*/ + +#define OMX_SPEC_VERSION 0x00000101 +#define OMX_INIT_STRUCT(_s_, _name_) \ + memset((_s_), 0x0, sizeof(_name_)); \ + (_s_)->nSize = sizeof(_name_); \ + (_s_)->nVersion.nVersion = OMX_SPEC_VERSION + +extern int m_pipe; + +// factory function executed by the core to create instances +void *get_omx_component_factory_fn(void) +{ + return(new omx_venc); +} + +//constructor + +omx_venc::omx_venc() +{ +#ifdef _ANDROID_ICS_ + get_syntaxhdr_enable == false; + meta_mode_enable = false; + memset(meta_buffer_hdr,0,sizeof(meta_buffer_hdr)); + memset(meta_buffers,0,sizeof(meta_buffers)); + mUseProxyColorFormat = false; +#endif +} + +omx_venc::~omx_venc() +{ + get_syntaxhdr_enable == false; + //nothing to do +} + +/* ====================================================================== +FUNCTION + omx_venc::ComponentInit + +DESCRIPTION + Initialize the component. + +PARAMETERS + ctxt -- Context information related to the self. + id -- Event identifier. This could be any of the following: + 1. Command completion event + 2. Buffer done callback event + 3. Frame done callback event + +RETURN VALUE + None. + +========================================================================== */ +OMX_ERRORTYPE omx_venc::component_init(OMX_STRING role) +{ + + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + int fds[2]; + int r; + + OMX_VIDEO_CODINGTYPE codec_type; + + DEBUG_PRINT_HIGH("\n omx_venc(): Inside component_init()"); + // Copy the role information which provides the decoder m_nkind + strlcpy((char *)m_nkind,role,OMX_MAX_STRINGNAME_SIZE); + + if(!strncmp((char *)m_nkind,"OMX.qcom.video.encoder.mpeg4",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_encoder.mpeg4",\ + OMX_MAX_STRINGNAME_SIZE); + codec_type = OMX_VIDEO_CodingMPEG4; + } + else if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.h263",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_encoder.h263",OMX_MAX_STRINGNAME_SIZE); + codec_type = OMX_VIDEO_CodingH263; + } + else if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.avc",\ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_encoder.avc",OMX_MAX_STRINGNAME_SIZE); + codec_type = OMX_VIDEO_CodingAVC; + } +#ifdef _MSM8974_ + else if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.vp8", \ + OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char *)m_cRole, "video_encoder.vp8",OMX_MAX_STRINGNAME_SIZE); + codec_type = OMX_VIDEO_CodingVPX; + } +#endif + else + { + DEBUG_PRINT_ERROR("\nERROR: Unknown Component\n"); + eRet = OMX_ErrorInvalidComponentName; + } + + + if(eRet != OMX_ErrorNone) + { + return eRet; + } +#ifdef ENABLE_GET_SYNTAX_HDR + get_syntaxhdr_enable = true; +#endif + + handle = new venc_dev(this); + + if(handle == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: handle is NULL"); + return OMX_ErrorInsufficientResources; + } + + if(handle->venc_open(codec_type) != true) + { + DEBUG_PRINT_ERROR("\nERROR: venc_open failed"); + return OMX_ErrorInsufficientResources; + } + + //Intialise the OMX layer variables + memset(&m_pCallbacks,0,sizeof(OMX_CALLBACKTYPE)); + + OMX_INIT_STRUCT(&m_sPortParam, OMX_PORT_PARAM_TYPE); + m_sPortParam.nPorts = 0x2; + m_sPortParam.nStartPortNumber = (OMX_U32) PORT_INDEX_IN; + + OMX_INIT_STRUCT(&m_sPortParam_audio, OMX_PORT_PARAM_TYPE); + m_sPortParam_audio.nPorts = 0; + m_sPortParam_audio.nStartPortNumber = 0; + + OMX_INIT_STRUCT(&m_sPortParam_img, OMX_PORT_PARAM_TYPE); + m_sPortParam_img.nPorts = 0; + m_sPortParam_img.nStartPortNumber = 0; + + OMX_INIT_STRUCT(&m_sParamBitrate, OMX_VIDEO_PARAM_BITRATETYPE); + m_sParamBitrate.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sParamBitrate.eControlRate = OMX_Video_ControlRateVariableSkipFrames; + m_sParamBitrate.nTargetBitrate = 64000; + + OMX_INIT_STRUCT(&m_sConfigBitrate, OMX_VIDEO_CONFIG_BITRATETYPE); + m_sConfigBitrate.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sConfigBitrate.nEncodeBitrate = 64000; + + OMX_INIT_STRUCT(&m_sConfigFramerate, OMX_CONFIG_FRAMERATETYPE); + m_sConfigFramerate.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sConfigFramerate.xEncodeFramerate = 30 << 16; + + OMX_INIT_STRUCT(&m_sConfigIntraRefreshVOP, OMX_CONFIG_INTRAREFRESHVOPTYPE); + m_sConfigIntraRefreshVOP.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sConfigIntraRefreshVOP.IntraRefreshVOP = OMX_FALSE; + + OMX_INIT_STRUCT(&m_sConfigFrameRotation, OMX_CONFIG_ROTATIONTYPE); + m_sConfigFrameRotation.nPortIndex = (OMX_U32) PORT_INDEX_IN; + m_sConfigFrameRotation.nRotation = 0; + + OMX_INIT_STRUCT(&m_sSessionQuantization, OMX_VIDEO_PARAM_QUANTIZATIONTYPE); + m_sSessionQuantization.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sSessionQuantization.nQpI = 9; + m_sSessionQuantization.nQpP = 6; + m_sSessionQuantization.nQpB = 2; + + OMX_INIT_STRUCT(&m_sAVCSliceFMO, OMX_VIDEO_PARAM_AVCSLICEFMO); + m_sAVCSliceFMO.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sAVCSliceFMO.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault; + m_sAVCSliceFMO.nNumSliceGroups = 0; + m_sAVCSliceFMO.nSliceGroupMapType = 0; + OMX_INIT_STRUCT(&m_sParamProfileLevel, OMX_VIDEO_PARAM_PROFILELEVELTYPE); + m_sParamProfileLevel.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + + OMX_INIT_STRUCT(&m_sIntraperiod, QOMX_VIDEO_INTRAPERIODTYPE); + m_sIntraperiod.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sIntraperiod.nPFrames = (m_sConfigFramerate.xEncodeFramerate * 2) - 1; + + OMX_INIT_STRUCT(&m_sErrorCorrection, OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE); + m_sErrorCorrection.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sErrorCorrection.bEnableDataPartitioning = OMX_FALSE; + m_sErrorCorrection.bEnableHEC = OMX_FALSE; + m_sErrorCorrection.bEnableResync = OMX_FALSE; + m_sErrorCorrection.bEnableRVLC = OMX_FALSE; + m_sErrorCorrection.nResynchMarkerSpacing = 0; + + OMX_INIT_STRUCT(&m_sIntraRefresh, OMX_VIDEO_PARAM_INTRAREFRESHTYPE); + m_sIntraRefresh.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sIntraRefresh.eRefreshMode = OMX_VIDEO_IntraRefreshMax; + + if(codec_type == OMX_VIDEO_CodingMPEG4) + { + m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple; + m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_MPEG4Level0; + } + else if(codec_type == OMX_VIDEO_CodingH263) + { + m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_H263ProfileBaseline; + m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_H263Level10; + } + else if(codec_type == OMX_VIDEO_CodingAVC) + { + m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_AVCProfileBaseline; + m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_AVCLevel1; + } + + // Initialize the video parameters for input port + OMX_INIT_STRUCT(&m_sInPortDef, OMX_PARAM_PORTDEFINITIONTYPE); + m_sInPortDef.nPortIndex= (OMX_U32) PORT_INDEX_IN; + m_sInPortDef.bEnabled = OMX_TRUE; + m_sInPortDef.bPopulated = OMX_FALSE; + m_sInPortDef.eDomain = OMX_PortDomainVideo; + m_sInPortDef.eDir = OMX_DirInput; + m_sInPortDef.format.video.cMIMEType = "YUV420"; + m_sInPortDef.format.video.nFrameWidth = OMX_CORE_QCIF_WIDTH; + m_sInPortDef.format.video.nFrameHeight = OMX_CORE_QCIF_HEIGHT; + m_sInPortDef.format.video.nStride = OMX_CORE_QCIF_WIDTH; + m_sInPortDef.format.video.nSliceHeight = OMX_CORE_QCIF_HEIGHT; + m_sInPortDef.format.video.nBitrate = 64000; + m_sInPortDef.format.video.xFramerate = 15 << 16; + m_sInPortDef.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + m_sInPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + + if(dev_get_buf_req(&m_sInPortDef.nBufferCountMin, + &m_sInPortDef.nBufferCountActual, + &m_sInPortDef.nBufferSize, + m_sInPortDef.nPortIndex) != true) + { + eRet = OMX_ErrorUndefined; + + } + + // Initialize the video parameters for output port + OMX_INIT_STRUCT(&m_sOutPortDef, OMX_PARAM_PORTDEFINITIONTYPE); + m_sOutPortDef.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sOutPortDef.bEnabled = OMX_TRUE; + m_sOutPortDef.bPopulated = OMX_FALSE; + m_sOutPortDef.eDomain = OMX_PortDomainVideo; + m_sOutPortDef.eDir = OMX_DirOutput; + m_sOutPortDef.format.video.nFrameWidth = OMX_CORE_QCIF_WIDTH; + m_sOutPortDef.format.video.nFrameHeight = OMX_CORE_QCIF_HEIGHT; + m_sOutPortDef.format.video.nBitrate = 64000; + m_sOutPortDef.format.video.xFramerate = 15 << 16; + m_sOutPortDef.format.video.eColorFormat = OMX_COLOR_FormatUnused; + if(codec_type == OMX_VIDEO_CodingMPEG4) + { + m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4; + } + else if(codec_type == OMX_VIDEO_CodingH263) + { + m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingH263; + } + else + { + m_sOutPortDef.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; + } + if(dev_get_buf_req(&m_sOutPortDef.nBufferCountMin, + &m_sOutPortDef.nBufferCountActual, + &m_sOutPortDef.nBufferSize, + m_sOutPortDef.nPortIndex) != true) + { + eRet = OMX_ErrorUndefined; + } + + // Initialize the video color format for input port + OMX_INIT_STRUCT(&m_sInPortFormat, OMX_VIDEO_PARAM_PORTFORMATTYPE); + m_sInPortFormat.nPortIndex = (OMX_U32) PORT_INDEX_IN; + m_sInPortFormat.nIndex = 0; + m_sInPortFormat.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + m_sInPortFormat.eCompressionFormat = OMX_VIDEO_CodingUnused; + + + // Initialize the compression format for output port + OMX_INIT_STRUCT(&m_sOutPortFormat, OMX_VIDEO_PARAM_PORTFORMATTYPE); + m_sOutPortFormat.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sOutPortFormat.nIndex = 0; + m_sOutPortFormat.eColorFormat = OMX_COLOR_FormatUnused; + if(codec_type == OMX_VIDEO_CodingMPEG4) + { + m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingMPEG4; + } + else if(codec_type == OMX_VIDEO_CodingH263) + { + m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingH263; + } + else + { + m_sOutPortFormat.eCompressionFormat = OMX_VIDEO_CodingAVC; + } + + // mandatory Indices for kronos test suite + OMX_INIT_STRUCT(&m_sPriorityMgmt, OMX_PRIORITYMGMTTYPE); + + OMX_INIT_STRUCT(&m_sInBufSupplier, OMX_PARAM_BUFFERSUPPLIERTYPE); + m_sInBufSupplier.nPortIndex = (OMX_U32) PORT_INDEX_IN; + + OMX_INIT_STRUCT(&m_sOutBufSupplier, OMX_PARAM_BUFFERSUPPLIERTYPE); + m_sOutBufSupplier.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + + + // mp4 specific init + OMX_INIT_STRUCT(&m_sParamMPEG4, OMX_VIDEO_PARAM_MPEG4TYPE); + m_sParamMPEG4.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sParamMPEG4.eProfile = OMX_VIDEO_MPEG4ProfileSimple; + m_sParamMPEG4.eLevel = OMX_VIDEO_MPEG4Level0; + m_sParamMPEG4.nSliceHeaderSpacing = 0; + m_sParamMPEG4.bSVH = OMX_FALSE; + m_sParamMPEG4.bGov = OMX_FALSE; + m_sParamMPEG4.nPFrames = (m_sOutPortFormat.xFramerate * 2 - 1); // 2 second intra period for default outport fps + m_sParamMPEG4.bACPred = OMX_TRUE; + m_sParamMPEG4.nTimeIncRes = 30; // delta = 2 @ 15 fps + m_sParamMPEG4.nAllowedPictureTypes = 2; // pframe and iframe + m_sParamMPEG4.nHeaderExtension = 1; // number of video packet headers per vop + m_sParamMPEG4.bReversibleVLC = OMX_FALSE; + + // h263 specific init + OMX_INIT_STRUCT(&m_sParamH263, OMX_VIDEO_PARAM_H263TYPE); + m_sParamH263.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sParamH263.nPFrames = (m_sOutPortFormat.xFramerate * 2 - 1); // 2 second intra period for default outport fps + m_sParamH263.nBFrames = 0; + m_sParamH263.eProfile = OMX_VIDEO_H263ProfileBaseline; + m_sParamH263.eLevel = OMX_VIDEO_H263Level10; + m_sParamH263.bPLUSPTYPEAllowed = OMX_FALSE; + m_sParamH263.nAllowedPictureTypes = 2; + m_sParamH263.bForceRoundingTypeToZero = OMX_TRUE; + m_sParamH263.nPictureHeaderRepetition = 0; + m_sParamH263.nGOBHeaderInterval = 1; + + // h264 specific init + OMX_INIT_STRUCT(&m_sParamAVC, OMX_VIDEO_PARAM_AVCTYPE); + m_sParamAVC.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + m_sParamAVC.nSliceHeaderSpacing = 0; + m_sParamAVC.nPFrames = (m_sOutPortFormat.xFramerate * 2 - 1); // 2 second intra period for default outport fps + m_sParamAVC.nBFrames = 0; + m_sParamAVC.bUseHadamard = OMX_FALSE; + m_sParamAVC.nRefFrames = 1; + m_sParamAVC.nRefIdx10ActiveMinus1 = 1; + m_sParamAVC.nRefIdx11ActiveMinus1 = 0; + m_sParamAVC.bEnableUEP = OMX_FALSE; + m_sParamAVC.bEnableFMO = OMX_FALSE; + m_sParamAVC.bEnableASO = OMX_FALSE; + m_sParamAVC.bEnableRS = OMX_FALSE; + m_sParamAVC.eProfile = OMX_VIDEO_AVCProfileBaseline; + m_sParamAVC.eLevel = OMX_VIDEO_AVCLevel1; + m_sParamAVC.nAllowedPictureTypes = 2; + m_sParamAVC.bFrameMBsOnly = OMX_FALSE; + m_sParamAVC.bMBAFF = OMX_FALSE; + m_sParamAVC.bEntropyCodingCABAC = OMX_FALSE; + m_sParamAVC.bWeightedPPrediction = OMX_FALSE; + m_sParamAVC.nWeightedBipredicitonMode = 0; + m_sParamAVC.bconstIpred = OMX_FALSE; + m_sParamAVC.bDirect8x8Inference = OMX_FALSE; + m_sParamAVC.bDirectSpatialTemporal = OMX_FALSE; + m_sParamAVC.nCabacInitIdc = 0; + m_sParamAVC.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; + + m_state = OMX_StateLoaded; + m_sExtraData = 0; + m_sDebugSliceinfo = 0; +#ifdef _ANDROID_ + char value[PROPERTY_VALUE_MAX] = {0}; + property_get("vidc.venc.debug.sliceinfo", value, "0"); + m_sDebugSliceinfo = (OMX_U32)atoi(value); + DEBUG_PRINT_HIGH("vidc.venc.debug.sliceinfo value is %d", m_sDebugSliceinfo); +#endif + + if(eRet == OMX_ErrorNone) + { + if(pipe(fds)) + { + DEBUG_PRINT_ERROR("ERROR: pipe creation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + else + { + if(fds[0] == 0 || fds[1] == 0) + { + if(pipe(fds)) + { + DEBUG_PRINT_ERROR("ERROR: pipe creation failed\n"); + eRet = OMX_ErrorInsufficientResources; + } + } + if(eRet == OMX_ErrorNone) + { + m_pipe_in = fds[0]; + m_pipe_out = fds[1]; + } + } + r = pthread_create(&msg_thread_id,0,message_thread,this); + + if(r < 0) + { + eRet = OMX_ErrorInsufficientResources; + } + else + { + r = pthread_create(&async_thread_id,0,async_venc_message_thread,this); + if(r < 0) + { + eRet = OMX_ErrorInsufficientResources; + } + } + } + + DEBUG_PRINT_HIGH("\n Component_init return value = 0x%x", eRet); + return eRet; +} + + +/* ====================================================================== +FUNCTION + omx_venc::Setparameter + +DESCRIPTION + OMX Set Parameter method implementation. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if successful. + +========================================================================== */ +OMX_ERRORTYPE omx_venc::set_parameter(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE paramIndex, + OMX_IN OMX_PTR paramData) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + + + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: Set Param in Invalid State\n"); + return OMX_ErrorInvalidState; + } + if(paramData == NULL) + { + DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid paramData \n"); + return OMX_ErrorBadParameter; + } + + /*set_parameter can be called in loaded state + or disabled port */ + if(m_state == OMX_StateLoaded + || m_sInPortDef.bEnabled == OMX_FALSE + || m_sOutPortDef.bEnabled == OMX_FALSE) + { + DEBUG_PRINT_LOW("Set Parameter called in valid state"); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Set Parameter called in Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + + switch(paramIndex) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d\n", + (int)portDefn->format.video.nFrameHeight, + (int)portDefn->format.video.nFrameWidth); + + if(PORT_INDEX_IN == portDefn->nPortIndex) + { + DEBUG_PRINT_LOW("\n i/p actual cnt requested = %d\n", portDefn->nBufferCountActual); + DEBUG_PRINT_LOW("\n i/p min cnt requested = %d\n", portDefn->nBufferCountMin); + DEBUG_PRINT_LOW("\n i/p buffersize requested = %d\n", portDefn->nBufferSize); + if(handle->venc_set_param(paramData,OMX_IndexParamPortDefinition) != true) + { + DEBUG_PRINT_ERROR("\nERROR: venc_set_param input failed"); + return OMX_ErrorUnsupportedSetting; + } + + DEBUG_PRINT_LOW("\n i/p previous actual cnt = %d\n", m_sInPortDef.nBufferCountActual); + DEBUG_PRINT_LOW("\n i/p previous min cnt = %d\n", m_sInPortDef.nBufferCountMin); + memcpy(&m_sInPortDef, portDefn,sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + +#ifdef _ANDROID_ICS_ + if (portDefn->format.video.eColorFormat == (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatAndroidOpaque) { + m_sInPortDef.format.video.eColorFormat = + OMX_COLOR_FormatYUV420SemiPlanar; + mUseProxyColorFormat = true; + } //else case not needed as color format is already updated in the memcpy above +#endif + /*Query Input Buffer Requirements*/ + dev_get_buf_req (&m_sInPortDef.nBufferCountMin, + &m_sInPortDef.nBufferCountActual, + &m_sInPortDef.nBufferSize, + m_sInPortDef.nPortIndex); + + /*Query ouput Buffer Requirements*/ + dev_get_buf_req (&m_sOutPortDef.nBufferCountMin, + &m_sOutPortDef.nBufferCountActual, + &m_sOutPortDef.nBufferSize, + m_sOutPortDef.nPortIndex); + m_sInPortDef.nBufferCountActual = portDefn->nBufferCountActual; + } + else if(PORT_INDEX_OUT == portDefn->nPortIndex) + { + DEBUG_PRINT_LOW("\n o/p actual cnt requested = %d\n", portDefn->nBufferCountActual); + DEBUG_PRINT_LOW("\n o/p min cnt requested = %d\n", portDefn->nBufferCountMin); + DEBUG_PRINT_LOW("\n o/p buffersize requested = %d\n", portDefn->nBufferSize); + if(handle->venc_set_param(paramData,OMX_IndexParamPortDefinition) != true) + { + DEBUG_PRINT_ERROR("\nERROR: venc_set_param output failed"); + return OMX_ErrorUnsupportedSetting; + } + memcpy(&m_sOutPortDef,portDefn,sizeof(struct OMX_PARAM_PORTDEFINITIONTYPE)); + update_profile_level(); //framerate , bitrate + + DEBUG_PRINT_LOW("\n o/p previous actual cnt = %d\n", m_sOutPortDef.nBufferCountActual); + DEBUG_PRINT_LOW("\n o/p previous min cnt = %d\n", m_sOutPortDef.nBufferCountMin); + m_sOutPortDef.nBufferCountActual = portDefn->nBufferCountActual; + } + else + { + DEBUG_PRINT_ERROR("ERROR: Set_parameter: Bad Port idx %d", + (int)portDefn->nPortIndex); + eRet = OMX_ErrorBadPortIndex; + } + m_sConfigFramerate.xEncodeFramerate = portDefn->format.video.xFramerate; + m_sConfigBitrate.nEncodeBitrate = portDefn->format.video.nBitrate; + m_sParamBitrate.nTargetBitrate = portDefn->format.video.nBitrate; + } + break; + + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = + (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d\n", + portFmt->eColorFormat); + //set the driver with the corresponding values + if(PORT_INDEX_IN == portFmt->nPortIndex) + { + if(handle->venc_set_param(paramData,OMX_IndexParamVideoPortFormat) != true) + { + return OMX_ErrorUnsupportedSetting; + } + + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat %d\n", + portFmt->eColorFormat); + update_profile_level(); //framerate + +#ifdef _ANDROID_ICS_ + if (portFmt->eColorFormat == + (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatAndroidOpaque) { + m_sInPortFormat.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + mUseProxyColorFormat = true; + } + else +#endif + { + m_sInPortFormat.eColorFormat = portFmt->eColorFormat; + } + m_sInPortFormat.xFramerate = portFmt->xFramerate; + } + //TODO if no use case for O/P port,delet m_sOutPortFormat + } + break; + case OMX_IndexParamVideoInit: + { //TODO, do we need this index set param + OMX_PORT_PARAM_TYPE* pParam = (OMX_PORT_PARAM_TYPE*)(paramData); + DEBUG_PRINT_LOW("\n Set OMX_IndexParamVideoInit called"); + break; + } + + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoBitrate"); + if(handle->venc_set_param(paramData,OMX_IndexParamVideoBitrate) != true) + { + return OMX_ErrorUnsupportedSetting; + } + m_sParamBitrate.nTargetBitrate = pParam->nTargetBitrate; + m_sParamBitrate.eControlRate = pParam->eControlRate; + update_profile_level(); //bitrate + m_sConfigBitrate.nEncodeBitrate = pParam->nTargetBitrate; + m_sInPortDef.format.video.nBitrate = pParam->nTargetBitrate; + m_sOutPortDef.format.video.nBitrate = pParam->nTargetBitrate; + DEBUG_PRINT_LOW("\nbitrate = %u", m_sOutPortDef.format.video.nBitrate); + break; + } + case OMX_IndexParamVideoMpeg4: + { + OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData; + OMX_VIDEO_PARAM_MPEG4TYPE mp4_param; + memcpy(&mp4_param, pParam, sizeof(struct OMX_VIDEO_PARAM_MPEG4TYPE)); + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4"); + if(pParam->eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) + { +#ifdef MAX_RES_1080P + if(pParam->nBFrames) + { + DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported"); + mp4_param.nBFrames = 1; + } +#else + if(pParam->nBFrames) + { + DEBUG_PRINT_ERROR("Warning: B frames not supported\n"); + mp4_param.nBFrames = 0; + } +#endif + } + else + { + if(pParam->nBFrames) + { + DEBUG_PRINT_ERROR("Warning: B frames not supported\n"); + mp4_param.nBFrames = 0; + } + } + if(handle->venc_set_param(&mp4_param,OMX_IndexParamVideoMpeg4) != true) + { + return OMX_ErrorUnsupportedSetting; + } + memcpy(&m_sParamMPEG4,pParam, sizeof(struct OMX_VIDEO_PARAM_MPEG4TYPE)); + break; + } + case OMX_IndexParamVideoH263: + { + OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263"); + if(handle->venc_set_param(paramData,OMX_IndexParamVideoH263) != true) + { + return OMX_ErrorUnsupportedSetting; + } + memcpy(&m_sParamH263,pParam, sizeof(struct OMX_VIDEO_PARAM_H263TYPE)); + break; + } + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData; + OMX_VIDEO_PARAM_AVCTYPE avc_param; + memcpy(&avc_param, pParam, sizeof( struct OMX_VIDEO_PARAM_AVCTYPE)); + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc"); + + if((pParam->eProfile == OMX_VIDEO_AVCProfileHigh)|| + (pParam->eProfile == OMX_VIDEO_AVCProfileMain)) + { +#ifdef MAX_RES_1080P + if(pParam->nBFrames) + { + DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported"); + avc_param.nBFrames = 1; + } + if(pParam->nRefFrames != 2) + { + DEBUG_PRINT_ERROR("Warning: 2 RefFrames are needed, changing RefFrames from %d to 2", pParam->nRefFrames); + avc_param.nRefFrames = 2; + } +#else + if(pParam->nBFrames) + { + DEBUG_PRINT_ERROR("Warning: B frames not supported\n"); + avc_param.nBFrames = 0; + } + if(pParam->nRefFrames != 1) + { + DEBUG_PRINT_ERROR("Warning: Only 1 RefFrame is supported, changing RefFrame from %d to 1)", pParam->nRefFrames); + avc_param.nRefFrames = 1; + } +#endif + } + else + { + if(pParam->nRefFrames != 1) + { + DEBUG_PRINT_ERROR("Warning: Only 1 RefFrame is supported, changing RefFrame from %d to 1)", pParam->nRefFrames); + avc_param.nRefFrames = 1; + } + if(pParam->nBFrames) + { + DEBUG_PRINT_ERROR("Warning: B frames not supported\n"); + avc_param.nBFrames = 0; + } + } + if(handle->venc_set_param(&avc_param,OMX_IndexParamVideoAvc) != true) + { + return OMX_ErrorUnsupportedSetting; + } + memcpy(&m_sParamAVC,pParam, sizeof(struct OMX_VIDEO_PARAM_AVCTYPE)); + break; + } + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoProfileLevelCurrent"); + if(handle->venc_set_param(pParam,OMX_IndexParamVideoProfileLevelCurrent) != true) + { + DEBUG_PRINT_ERROR("set_parameter: OMX_IndexParamVideoProfileLevelCurrent failed for Profile: %d " + "Level :%d", pParam->eProfile, pParam->eLevel); + return OMX_ErrorUnsupportedSetting; + } + m_sParamProfileLevel.eProfile = pParam->eProfile; + m_sParamProfileLevel.eLevel = pParam->eLevel; + + if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.mpeg4",\ + OMX_MAX_STRINGNAME_SIZE)) + { + m_sParamMPEG4.eProfile = (OMX_VIDEO_MPEG4PROFILETYPE)m_sParamProfileLevel.eProfile; + m_sParamMPEG4.eLevel = (OMX_VIDEO_MPEG4LEVELTYPE)m_sParamProfileLevel.eLevel; + DEBUG_PRINT_LOW("\n MPEG4 profile = %d, level = %d", m_sParamMPEG4.eProfile, + m_sParamMPEG4.eLevel); + } + else if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.h263",\ + OMX_MAX_STRINGNAME_SIZE)) + { + m_sParamH263.eProfile = (OMX_VIDEO_H263PROFILETYPE)m_sParamProfileLevel.eProfile; + m_sParamH263.eLevel = (OMX_VIDEO_H263LEVELTYPE)m_sParamProfileLevel.eLevel; + DEBUG_PRINT_LOW("\n H263 profile = %d, level = %d", m_sParamH263.eProfile, + m_sParamH263.eLevel); + } + else if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.avc",\ + OMX_MAX_STRINGNAME_SIZE)) + { + m_sParamAVC.eProfile = (OMX_VIDEO_AVCPROFILETYPE)m_sParamProfileLevel.eProfile; + m_sParamAVC.eLevel = (OMX_VIDEO_AVCLEVELTYPE)m_sParamProfileLevel.eLevel; + DEBUG_PRINT_LOW("\n AVC profile = %d, level = %d", m_sParamAVC.eProfile, + m_sParamAVC.eLevel); + } + break; + } + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *comp_role; + comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s\n", + comp_role->cRole); + + if((m_state == OMX_StateLoaded)&& + !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) + { + DEBUG_PRINT_LOW("Set Parameter called in valid state"); + } + else + { + DEBUG_PRINT_ERROR("Set Parameter called in Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + + if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((char*)comp_role->cRole,"video_encoder.avc",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_encoder.avc",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown Index %s\n", comp_role->cRole); + eRet =OMX_ErrorUnsupportedSetting; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((const char*)comp_role->cRole,"video_encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_encoder.mpeg4",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown Index %s\n", comp_role->cRole); + eRet = OMX_ErrorUnsupportedSetting; + } + } + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((const char*)comp_role->cRole,"video_encoder.h263",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_encoder.h263",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown Index %s\n", comp_role->cRole); + eRet =OMX_ErrorUnsupportedSetting; + } + } +#ifdef _MSM8974_ + else if(!strncmp((char*)m_nkind, "OMX.qcom.video.encoder.vp8",OMX_MAX_STRINGNAME_SIZE)) + { + if(!strncmp((const char*)comp_role->cRole,"video_encoder.vp8",OMX_MAX_STRINGNAME_SIZE)) + { + strlcpy((char*)m_cRole,"video_encoder.vp8",OMX_MAX_STRINGNAME_SIZE); + } + else + { + DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown Index %s\n", comp_role->cRole); + eRet =OMX_ErrorUnsupportedSetting; + } + } +#endif + else + { + DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown param %s\n", m_nkind); + eRet = OMX_ErrorInvalidComponentName; + } + break; + } + + case OMX_IndexParamPriorityMgmt: + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt"); + if(m_state != OMX_StateLoaded) + { + DEBUG_PRINT_ERROR("ERROR: Set Parameter called in Invalid State\n"); + return OMX_ErrorIncorrectStateOperation; + } + OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %d\n", + priorityMgmtype->nGroupID); + + DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %d\n", + priorityMgmtype->nGroupPriority); + + m_sPriorityMgmt.nGroupID = priorityMgmtype->nGroupID; + m_sPriorityMgmt.nGroupPriority = priorityMgmtype->nGroupPriority; + + break; + } + + case OMX_IndexParamCompBufferSupplier: + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier"); + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d\n", + bufferSupplierType->eBufferSupplier); + if(bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1) + m_sInBufSupplier.eBufferSupplier = bufferSupplierType->eBufferSupplier; + + else + + eRet = OMX_ErrorBadPortIndex; + + break; + + } + case OMX_IndexParamVideoQuantization: + { + DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoQuantization\n"); + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData; + if(session_qp->nPortIndex == PORT_INDEX_OUT) + { + if(handle->venc_set_param(paramData, OMX_IndexParamVideoQuantization) != true) + { + return OMX_ErrorUnsupportedSetting; + } + m_sSessionQuantization.nQpI = session_qp->nQpI; + m_sSessionQuantization.nQpP = session_qp->nQpP; + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Unsupported port Index for Session QP setting\n"); + eRet = OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_QcomIndexPortDefn: + { + OMX_QCOM_PARAM_PORTDEFINITIONTYPE* pParam = + (OMX_QCOM_PARAM_PORTDEFINITIONTYPE*)paramData; + DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexPortDefn"); + if(pParam->nPortIndex == (OMX_U32)PORT_INDEX_IN) + { + if(pParam->nMemRegion > OMX_QCOM_MemRegionInvalid && + pParam->nMemRegion < OMX_QCOM_MemRegionMax) + { + m_use_input_pmem = OMX_TRUE; + } + else + { + m_use_input_pmem = OMX_FALSE; + } + } + else if (pParam->nPortIndex == (OMX_U32)PORT_INDEX_OUT) + { + if(pParam->nMemRegion > OMX_QCOM_MemRegionInvalid && + pParam->nMemRegion < OMX_QCOM_MemRegionMax) + { + m_use_output_pmem = OMX_TRUE; + } + else + { + m_use_output_pmem = OMX_FALSE; + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: SetParameter called on unsupported Port Index for QcomPortDefn"); + return OMX_ErrorBadPortIndex; + } + break; + } + + case OMX_IndexParamVideoErrorCorrection: + { + DEBUG_PRINT_LOW("OMX_IndexParamVideoErrorCorrection\n"); + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* pParam = + (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*)paramData; + if(!handle->venc_set_param(paramData, OMX_IndexParamVideoErrorCorrection)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Error Resilience failed"); + return OMX_ErrorUnsupportedSetting; + } + memcpy(&m_sErrorCorrection,pParam, sizeof(m_sErrorCorrection)); + break; + } + case OMX_IndexParamVideoIntraRefresh: + { + DEBUG_PRINT_LOW("set_param:OMX_IndexParamVideoIntraRefresh\n"); + OMX_VIDEO_PARAM_INTRAREFRESHTYPE* pParam = + (OMX_VIDEO_PARAM_INTRAREFRESHTYPE*)paramData; + if(!handle->venc_set_param(paramData,OMX_IndexParamVideoIntraRefresh)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra refresh failed"); + return OMX_ErrorUnsupportedSetting; + } + memcpy(&m_sIntraRefresh, pParam, sizeof(m_sIntraRefresh)); + break; + } +#ifdef _ANDROID_ICS_ + case OMX_QcomIndexParamVideoEncodeMetaBufferMode: + { + StoreMetaDataInBuffersParams *pParam = + (StoreMetaDataInBuffersParams*)paramData; + if(pParam->nPortIndex == PORT_INDEX_IN) + { + if(pParam->bStoreMetaData != meta_mode_enable) + { + if(!handle->venc_set_meta_mode(pParam->bStoreMetaData)) + { + DEBUG_PRINT_ERROR("\nERROR: set Metabuffer mode %d fail", + pParam->bStoreMetaData); + return OMX_ErrorUnsupportedSetting; + } + meta_mode_enable = pParam->bStoreMetaData; + if(meta_mode_enable) { + m_sInPortDef.nBufferCountActual = 4; + if(handle->venc_set_param(&m_sInPortDef,OMX_IndexParamPortDefinition) != true) + { + DEBUG_PRINT_ERROR("\nERROR: venc_set_param input failed"); + return OMX_ErrorUnsupportedSetting; + } + } else { + /*TODO: reset encoder driver Meta mode*/ + dev_get_buf_req (&m_sOutPortDef.nBufferCountMin, + &m_sOutPortDef.nBufferCountActual, + &m_sOutPortDef.nBufferSize, + m_sOutPortDef.nPortIndex); + } + } + } + break; + } +#endif +#ifndef MAX_RES_720P + case OMX_QcomIndexParamIndexExtraDataType: + { + DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamIndexExtraDataType"); + QOMX_INDEXEXTRADATATYPE *pParam = (QOMX_INDEXEXTRADATATYPE *)paramData; + if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoEncoderSliceInfo) + { + if (pParam->nPortIndex == PORT_INDEX_OUT) + { + if (pParam->bEnabled == OMX_TRUE) + m_sExtraData |= VEN_EXTRADATA_SLICEINFO; + else + m_sExtraData &= ~VEN_EXTRADATA_SLICEINFO; + DEBUG_PRINT_HIGH("set_param: m_sExtraData=%x", m_sExtraData); + if(handle->venc_set_param(&m_sExtraData, + (OMX_INDEXTYPE)OMX_ExtraDataVideoEncoderSliceInfo) != true) + { + DEBUG_PRINT_ERROR("ERROR: Setting " + "OMX_QcomIndexParamIndexExtraDataType failed"); + return OMX_ErrorUnsupportedSetting; + } + else + { + m_sOutPortDef.nPortIndex = PORT_INDEX_OUT; + dev_get_buf_req(&m_sOutPortDef.nBufferCountMin, + &m_sOutPortDef.nBufferCountActual, + &m_sOutPortDef.nBufferSize, + m_sOutPortDef.nPortIndex); + DEBUG_PRINT_HIGH("updated out_buf_req: buffer cnt=%d, " + "count min=%d, buffer size=%d", + m_sOutPortDef.nBufferCountActual, + m_sOutPortDef.nBufferCountMin, + m_sOutPortDef.nBufferSize); + } + } + else + { + DEBUG_PRINT_ERROR("set_parameter: slice information is " + "valid for output port only"); + eRet = OMX_ErrorUnsupportedIndex; + } + } + else + { + DEBUG_PRINT_ERROR("set_parameter: unsupported index (%x), " + "only slice information extradata is supported", pParam->nIndex); + eRet = OMX_ErrorUnsupportedIndex; + } + break; + } +#endif + case OMX_QcomIndexParamVideoMaxAllowedBitrateCheck: + { + QOMX_EXTNINDEX_PARAMTYPE* pParam = + (QOMX_EXTNINDEX_PARAMTYPE*)paramData; + if(pParam->nPortIndex == PORT_INDEX_OUT) + { + handle->m_max_allowed_bitrate_check = + ((pParam->bEnable == OMX_TRUE) ? true : false); + DEBUG_PRINT_HIGH("set_parameter: max allowed bitrate check %s", + ((pParam->bEnable == OMX_TRUE) ? "enabled" : "disabled")); + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMX_QcomIndexParamVideoMaxAllowedBitrateCheck " + " called on wrong port(%d)", pParam->nPortIndex); + return OMX_ErrorBadPortIndex; + } + break; + } +#ifdef MAX_RES_1080P + case OMX_QcomIndexEnableSliceDeliveryMode: + { + QOMX_EXTNINDEX_PARAMTYPE* pParam = + (QOMX_EXTNINDEX_PARAMTYPE*)paramData; + if(pParam->nPortIndex == PORT_INDEX_OUT) + { + if(!handle->venc_set_param(paramData, + (OMX_INDEXTYPE)OMX_QcomIndexEnableSliceDeliveryMode)) + { + DEBUG_PRINT_ERROR("ERROR: Request for setting slice delivery mode failed"); + return OMX_ErrorUnsupportedSetting; + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: OMX_QcomIndexEnableSliceDeliveryMode " + "called on wrong port(%d)", pParam->nPortIndex); + return OMX_ErrorBadPortIndex; + } + break; + } +#endif + case OMX_IndexParamVideoSliceFMO: + default: + { + DEBUG_PRINT_ERROR("ERROR: Setparameter: unknown param %d\n", paramIndex); + eRet = OMX_ErrorUnsupportedIndex; + break; + } + } + return eRet; +} + +bool omx_venc::update_profile_level() +{ + OMX_U32 eProfile, eLevel; + + if(!handle->venc_get_profile_level(&eProfile,&eLevel)) + { + DEBUG_PRINT_ERROR("\nFailed to update the profile_level\n"); + return false; + } + + m_sParamProfileLevel.eProfile = (OMX_VIDEO_MPEG4PROFILETYPE)eProfile; + m_sParamProfileLevel.eLevel = (OMX_VIDEO_MPEG4LEVELTYPE)eLevel; + + if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.mpeg4",\ + OMX_MAX_STRINGNAME_SIZE)) + { + m_sParamMPEG4.eProfile = (OMX_VIDEO_MPEG4PROFILETYPE)eProfile; + m_sParamMPEG4.eLevel = (OMX_VIDEO_MPEG4LEVELTYPE)eLevel; + DEBUG_PRINT_LOW("\n MPEG4 profile = %d, level = %d", m_sParamMPEG4.eProfile, + m_sParamMPEG4.eLevel); + } + else if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.h263",\ + OMX_MAX_STRINGNAME_SIZE)) + { + m_sParamH263.eProfile = (OMX_VIDEO_H263PROFILETYPE)eProfile; + m_sParamH263.eLevel = (OMX_VIDEO_H263LEVELTYPE)eLevel; + DEBUG_PRINT_LOW("\n H263 profile = %d, level = %d", m_sParamH263.eProfile, + m_sParamH263.eLevel); + } + else if(!strncmp((char *)m_nkind, "OMX.qcom.video.encoder.avc",\ + OMX_MAX_STRINGNAME_SIZE)) + { + m_sParamAVC.eProfile = (OMX_VIDEO_AVCPROFILETYPE)eProfile; + m_sParamAVC.eLevel = (OMX_VIDEO_AVCLEVELTYPE)eLevel; + DEBUG_PRINT_LOW("\n AVC profile = %d, level = %d", m_sParamAVC.eProfile, + m_sParamAVC.eLevel); + } + return true; +} +/* ====================================================================== +FUNCTION + omx_video::SetConfig + +DESCRIPTION + OMX Set Config method implementation + +PARAMETERS + . + +RETURN VALUE + OMX Error None if successful. +========================================================================== */ +OMX_ERRORTYPE omx_venc::set_config(OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_INDEXTYPE configIndex, + OMX_IN OMX_PTR configData) +{ + if(configData == NULL) + { + DEBUG_PRINT_ERROR("ERROR: param is null"); + return OMX_ErrorBadParameter; + } + + if(m_state == OMX_StateInvalid) + { + DEBUG_PRINT_ERROR("ERROR: config called in Invalid state"); + return OMX_ErrorIncorrectStateOperation; + } + + // params will be validated prior to venc_init + switch(configIndex) + { + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE* pParam = + reinterpret_cast(configData); + DEBUG_PRINT_LOW("\n omx_venc:: set_config(): OMX_IndexConfigVideoBitrate"); + + if(pParam->nPortIndex == PORT_INDEX_OUT) + { + if(handle->venc_set_config(configData, OMX_IndexConfigVideoBitrate) != true) + { + DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigVideoBitrate failed"); + return OMX_ErrorUnsupportedSetting; + } + + m_sConfigBitrate.nEncodeBitrate = pParam->nEncodeBitrate; + m_sParamBitrate.nTargetBitrate = pParam->nEncodeBitrate; + m_sOutPortDef.format.video.nBitrate = pParam->nEncodeBitrate; + } + else + { + DEBUG_PRINT_ERROR("ERROR: Unsupported port index: %u", pParam->nPortIndex); + return OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE* pParam = + reinterpret_cast(configData); + DEBUG_PRINT_LOW("\n omx_venc:: set_config(): OMX_IndexConfigVideoFramerate"); + + if(pParam->nPortIndex == PORT_INDEX_OUT) + { + if(handle->venc_set_config(configData, OMX_IndexConfigVideoFramerate) != true) + { + DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigVideoFramerate failed"); + return OMX_ErrorUnsupportedSetting; + } + + m_sConfigFramerate.xEncodeFramerate = pParam->xEncodeFramerate; + m_sOutPortDef.format.video.xFramerate = pParam->xEncodeFramerate; + m_sOutPortFormat.xFramerate = pParam->xEncodeFramerate; + } + else + { + DEBUG_PRINT_ERROR("ERROR: Unsupported port index: %u", pParam->nPortIndex); + return OMX_ErrorBadPortIndex; + } + + break; + } + case QOMX_IndexConfigVideoIntraperiod: + { + QOMX_VIDEO_INTRAPERIODTYPE* pParam = + reinterpret_cast(configData); + + if(pParam->nPortIndex == PORT_INDEX_OUT) + { +#ifdef MAX_RES_720P + if(pParam->nBFrames > 0) + { + DEBUG_PRINT_ERROR("B frames not supported\n"); + return OMX_ErrorUnsupportedSetting; + } +#endif + if(handle->venc_set_config(configData, (OMX_INDEXTYPE) QOMX_IndexConfigVideoIntraperiod) != true) + { + DEBUG_PRINT_ERROR("ERROR: Setting QOMX_IndexConfigVideoIntraperiod failed"); + return OMX_ErrorUnsupportedSetting; + } + m_sIntraperiod.nPFrames = pParam->nPFrames; + m_sIntraperiod.nBFrames = pParam->nBFrames; + m_sIntraperiod.nIDRPeriod = pParam->nIDRPeriod; + + if(m_sOutPortFormat.eCompressionFormat == OMX_VIDEO_CodingMPEG4) + { + m_sParamMPEG4.nPFrames = pParam->nPFrames; + if(m_sParamMPEG4.eProfile != OMX_VIDEO_MPEG4ProfileSimple) + m_sParamMPEG4.nBFrames = pParam->nBFrames; + else + m_sParamMPEG4.nBFrames = 0; + } + else if(m_sOutPortFormat.eCompressionFormat == OMX_VIDEO_CodingH263) + { + m_sParamH263.nPFrames = pParam->nPFrames; + } + else + { + m_sParamAVC.nPFrames = pParam->nPFrames; + if(m_sParamAVC.eProfile != OMX_VIDEO_AVCProfileBaseline) + m_sParamAVC.nBFrames = pParam->nBFrames; + else + m_sParamAVC.nBFrames = 0; + } + } + else + { + DEBUG_PRINT_ERROR("ERROR: (QOMX_IndexConfigVideoIntraperiod) Unsupported port index: %u", pParam->nPortIndex); + return OMX_ErrorBadPortIndex; + } + + break; + } + + case OMX_IndexConfigVideoIntraVOPRefresh: + { + OMX_CONFIG_INTRAREFRESHVOPTYPE* pParam = + reinterpret_cast(configData); + + if(pParam->nPortIndex == PORT_INDEX_OUT) + { + if(handle->venc_set_config(configData, + OMX_IndexConfigVideoIntraVOPRefresh) != true) + { + DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigVideoIntraVOPRefresh failed"); + return OMX_ErrorUnsupportedSetting; + } + + m_sConfigIntraRefreshVOP.IntraRefreshVOP = pParam->IntraRefreshVOP; + } + else + { + DEBUG_PRINT_ERROR("ERROR: Unsupported port index: %u", pParam->nPortIndex); + return OMX_ErrorBadPortIndex; + } + + break; + } + case OMX_IndexConfigCommonRotate: + { + OMX_CONFIG_ROTATIONTYPE *pParam = + reinterpret_cast(configData); + OMX_S32 nRotation; + + if(pParam->nPortIndex != PORT_INDEX_IN){ + DEBUG_PRINT_ERROR("ERROR: Unsupported port index: %u", pParam->nPortIndex); + return OMX_ErrorBadPortIndex; + } + if( pParam->nRotation == 0 || + pParam->nRotation == 90 || + pParam->nRotation == 180 || + pParam->nRotation == 270 ) { + DEBUG_PRINT_HIGH("\nset_config: Rotation Angle %u", pParam->nRotation); + } else { + DEBUG_PRINT_ERROR("ERROR: un supported Rotation %u", pParam->nRotation); + return OMX_ErrorUnsupportedSetting; + } + nRotation = pParam->nRotation - m_sConfigFrameRotation.nRotation; + if(nRotation < 0) + nRotation = -nRotation; + if(nRotation == 90 || nRotation == 270) { + DEBUG_PRINT_HIGH("\nset_config: updating device Dims"); + if(handle->venc_set_config(configData, + OMX_IndexConfigCommonRotate) != true) { + DEBUG_PRINT_ERROR("ERROR: Set OMX_IndexConfigCommonRotate failed"); + return OMX_ErrorUnsupportedSetting; + } else { + OMX_U32 nFrameWidth; + + DEBUG_PRINT_HIGH("\nset_config: updating port Dims"); + + nFrameWidth = m_sInPortDef.format.video.nFrameWidth; + m_sInPortDef.format.video.nFrameWidth = + m_sInPortDef.format.video.nFrameHeight; + m_sInPortDef.format.video.nFrameHeight = nFrameWidth; + + m_sOutPortDef.format.video.nFrameWidth = + m_sInPortDef.format.video.nFrameWidth; + m_sOutPortDef.format.video.nFrameHeight = + m_sInPortDef.format.video.nFrameHeight; + m_sConfigFrameRotation.nRotation = pParam->nRotation; + } + } else { + m_sConfigFrameRotation.nRotation = pParam->nRotation; + } + break; + } + case OMX_QcomIndexConfigVideoFramePackingArrangement: + { + if(m_sOutPortFormat.eCompressionFormat == OMX_VIDEO_CodingAVC) + { + OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt = + (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData; + extra_data_handle.set_frame_pack_data(configFmt); + } + else + { + DEBUG_PRINT_ERROR("ERROR: FramePackingData not supported for non AVC compression"); + } + break; + } + default: + DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex); + break; + } + + return OMX_ErrorNone; +} + +/* ====================================================================== +FUNCTION + omx_venc::ComponentDeInit + +DESCRIPTION + Destroys the component and release memory allocated to the heap. + +PARAMETERS + . + +RETURN VALUE + OMX Error None if everything successful. + +========================================================================== */ +OMX_ERRORTYPE omx_venc::component_deinit(OMX_IN OMX_HANDLETYPE hComp) +{ + OMX_U32 i = 0; + DEBUG_PRINT_HIGH("\n omx_venc(): Inside component_deinit()"); + if(OMX_StateLoaded != m_state) + { + DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d\n",\ + m_state); + } + if(m_out_mem_ptr) + { + DEBUG_PRINT_LOW("Freeing the Output Memory\n"); + for(i=0; i< m_sOutPortDef.nBufferCountActual; i++ ) + { + free_output_buffer (&m_out_mem_ptr[i]); + } + free(m_out_mem_ptr); + m_out_mem_ptr = NULL; + } + + /*Check if the input buffers have to be cleaned up*/ + if(m_inp_mem_ptr +#ifdef _ANDROID_ICS_ + && !meta_mode_enable +#endif + ) + { + DEBUG_PRINT_LOW("Freeing the Input Memory\n"); + for(i=0; ivenc_close(); + DEBUG_PRINT_HIGH("Deleting HANDLE[%p]\n", handle); + delete (handle); + DEBUG_PRINT_HIGH("OMX_Venc:Component Deinit\n"); + return OMX_ErrorNone; +} + + +OMX_U32 omx_venc::dev_stop( void) +{ + return handle->venc_stop(); +} + + +OMX_U32 omx_venc::dev_pause(void) +{ + return handle->venc_pause(); +} + +OMX_U32 omx_venc::dev_start(void) +{ + return handle->venc_start(); +} + +OMX_U32 omx_venc::dev_flush(unsigned port) +{ + return handle->venc_flush(port); +} +OMX_U32 omx_venc::dev_resume(void) +{ + return handle->venc_resume(); +} + +OMX_U32 omx_venc::dev_start_done(void) +{ + return handle->venc_start_done(); +} + +OMX_U32 omx_venc::dev_stop_done(void) +{ + return handle->venc_stop_done(); +} + +bool omx_venc::dev_use_buf(void *buf_addr,unsigned port,unsigned index) +{ + return handle->venc_use_buf(buf_addr,port,index); +} + +bool omx_venc::dev_free_buf(void *buf_addr,unsigned port) +{ + return handle->venc_free_buf(buf_addr,port); +} + +bool omx_venc::dev_empty_buf(void *buffer, void *pmem_data_buf,unsigned index,unsigned fd) +{ + return handle->venc_empty_buf(buffer, pmem_data_buf,index,fd); +} + +bool omx_venc::dev_fill_buf(void *buffer, void *pmem_data_buf,unsigned index,unsigned fd) +{ + return handle->venc_fill_buf(buffer, pmem_data_buf,index,fd); +} + +bool omx_venc::dev_get_seq_hdr(void *buffer, unsigned size, unsigned *hdrlen) +{ + return handle->venc_get_seq_hdr(buffer, size, hdrlen); +} + +bool omx_venc::dev_loaded_start() +{ + return handle->venc_loaded_start(); +} + +bool omx_venc::dev_loaded_stop() +{ + return handle->venc_loaded_stop(); +} + +bool omx_venc::dev_loaded_start_done() +{ + return handle->venc_loaded_start_done(); +} + +bool omx_venc::dev_loaded_stop_done() +{ + return handle->venc_loaded_stop_done(); +} + +bool omx_venc::dev_get_buf_req(OMX_U32 *min_buff_count, + OMX_U32 *actual_buff_count, + OMX_U32 *buff_size, + OMX_U32 port) +{ + return handle->venc_get_buf_req(min_buff_count, + actual_buff_count, + buff_size, + port); + +} + +bool omx_venc::dev_set_buf_req(OMX_U32 *min_buff_count, + OMX_U32 *actual_buff_count, + OMX_U32 *buff_size, + OMX_U32 port) +{ + return handle->venc_set_buf_req(min_buff_count, + actual_buff_count, + buff_size, + port); + +} + +int omx_venc::async_message_process (void *context, void* message) +{ + omx_video* omx = NULL; + struct venc_msg *m_sVenc_msg = NULL; + OMX_BUFFERHEADERTYPE* omxhdr = NULL; + struct venc_buffer *temp_buff = NULL; + + if(context == NULL || message == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: omx_venc::async_message_process invalid i/p params"); + return -1; + } + m_sVenc_msg = (struct venc_msg *)message; + + omx = reinterpret_cast(context); + + if(m_sVenc_msg->statuscode != VEN_S_SUCCESS) + { + DEBUG_PRINT_ERROR("\nERROR: async_msg_process() - Error statuscode = %d\n", + m_sVenc_msg->statuscode); + omx->omx_report_error(); + } + + DEBUG_PRINT_LOW("\n omx_venc::async_message_process- msgcode = %d\n", + m_sVenc_msg->msgcode); + switch(m_sVenc_msg->msgcode) + { + + case VEN_MSG_START: + omx->post_event (NULL,m_sVenc_msg->statuscode,\ + OMX_COMPONENT_GENERATE_START_DONE); + break; + + case VEN_MSG_STOP: + omx->post_event (NULL,m_sVenc_msg->statuscode,\ + OMX_COMPONENT_GENERATE_STOP_DONE); + break; + + case VEN_MSG_RESUME: + omx->post_event (NULL,m_sVenc_msg->statuscode,\ + OMX_COMPONENT_GENERATE_RESUME_DONE); + break; + + case VEN_MSG_PAUSE: + omx->post_event (NULL,m_sVenc_msg->statuscode,\ + OMX_COMPONENT_GENERATE_PAUSE_DONE); + + break; + + case VEN_MSG_FLUSH_INPUT_DONE: + + omx->post_event (NULL,m_sVenc_msg->statuscode,\ + OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH); + break; + case VEN_MSG_FLUSH_OUPUT_DONE: + omx->post_event (NULL,m_sVenc_msg->statuscode,\ + OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH); + break; + case VEN_MSG_INPUT_BUFFER_DONE: + omxhdr = (OMX_BUFFERHEADERTYPE* )\ + m_sVenc_msg->buf.clientdata; + + if(omxhdr == NULL || + ((OMX_U32)(omxhdr - omx->m_inp_mem_ptr) > omx->m_sInPortDef.nBufferCountActual) ) + { + omxhdr = NULL; + m_sVenc_msg->statuscode = VEN_S_EFAIL; + } +#ifdef _ANDROID_ICS_ + omx->omx_release_meta_buffer(omxhdr); +#endif + omx->post_event ((unsigned int)omxhdr,m_sVenc_msg->statuscode, + OMX_COMPONENT_GENERATE_EBD); + break; + case VEN_MSG_OUTPUT_BUFFER_DONE: + + omxhdr = (OMX_BUFFERHEADERTYPE*)m_sVenc_msg->buf.clientdata; + + if( (omxhdr != NULL) && + ((OMX_U32)(omxhdr - omx->m_out_mem_ptr) < omx->m_sOutPortDef.nBufferCountActual)) + { + if(m_sVenc_msg->buf.len <= omxhdr->nAllocLen) + { + omxhdr->nFilledLen = m_sVenc_msg->buf.len; + omxhdr->nOffset = m_sVenc_msg->buf.offset; + omxhdr->nTimeStamp = m_sVenc_msg->buf.timestamp; + DEBUG_PRINT_LOW("\n o/p TS = %u", (OMX_U32)m_sVenc_msg->buf.timestamp); + omxhdr->nFlags = m_sVenc_msg->buf.flags; + + /*Use buffer case*/ + if(omx->output_use_buffer && !omx->m_use_output_pmem) + { + DEBUG_PRINT_LOW("\n memcpy() for o/p Heap UseBuffer"); + memcpy(omxhdr->pBuffer, + (m_sVenc_msg->buf.ptrbuffer), + m_sVenc_msg->buf.len); + } + } + else + { + omxhdr->nFilledLen = 0; + } + + } + else + { + omxhdr = NULL; + m_sVenc_msg->statuscode = VEN_S_EFAIL; + } + + omx->post_event ((unsigned int)omxhdr,m_sVenc_msg->statuscode, + OMX_COMPONENT_GENERATE_FBD); + break; + case VEN_MSG_NEED_OUTPUT_BUFFER: + //TBD what action needs to be done here?? + break; + default: + break; + } + return 0; +} diff --git a/mm-video/vidc/venc/src/video_encoder_device.cpp b/mm-video/vidc/venc/src/video_encoder_device.cpp new file mode 100755 index 0000000..63b9d98 --- /dev/null +++ b/mm-video/vidc/venc/src/video_encoder_device.cpp @@ -0,0 +1,2923 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include "video_encoder_device.h" +#include "omx_video_encoder.h" +#include +#ifdef USE_ION +#include +#endif + +#define MPEG4_SP_START 0 +#define MPEG4_ASP_START (MPEG4_SP_START + 8) +#define MPEG4_720P_LEVEL 6 +#define H263_BP_START 0 +#define H264_BP_START 0 +#define H264_HP_START (H264_BP_START + 13) +#define H264_MP_START (H264_BP_START + 26) + +/* MPEG4 profile and level table*/ +static const unsigned int mpeg4_profile_level_table[][5]= +{ + /*max mb per frame, max mb per sec, max bitrate, level, profile*/ + {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple}, + {99,1485,64000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple}, + {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple}, + {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple}, + {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple}, + {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, + {3600,108000,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, + {0,0,0,0,0}, + + {99,1485,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {0,0,0,0,0}, +}; + +/* H264 profile and level table*/ +static const unsigned int h264_profile_level_table[][5]= +{ + /*max mb per frame, max mb per sec, max bitrate, level, profile*/ + {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline}, + {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline}, + {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline}, + {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline}, + {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline}, + {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline}, + {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline}, + {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline}, + {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline}, + {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline}, + {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileBaseline}, + {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline}, + {0,0,0,0,0}, + + {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh}, + {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh}, + {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh}, + {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh}, + {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh}, + {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh}, + {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh}, + {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh}, + {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh}, + {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh}, + {5120,216000,25000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh}, + {8192,245760,25000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh}, + {0,0,0,0,0}, + + {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain}, + {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain}, + {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain}, + {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain}, + {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain}, + {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain}, + {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain}, + {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain}, + {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain}, + {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain}, + {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileMain}, + {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain}, + {0,0,0,0,0} + +}; + +/* H263 profile and level table*/ +static const unsigned int h263_profile_level_table[][5]= +{ + /*max mb per frame, max mb per sec, max bitrate, level, profile*/ + {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline}, + {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline}, + {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline}, + {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline}, + {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline}, + {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline}, + {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline}, + {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, + {0,0,0,0,0} +}; + +#define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } +#define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); } + +#ifdef INPUT_BUFFER_LOG +FILE *inputBufferFile1; +char inputfilename [] = "/data/input.yuv"; +#endif +#ifdef OUTPUT_BUFFER_LOG +FILE *outputBufferFile1; +char outputfilename [] = "/data/output-bitstream.\0\0\0\0"; +#endif +//constructor +venc_dev::venc_dev(class omx_venc *venc_class) +{ + m_max_allowed_bitrate_check = false; + m_eLevel = 0; + m_eProfile = 0; + pthread_mutex_init(&loaded_start_stop_mlock, NULL); + pthread_cond_init (&loaded_start_stop_cond, NULL); + DEBUG_PRINT_LOW("venc_dev constructor"); +} + +venc_dev::~venc_dev() +{ + pthread_cond_destroy(&loaded_start_stop_cond); + pthread_mutex_destroy(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("venc_dev distructor"); +} + +void* async_venc_message_thread (void *input) +{ + struct venc_ioctl_msg ioctl_msg ={NULL,NULL}; + struct venc_timeout timeout; + struct venc_msg venc_msg; + int error_code = 0; + omx_venc *omx = reinterpret_cast(input); + + prctl(PR_SET_NAME, (unsigned long)"VideoEncCallBackThread", 0, 0, 0); + timeout.millisec = VEN_TIMEOUT_INFINITE; + while(1) + { + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&venc_msg; + + /*Wait for a message from the video decoder driver*/ + error_code = ioctl(omx->handle->m_nDriver_fd,VEN_IOCTL_CMD_READ_NEXT_MSG,(void *)&ioctl_msg); + if (error_code == -512) // ERESTARTSYS + { + DEBUG_PRINT_ERROR("\n ERESTARTSYS received in ioctl read next msg!"); + } + else if (error_code <0) + { + DEBUG_PRINT_LOW("\nioctl VEN_IOCTL_CMD_READ_NEXT_MSG failed"); + break; + } + else if(omx->async_message_process(input,&venc_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Wrong ioctl message"); + break; + } + } + DEBUG_PRINT_HIGH("omx_venc: Async Thread exit\n"); + return NULL; +} + +bool venc_dev::venc_open(OMX_U32 codec) +{ + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + int r; + unsigned int alignment = 0,buffer_size = 0, temp =0; + + m_nDriver_fd = open ("/dev/msm_vidc_enc",O_RDWR|O_NONBLOCK); + if(m_nDriver_fd == 0) + { + DEBUG_PRINT_ERROR("ERROR: Got fd as 0 for msm_vidc_enc, Opening again\n"); + m_nDriver_fd = open ("/dev/msm_vidc_enc",O_RDWR|O_NONBLOCK); + } + + if((int)m_nDriver_fd < 0) + { + DEBUG_PRINT_ERROR("ERROR: Omx_venc::Comp Init Returning failure\n"); + return false; + } + + DEBUG_PRINT_LOW("\nm_nDriver_fd = %d\n", m_nDriver_fd); +#ifdef SINGLE_ENCODER_INSTANCE + OMX_U32 num_instances = 0; + ioctl_msg.in = NULL; + ioctl_msg.out = &num_instances; + if(ioctl (m_nDriver_fd, VEN_IOCTL_GET_NUMBER_INSTANCES, (void*)&ioctl_msg) < 0 ) + { + DEBUG_PRINT_ERROR("\nERROR: Request number of encoder instances failed"); + } + else if (num_instances > 1) + { + DEBUG_PRINT_ERROR("\nSecond encoder instance rejected!"); + venc_close(); + return false; + } +#endif + // set the basic configuration of the video encoder driver + m_sVenc_cfg.input_width = OMX_CORE_QCIF_WIDTH; + m_sVenc_cfg.input_height= OMX_CORE_QCIF_HEIGHT; + m_sVenc_cfg.dvs_width = OMX_CORE_QCIF_WIDTH; + m_sVenc_cfg.dvs_height = OMX_CORE_QCIF_HEIGHT; + m_sVenc_cfg.fps_num = 30; + m_sVenc_cfg.fps_den = 1; + m_sVenc_cfg.targetbitrate = 64000; +#ifdef MAX_RES_1080P + m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12_16M2KA; +#else + m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12; +#endif + if(codec == OMX_VIDEO_CodingMPEG4) + { + m_sVenc_cfg.codectype = VEN_CODEC_MPEG4; + codec_profile.profile = VEN_PROFILE_MPEG4_SP; + profile_level.level = VEN_LEVEL_MPEG4_2; +#ifdef OUTPUT_BUFFER_LOG + strcat(outputfilename, "m4v"); +#endif + } + else if(codec == OMX_VIDEO_CodingH263) + { + m_sVenc_cfg.codectype = VEN_CODEC_H263; + codec_profile.profile = VEN_PROFILE_H263_BASELINE; + profile_level.level = VEN_LEVEL_H263_20; +#ifdef OUTPUT_BUFFER_LOG + strcat(outputfilename, "263"); +#endif + } + if(codec == OMX_VIDEO_CodingAVC) + { + m_sVenc_cfg.codectype = VEN_CODEC_H264; + codec_profile.profile = VEN_PROFILE_H264_BASELINE; + profile_level.level = VEN_LEVEL_H264_1p1; +#ifdef OUTPUT_BUFFER_LOG + strcat(outputfilename, "264"); +#endif + } + ioctl_msg.in = (void*)&m_sVenc_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < 0 ) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting base configuration failed"); + return false; + } +#ifdef INPUT_BUFFER_LOG + inputBufferFile1 = fopen (inputfilename, "ab"); +#endif +#ifdef OUTPUT_BUFFER_LOG + outputBufferFile1 = fopen (outputfilename, "ab"); +#endif + // Get the I/P and O/P buffer requirements + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sInput_buff_property; + if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for getting i/p buffer requirement failed"); + return false; + } + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sOutput_buff_property; + if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for getting o/p buffer requirement failed"); + return false; + } + + m_profile_set = false; + m_level_set = false; + if(venc_set_profile_level(0, 0)) + { + DEBUG_PRINT_HIGH("\n %s(): Init Profile/Level setting success", + __func__); + } + recon_buffers_count = MAX_RECON_BUFFERS; + return true; +} + +void venc_dev::venc_close() +{ + DEBUG_PRINT_LOW("\nvenc_close: fd = %d", m_nDriver_fd); + if((int)m_nDriver_fd >= 0) + { + DEBUG_PRINT_HIGH("\n venc_close(): Calling VEN_IOCTL_CMD_STOP_READ_MSG"); + (void)ioctl(m_nDriver_fd, VEN_IOCTL_CMD_STOP_READ_MSG, + NULL); + DEBUG_PRINT_LOW("\nCalling close()\n"); + close(m_nDriver_fd); + m_nDriver_fd = -1; + } +#ifdef INPUT_BUFFER_LOG + fclose (inputBufferFile1); +#endif +#ifdef OUTPUT_BUFFER_LOG + fclose (outputBufferFile1); +#endif +} + +bool venc_dev::venc_set_buf_req(unsigned long *min_buff_count, + unsigned long *actual_buff_count, + unsigned long *buff_size, + unsigned long port) +{ + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + unsigned long temp_count = 0; + + if(port == 0) + { + if(*actual_buff_count > m_sInput_buff_property.mincount) + { + temp_count = m_sInput_buff_property.actualcount; + m_sInput_buff_property.actualcount = *actual_buff_count; + ioctl_msg.in = (void*)&m_sInput_buff_property; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting i/p buffer requirement failed"); + m_sInput_buff_property.actualcount = temp_count; + return false; + } + DEBUG_PRINT_LOW("\n I/P Count set to %lu\n", *actual_buff_count); + } + } + else + { + if(*actual_buff_count > m_sOutput_buff_property.mincount) + { + temp_count = m_sOutput_buff_property.actualcount; + m_sOutput_buff_property.actualcount = *actual_buff_count; + ioctl_msg.in = (void*)&m_sOutput_buff_property; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting o/p buffer requirement failed"); + m_sOutput_buff_property.actualcount = temp_count; + return false; + } + DEBUG_PRINT_LOW("\n O/P Count set to %lu\n", *actual_buff_count); + } + } + + return true; + +} + +bool venc_dev::venc_loaded_start() +{ + struct timespec ts; + int status = 0; + if(ioctl (m_nDriver_fd,VEN_IOCTL_CMD_START, NULL) < 0) + { + DEBUG_PRINT_ERROR("ERROR: VEN_IOCTL_CMD_START failed"); + return false; + } + if (clock_gettime(CLOCK_REALTIME, &ts) < 0) + { + DEBUG_PRINT_ERROR("%s: clock_gettime failed", __func__); + return false; + } + ts.tv_sec += 1; + pthread_mutex_lock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: wait on start done", __func__); + status = pthread_cond_timedwait(&loaded_start_stop_cond, + &loaded_start_stop_mlock, &ts); + if (status != 0) + { + DEBUG_PRINT_ERROR("%s: error status = %d, %s", __func__, + status, strerror(status)); + pthread_mutex_unlock(&loaded_start_stop_mlock); + return false; + } + DEBUG_PRINT_LOW("%s: wait over on start done", __func__); + pthread_mutex_unlock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: venc_loaded_start success", __func__); + return true; +} + +bool venc_dev::venc_loaded_stop() +{ + struct timespec ts; + int status = 0; + if(ioctl (m_nDriver_fd,VEN_IOCTL_CMD_STOP, NULL) < 0) + { + DEBUG_PRINT_ERROR("ERROR: VEN_IOCTL_CMD_STOP failed"); + return false; + } + if (clock_gettime(CLOCK_REALTIME, &ts) < 0) + { + DEBUG_PRINT_ERROR("%s: clock_gettime failed", __func__); + return false; + } + ts.tv_sec += 1; + pthread_mutex_lock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: wait on stop done", __func__); + status = pthread_cond_timedwait(&loaded_start_stop_cond, + &loaded_start_stop_mlock, &ts); + if (status != 0) + { + DEBUG_PRINT_ERROR("%s: error status = %d, %s", __func__, + status, strerror(status)); + pthread_mutex_unlock(&loaded_start_stop_mlock); + return false; + } + DEBUG_PRINT_LOW("%s: wait over on stop done", __func__); + pthread_mutex_unlock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: venc_loaded_stop success", __func__); + return true; +} + +bool venc_dev::venc_loaded_start_done() +{ + pthread_mutex_lock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: signal start done", __func__); + pthread_cond_signal(&loaded_start_stop_cond); + pthread_mutex_unlock(&loaded_start_stop_mlock); + return true; +} + +bool venc_dev::venc_loaded_stop_done() +{ + pthread_mutex_lock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: signal stop done", __func__); + pthread_cond_signal(&loaded_start_stop_cond); + pthread_mutex_unlock(&loaded_start_stop_mlock); + return true; +} + +bool venc_dev::venc_get_seq_hdr(void *buffer, + unsigned buffer_size, unsigned *header_len) +{ + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + int i = 0; + DEBUG_PRINT_HIGH("venc_dev::venc_get_seq_hdr"); + venc_seqheader seq_in, seq_out; + seq_in.hdrlen = 0; + seq_in.bufsize = buffer_size; + seq_in.hdrbufptr = (unsigned char*)buffer; + if (seq_in.hdrbufptr == NULL) { + DEBUG_PRINT_ERROR("ERROR: malloc for sequence header failed"); + return false; + } + DEBUG_PRINT_LOW("seq_in: buf=%x, sz=%d, hdrlen=%d", seq_in.hdrbufptr, + seq_in.bufsize, seq_in.hdrlen); + + ioctl_msg.in = (void*)&seq_in; + ioctl_msg.out = (void*)&seq_out; + if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_SEQUENCE_HDR,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("ERROR: Request for getting sequence header failed"); + return false; + } + if (seq_out.hdrlen == 0) { + DEBUG_PRINT_ERROR("ERROR: Seq header returned zero length header"); + DEBUG_PRINT_ERROR("seq_out: buf=%x, sz=%d, hdrlen=%d", seq_out.hdrbufptr, + seq_out.bufsize, seq_out.hdrlen); + return false; + } + *header_len = seq_out.hdrlen; + DEBUG_PRINT_LOW("seq_out: buf=%x, sz=%d, hdrlen=%d", seq_out.hdrbufptr, + seq_out.bufsize, seq_out.hdrlen); + + return true; +} + +bool venc_dev::venc_get_buf_req(unsigned long *min_buff_count, + unsigned long *actual_buff_count, + unsigned long *buff_size, + unsigned long port) +{ + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + + if(port == 0) + { + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sInput_buff_property; + if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for getting i/p buffer requirement failed"); + return false; + } + *min_buff_count = m_sInput_buff_property.mincount; + *actual_buff_count = m_sInput_buff_property.actualcount; +#ifdef USE_ION + // For ION memory allocations of the allocated buffer size + // must be 4k aligned, hence aligning the input buffer + // size to 4k. + m_sInput_buff_property.datasize = (m_sInput_buff_property.datasize + 4095) + & (~4095); +#endif + *buff_size = m_sInput_buff_property.datasize; + } + else + { + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sOutput_buff_property; + if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for getting o/p buffer requirement failed"); + return false; + } + *min_buff_count = m_sOutput_buff_property.mincount; + *actual_buff_count = m_sOutput_buff_property.actualcount; + *buff_size = m_sOutput_buff_property.datasize; + } + + return true; + +} + +bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + DEBUG_PRINT_LOW("venc_set_param:: venc-720p\n"); + switch(index) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition\n"); + if(portDefn->nPortIndex == PORT_INDEX_IN) + { + + if(!venc_set_encode_framerate(portDefn->format.video.xFramerate, 0)) + { + return false; + } + + if(!venc_set_color_format(portDefn->format.video.eColorFormat)) + { + return false; + } + + DEBUG_PRINT_LOW("\n Basic parameter has changed"); + m_sVenc_cfg.input_height = portDefn->format.video.nFrameHeight; + m_sVenc_cfg.input_width = portDefn->format.video.nFrameWidth; + + ioctl_msg.in = (void*)&m_sVenc_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < 0) { + DEBUG_PRINT_ERROR("\nERROR: Request for setting base config failed"); + return false; + } + + DEBUG_PRINT_LOW("\n Updating the buffer count/size for the new resolution"); + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sInput_buff_property; + if(ioctl (m_nDriver_fd, VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { + DEBUG_PRINT_ERROR("\nERROR: Request for getting i/p bufreq failed"); + return false; + } + DEBUG_PRINT_LOW("\n Got updated m_sInput_buff_property values: " + "datasize = %u, maxcount = %u, actualcnt = %u, " + "mincount = %u", m_sInput_buff_property.datasize, + m_sInput_buff_property.maxcount, m_sInput_buff_property.actualcount, + m_sInput_buff_property.mincount); + + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sOutput_buff_property; + if(ioctl (m_nDriver_fd, VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { + DEBUG_PRINT_ERROR("\nERROR: Request for getting o/p bufreq failed"); + return false; + } + + DEBUG_PRINT_LOW("\n Got updated m_sOutput_buff_property values: " + "datasize = %u, maxcount = %u, actualcnt = %u, " + "mincount = %u", m_sOutput_buff_property.datasize, + m_sOutput_buff_property.maxcount, m_sOutput_buff_property.actualcount, + m_sOutput_buff_property.mincount); + ioctl_msg.in = (void*)&m_sOutput_buff_property; + ioctl_msg.out = NULL; + + if(ioctl (m_nDriver_fd, VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { + DEBUG_PRINT_ERROR("\nERROR: Request for setting o/p bufreq failed"); + return false; + } + + if((portDefn->nBufferCountActual >= m_sInput_buff_property.mincount) && + (portDefn->nBufferCountActual <= m_sInput_buff_property.maxcount)) { + m_sInput_buff_property.actualcount = portDefn->nBufferCountActual; + ioctl_msg.in = (void*)&m_sInput_buff_property; + ioctl_msg.out = NULL; + if(ioctl(m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { + DEBUG_PRINT_ERROR("\nERROR: Request for setting i/p buffer requirements failed"); + return false; + } + } + if(m_sInput_buff_property.datasize != portDefn->nBufferSize) { + DEBUG_PRINT_ERROR("\nWARNING: Requested i/p bufsize[%u]," + "Driver's updated i/p bufsize = %u", portDefn->nBufferSize, + m_sInput_buff_property.datasize); + } + m_level_set = false; + if(venc_set_profile_level(0, 0)) { + DEBUG_PRINT_HIGH("\n %s(): Profile/Level setting success", __func__); + } + } + else if(portDefn->nPortIndex == PORT_INDEX_OUT) + { + if(!venc_set_target_bitrate(portDefn->format.video.nBitrate, 0)) + { + return false; + } + + if( (portDefn->nBufferCountActual >= m_sOutput_buff_property.mincount) + && + (m_sOutput_buff_property.maxcount >= portDefn->nBufferCountActual) + && + (m_sOutput_buff_property.datasize == portDefn->nBufferSize) + ) + { + m_sOutput_buff_property.actualcount = portDefn->nBufferCountActual; + ioctl_msg.in = (void*)&m_sOutput_buff_property; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: ioctl VEN_IOCTL_SET_OUTPUT_BUFFER_REQ failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Setting Output buffer requirements failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamPortDefinition"); + } + break; + } + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt; + portFmt =(OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; + DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoPortFormat\n"); + + if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) + { + if(!venc_set_color_format(portFmt->eColorFormat)) + { + return false; + } + } + else if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(!venc_set_encode_framerate(portFmt->xFramerate, 0)) + { + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoPortFormat"); + } + break; + } + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE* pParam; + pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData; + DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoBitrate\n"); + + if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(!venc_set_target_bitrate(pParam->nTargetBitrate, 0)) + { + DEBUG_PRINT_ERROR("\nERROR: Target Bit Rate setting failed"); + return false; + } + if(!venc_set_ratectrl_cfg(pParam->eControlRate)) + { + DEBUG_PRINT_ERROR("\nERROR: Rate Control setting failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoBitrate"); + } + break; + } + case OMX_IndexParamVideoMpeg4: + { + OMX_VIDEO_PARAM_MPEG4TYPE* pParam; + OMX_U32 bFrames = 0; + + pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData; + DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoMpeg4\n"); + if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(!venc_set_voptiming_cfg(pParam->nTimeIncRes)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting vop_timing failed"); + return false; + } + m_profile_set = false; + m_level_set = false; + if(!venc_set_profile_level (pParam->eProfile, pParam->eLevel)) + { + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating Profile and level"); + return false; + } +#ifdef MAX_RES_1080P + else { + if(pParam->eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) + { + if(pParam->nBFrames) + { + DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported"); + bFrames = 1; + } + } + else + { + if(pParam->nBFrames) + { + DEBUG_PRINT_ERROR("Warning: B frames not supported\n"); + bFrames = 0; + } + } + } +#endif + if(!venc_set_intra_period (pParam->nPFrames,bFrames)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + if(!venc_set_multislice_cfg(OMX_IndexParamVideoMpeg4,pParam->nSliceHeaderSpacing)) + { + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating slice_config"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoMpeg4"); + } + break; + } + case OMX_IndexParamVideoH263: + { + OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData; + DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoH263\n"); + OMX_U32 bFrames = 0; + if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + m_profile_set = false; + m_level_set = false; + if(!venc_set_profile_level (pParam->eProfile, pParam->eLevel)) + { + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating Profile and level"); + return false; + } + if (pParam->nBFrames) + DEBUG_PRINT_ERROR("\nWARNING: B frame not supported for H.263"); + + if(venc_set_intra_period (pParam->nPFrames, bFrames) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoH263"); + } + break; + } + case OMX_IndexParamVideoAvc: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoAvc\n"); + OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData; + OMX_U32 bFrames = 0; + + if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + DEBUG_PRINT_LOW("pParam->eProfile :%d ,pParam->eLevel %d\n", + pParam->eProfile,pParam->eLevel); + + m_profile_set = false; + m_level_set = false; + + if(!venc_set_profile_level (pParam->eProfile,pParam->eLevel)) + { + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating Profile and level %d, %d", + pParam->eProfile, pParam->eLevel); + return false; + } +#ifdef MAX_RES_1080P + else { + if(pParam->eProfile != OMX_VIDEO_AVCProfileBaseline) + { + if(pParam->nBFrames) + { + DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported"); + bFrames = 1; + } + } + else + { + if(pParam->nBFrames) + { + DEBUG_PRINT_ERROR("Warning: B frames not supported\n"); + bFrames = 0; + } + } + } +#endif + if(!venc_set_intra_period (pParam->nPFrames, bFrames)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + if(!venc_set_entropy_config (pParam->bEntropyCodingCABAC, pParam->nCabacInitIdc)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Entropy failed"); + return false; + } + if(!venc_set_inloop_filter (pParam->eLoopFilterMode)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Inloop filter failed"); + return false; + } + if(!venc_set_multislice_cfg(OMX_IndexParamVideoAvc, pParam->nSliceHeaderSpacing)) + { + DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating slice_config"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoAvc"); + } + //TBD, lot of other variables to be updated, yet to decide + break; + } + case OMX_IndexParamVideoIntraRefresh: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoIntraRefresh\n"); + OMX_VIDEO_PARAM_INTRAREFRESHTYPE *intra_refresh = + (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)paramData; + if(intra_refresh->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(venc_set_intra_refresh(intra_refresh->eRefreshMode, intra_refresh->nCirMBs) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Intra refresh failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoIntraRefresh"); + } + break; + } + case OMX_IndexParamVideoErrorCorrection: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoErrorCorrection\n"); + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *error_resilience = + (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)paramData; + if(error_resilience->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(venc_set_error_resilience(error_resilience) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Intra refresh failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoErrorCorrection"); + } + break; + } + case OMX_IndexParamVideoProfileLevelCurrent: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoProfileLevelCurrent\n"); + OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = + (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData; + if(profile_level->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + m_profile_set = false; + m_level_set = false; + if(!venc_set_profile_level (profile_level->eProfile, + profile_level->eLevel)) + { + DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating Profile and level"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoProfileLevelCurrent"); + } + break; + } + case OMX_IndexParamVideoQuantization: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoQuantization\n"); + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = + (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)paramData; + if(session_qp->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(venc_set_session_qp (session_qp->nQpI, + session_qp->nQpP) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Session QP failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoQuantization"); + } + break; + } + case OMX_ExtraDataVideoEncoderSliceInfo: + { + DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoEncoderSliceInfo"); + OMX_U32 extra_data = *(OMX_U32 *)paramData; + if(venc_set_extradata(extra_data) == false) + { + DEBUG_PRINT_ERROR("ERROR: Setting " + "OMX_QcomIndexParamIndexExtraDataType failed"); + return false; + } + break; + } + case OMX_QcomIndexEnableSliceDeliveryMode: + { + QOMX_EXTNINDEX_PARAMTYPE* pParam = + (QOMX_EXTNINDEX_PARAMTYPE*)paramData; + if(pParam->nPortIndex == PORT_INDEX_OUT) + { + if(venc_set_slice_delivery_mode(pParam->bEnable) == false) + { + DEBUG_PRINT_ERROR("Setting slice delivery mode failed"); + return OMX_ErrorUnsupportedSetting; + } + } + else + { + DEBUG_PRINT_ERROR("OMX_QcomIndexEnableSliceDeliveryMode " + "called on wrong port(%d)", pParam->nPortIndex); + return OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamVideoSliceFMO: + default: + DEBUG_PRINT_ERROR("\nERROR: Unsupported parameter in venc_set_param: %u", + index); + break; + //case + } + + return true; +} + +bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + DEBUG_PRINT_LOW("\n Inside venc_set_config"); + + switch(index) + { + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *bit_rate = (OMX_VIDEO_CONFIG_BITRATETYPE *) + configData; + if(m_max_allowed_bitrate_check && + !venc_max_allowed_bitrate_check(bit_rate->nEncodeBitrate)) + { + DEBUG_PRINT_ERROR("Max Allowed Bitrate Check failed"); + return false; + } + DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigVideoBitrate"); + if(bit_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) + { + if(venc_set_target_bitrate(bit_rate->nEncodeBitrate, 1) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Target Bit rate failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexConfigVideoBitrate"); + } + break; + } + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *frame_rate = (OMX_CONFIG_FRAMERATETYPE *) + configData; + DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigVideoFramerate"); + if(frame_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) + { + if(venc_set_encode_framerate(frame_rate->xEncodeFramerate, 1) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Encode Framerate failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate"); + } + break; + } + case QOMX_IndexConfigVideoIntraperiod: + { + DEBUG_PRINT_LOW("venc_set_param:QOMX_IndexConfigVideoIntraperiod\n"); + QOMX_VIDEO_INTRAPERIODTYPE *intraperiod = + (QOMX_VIDEO_INTRAPERIODTYPE *)configData; + if(intraperiod->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(venc_set_intra_period(intraperiod->nPFrames, intraperiod->nBFrames) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + } + break; + } + case OMX_IndexConfigVideoIntraVOPRefresh: + { + OMX_CONFIG_INTRAREFRESHVOPTYPE *intra_vop_refresh = (OMX_CONFIG_INTRAREFRESHVOPTYPE *) + configData; + DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigVideoIntraVOPRefresh"); + if(intra_vop_refresh->nPortIndex == (OMX_U32)PORT_INDEX_OUT) + { + if(venc_set_intra_vop_refresh(intra_vop_refresh->IntraRefreshVOP) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Encode Framerate failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate"); + } + break; + } + case OMX_IndexConfigCommonRotate: + { + OMX_CONFIG_ROTATIONTYPE *config_rotation = + reinterpret_cast(configData); + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + OMX_U32 nFrameWidth; + + DEBUG_PRINT_HIGH("\nvenc_set_config: updating the new Dims"); + nFrameWidth = m_sVenc_cfg.input_width; + m_sVenc_cfg.input_width = m_sVenc_cfg.input_height; + m_sVenc_cfg.input_height = nFrameWidth; + ioctl_msg.in = (void*)&m_sVenc_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < 0) { + DEBUG_PRINT_ERROR("\nERROR: Dimension Change for Rotation failed"); + return false; + } + break; + } + default: + DEBUG_PRINT_ERROR("\n Unsupported config index = %u", index); + break; + } + + return true; +} + +unsigned venc_dev::venc_stop( void) +{ +#ifdef MAX_RES_1080P + pmem_free(); +#endif + return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_STOP,NULL); +} + +unsigned venc_dev::venc_pause(void) +{ + return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_PAUSE,NULL); +} + +unsigned venc_dev::venc_resume(void) +{ + return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_RESUME,NULL) ; +} + +unsigned venc_dev::venc_start_done(void) +{ + return 0; +} + +unsigned venc_dev::venc_stop_done(void) +{ + return 0; +} + +unsigned venc_dev::venc_start(void) +{ + DEBUG_PRINT_HIGH("\n %s(): Check Profile/Level set in driver before start", + __func__); + if (!venc_set_profile_level(0, 0)) + { + DEBUG_PRINT_ERROR("\n ERROR: %s(): Driver Profile/Level is NOT SET", + __func__); + } + else + { + DEBUG_PRINT_HIGH("\n %s(): Driver Profile[%lu]/Level[%lu] successfully SET", + __func__, codec_profile.profile, profile_level.level); + } + + if(m_max_allowed_bitrate_check && + !venc_max_allowed_bitrate_check(bitrate.target_bitrate)) + { + DEBUG_PRINT_ERROR("Maximum Allowed Bitrate Check failed"); + return -1; + } + + venc_config_print(); + +#ifdef MAX_RES_1080P + if((codec_profile.profile == VEN_PROFILE_MPEG4_SP) || + (codec_profile.profile == VEN_PROFILE_H264_BASELINE) || + (codec_profile.profile == VEN_PROFILE_H263_BASELINE)) + recon_buffers_count = MAX_RECON_BUFFERS - 2; + else + recon_buffers_count = MAX_RECON_BUFFERS; + + if (!venc_allocate_recon_buffers()) + return ioctl(m_nDriver_fd, VEN_IOCTL_CMD_START, NULL); + else + { + DEBUG_PRINT_ERROR("Failed in creating Recon buffers\n"); + return -1; + } +#else + return ioctl(m_nDriver_fd, VEN_IOCTL_CMD_START, NULL); +#endif +} + +#ifdef MAX_RES_1080P +OMX_U32 venc_dev::venc_allocate_recon_buffers() +{ + OMX_U32 yuv_size; + struct venc_ioctl_msg ioctl_msg; + struct venc_recon_buff_size recon_buff_size; + + recon_buff_size.width = ((m_sVenc_cfg.input_width + 15) / 16) * 16; + recon_buff_size.height = ((m_sVenc_cfg.input_height + 15) / 16 ) * 16; + + DEBUG_PRINT_LOW("Width %d, Height %d, w_round %d, h_round %d\n", m_sVenc_cfg.input_width, + m_sVenc_cfg.input_height, recon_buff_size.width, recon_buff_size.height); + + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&recon_buff_size; + + if (ioctl (m_nDriver_fd,VEN_IOCTL_GET_RECON_BUFFER_SIZE, (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n VEN_IOCTL_GET_RECON_BUFFER_SIZE Failed for width: %d, Height %d" , + recon_buff_size.width, recon_buff_size.height); + return OMX_ErrorInsufficientResources; + } + + DEBUG_PRINT_HIGH("Width %d, Height %d, w_round %d, h_round %d, yuv_size %d alignment %d count %d\n", + m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, recon_buff_size.width, + recon_buff_size.height, recon_buff_size.size, recon_buff_size.alignment, + recon_buffers_count); + + for(int i = 0; i < recon_buffers_count; i++) + { + if(pmem_allocate(recon_buff_size.size, recon_buff_size.alignment,i)) + { + DEBUG_PRINT_ERROR("Error returned in allocating recon buffers\n"); + return -1; + } + } + return 0; +} +OMX_U32 venc_dev::pmem_allocate(OMX_U32 size, OMX_U32 alignment, OMX_U32 count) +{ + OMX_U32 pmem_fd = -1; + OMX_U32 width, height; + void *buf_addr = NULL; + struct venc_ioctl_msg ioctl_msg; + struct venc_recon_addr recon_addr; + int rc = 0; + +#ifdef USE_ION + recon_buff[count].ion_device_fd = open (MEM_DEVICE,O_RDONLY); + if(recon_buff[count].ion_device_fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: ION Device open() Failed"); + return -1; + } + + recon_buff[count].alloc_data.len = size; +#ifdef MAX_RES_720P + recon_buff[count].alloc_data.flags = ION_HEAP(MEM_HEAP_ID); +#else + recon_buff[count].alloc_data.flags = (ION_HEAP(MEM_HEAP_ID) | + ION_HEAP(ION_IOMMU_HEAP_ID)); +#endif + recon_buff[count].alloc_data.align = clip2(alignment); + if (recon_buff[count].alloc_data.align != 8192) + recon_buff[count].alloc_data.align = 8192; + + rc = ioctl(recon_buff[count].ion_device_fd,ION_IOC_ALLOC,&recon_buff[count].alloc_data); + if(rc || !recon_buff[count].alloc_data.handle) { + DEBUG_PRINT_ERROR("\n ION ALLOC memory failed "); + recon_buff[count].alloc_data.handle=NULL; + return -1; + } + + recon_buff[count].ion_alloc_fd.handle = recon_buff[count].alloc_data.handle; + rc = ioctl(recon_buff[count].ion_device_fd,ION_IOC_MAP,&recon_buff[count].ion_alloc_fd); + if(rc) { + DEBUG_PRINT_ERROR("\n ION MAP failed "); + recon_buff[count].ion_alloc_fd.fd =-1; + recon_buff[count].ion_alloc_fd.fd =-1; + return -1; + } + pmem_fd = recon_buff[count].ion_alloc_fd.fd; +#else + struct pmem_allocation allocation; + pmem_fd = open(MEM_DEVICE, O_RDWR); + + if ((int)(pmem_fd) < 0) + { + DEBUG_PRINT_ERROR("\n Failed to get an pmem handle"); + return -1; + } + + allocation.size = size; + allocation.align = clip2(alignment); + + if (allocation.align != 8192) + allocation.align = 8192; + + if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) + { + DEBUG_PRINT_ERROR("\n Aligment(%u) failed with pmem driver Sz(%lu)", + allocation.align, allocation.size); + return -1; + } +#endif + buf_addr = mmap(NULL, size, + PROT_READ | PROT_WRITE, + MAP_SHARED, pmem_fd, 0); + + if (buf_addr == (void*) MAP_FAILED) + { + close(pmem_fd); + pmem_fd = -1; + DEBUG_PRINT_ERROR("Error returned in allocating recon buffers buf_addr: %p\n",buf_addr); +#ifdef USE_ION + if(ioctl(recon_buff[count].ion_device_fd,ION_IOC_FREE, + &recon_buff[count].alloc_data.handle)) { + DEBUG_PRINT_LOW("ion recon buffer free failed"); + } + recon_buff[count].alloc_data.handle = NULL; + recon_buff[count].ion_alloc_fd.fd =-1; + close(recon_buff[count].ion_device_fd); + recon_buff[count].ion_device_fd =-1; +#endif + return -1; + } + + DEBUG_PRINT_HIGH("\n Allocated virt:%p, FD: %d of size %d \n", buf_addr, pmem_fd, size); + + recon_addr.buffer_size = size; + recon_addr.pmem_fd = pmem_fd; + recon_addr.offset = 0; + recon_addr.pbuffer = (unsigned char *)buf_addr; + + ioctl_msg.in = (void*)&recon_addr; + ioctl_msg.out = NULL; + + if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_RECON_BUFFER, (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("Failed to set the Recon_buffers\n"); + return -1; + } + + recon_buff[count].virtual_address = (unsigned char *) buf_addr; + recon_buff[count].size = size; + recon_buff[count].offset = 0; + recon_buff[count].pmem_fd = pmem_fd; + + DEBUG_PRINT_ERROR("\n Allocated virt:%p, FD: %d of size %d at index: %d\n", recon_buff[count].virtual_address, + recon_buff[count].pmem_fd, recon_buff[count].size, count); + return 0; +} + +OMX_U32 venc_dev::pmem_free() +{ + int cnt = 0; + struct venc_ioctl_msg ioctl_msg; + struct venc_recon_addr recon_addr; + for (cnt = 0; cnt < recon_buffers_count; cnt++) + { + if(recon_buff[cnt].pmem_fd) + { + recon_addr.pbuffer = recon_buff[cnt].virtual_address; + recon_addr.offset = recon_buff[cnt].offset; + recon_addr.pmem_fd = recon_buff[cnt].pmem_fd; + recon_addr.buffer_size = recon_buff[cnt].size; + ioctl_msg.in = (void*)&recon_addr; + ioctl_msg.out = NULL; + if(ioctl(m_nDriver_fd, VEN_IOCTL_FREE_RECON_BUFFER ,&ioctl_msg) < 0) + DEBUG_PRINT_ERROR("VEN_IOCTL_FREE_RECON_BUFFER failed"); + munmap(recon_buff[cnt].virtual_address, recon_buff[cnt].size); + close(recon_buff[cnt].pmem_fd); +#ifdef USE_ION + if(ioctl(recon_buff[cnt].ion_device_fd,ION_IOC_FREE, + &recon_buff[cnt].alloc_data.handle)) { + DEBUG_PRINT_LOW("ion recon buffer free failed"); + } + recon_buff[cnt].alloc_data.handle = NULL; + recon_buff[cnt].ion_alloc_fd.fd =-1; + close(recon_buff[cnt].ion_device_fd); + recon_buff[cnt].ion_device_fd =-1; +#endif + DEBUG_PRINT_LOW("\n cleaning Index %d of size %d \n",cnt,recon_buff[cnt].size); + recon_buff[cnt].pmem_fd = -1; + recon_buff[cnt].virtual_address = NULL; + recon_buff[cnt].offset = 0; + recon_buff[cnt].alignment = 0; + recon_buff[cnt].size = 0; + } + } + return 0; +} +#endif + +void venc_dev::venc_config_print() +{ + + DEBUG_PRINT_HIGH("\nENC_CONFIG: Codec: %d, Profile %d, level : %d", + m_sVenc_cfg.codectype, codec_profile.profile, profile_level.level); + + DEBUG_PRINT_HIGH("\n ENC_CONFIG: Width: %d, Height:%d, Fps: %d", + m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, + m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: Bitrate: %d, RC: %d, I-Period: %d", + bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: qpI: %d, qpP: %d, qpb: 0", + session_qp.iframeqp, session_qp.pframqp); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: VOP_Resolution: %d, Slice-Mode: %d, Slize_Size: %d", + voptimecfg.voptime_resolution, multislice.mslice_mode, + multislice.mslice_size); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: EntropyMode: %d, CabacModel: %d", + entropy.longentropysel, entropy.cabacmodel); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: DB-Mode: %d, alpha: %d, Beta: %d\n", + dbkfilter.db_mode, dbkfilter.slicealpha_offset, + dbkfilter.slicebeta_offset); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: IntraMB/Frame: %d, HEC: %d\n", + intra_refresh.mbcount, hec.header_extension); +} + +unsigned venc_dev::venc_flush( unsigned port) +{ + struct venc_ioctl_msg ioctl_msg; + struct venc_bufferflush buffer_index; + + if(port == PORT_INDEX_IN) + { + DEBUG_PRINT_HIGH("Calling Input Flush"); + buffer_index.flush_mode = VEN_FLUSH_INPUT; + ioctl_msg.in = (void*)&buffer_index; + ioctl_msg.out = NULL; + + return ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FLUSH,(void*)&ioctl_msg); + } + else if(port == PORT_INDEX_OUT) + { + DEBUG_PRINT_HIGH("Calling Output Flush"); + buffer_index.flush_mode = VEN_FLUSH_OUTPUT; + ioctl_msg.in = (void*)&buffer_index; + ioctl_msg.out = NULL; + return ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FLUSH,(void*)&ioctl_msg); + } + else + { + return -1; + } +} + +//allocating I/P memory from pmem and register with the device + + +bool venc_dev::venc_use_buf(void *buf_addr, unsigned port,unsigned) +{ + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct pmem *pmem_tmp; + struct venc_bufferpayload dev_buffer = {0}; + + pmem_tmp = (struct pmem *)buf_addr; + + DEBUG_PRINT_LOW("\n venc_use_buf:: pmem_tmp = %p", pmem_tmp); + + if(port == PORT_INDEX_IN) + { + dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; + dev_buffer.fd = pmem_tmp->fd; + dev_buffer.maped_size = pmem_tmp->size; + dev_buffer.sz = pmem_tmp->size; + dev_buffer.offset = pmem_tmp->offset; + ioctl_msg.in = (void*)&dev_buffer; + ioctl_msg.out = NULL; + + if((m_sVenc_cfg.input_height %16 !=0) || (m_sVenc_cfg.input_width%16 != 0)) + { + unsigned long ht = m_sVenc_cfg.input_height; + unsigned long wd = m_sVenc_cfg.input_width; + unsigned int luma_size, luma_size_2k; + + ht = (ht + 15) & ~15; + wd = (wd + 15) & ~15; + + luma_size = ht * wd; + luma_size_2k = (luma_size + 2047) & ~2047; + + dev_buffer.sz = luma_size_2k + luma_size/2; + dev_buffer.maped_size = dev_buffer.sz; + } + + DEBUG_PRINT_LOW("\n venc_use_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ + dev_buffer.pbuffer, \ + dev_buffer.fd, \ + dev_buffer.offset, \ + dev_buffer.maped_size); + + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER,&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: venc_use_buf:set input buffer failed "); + return false; + } + } + else if(port == PORT_INDEX_OUT) + { + dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; + dev_buffer.fd = pmem_tmp->fd; + dev_buffer.sz = pmem_tmp->size; + dev_buffer.maped_size = pmem_tmp->size; + dev_buffer.offset = pmem_tmp->offset; + ioctl_msg.in = (void*)&dev_buffer; + ioctl_msg.out = NULL; + + DEBUG_PRINT_LOW("\n venc_use_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ + dev_buffer.pbuffer, \ + dev_buffer.fd, \ + dev_buffer.offset, \ + dev_buffer.maped_size); + + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER,&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: venc_use_buf:set output buffer failed "); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: venc_use_buf:Invalid Port Index "); + return false; + } + + return true; +} + +bool venc_dev::venc_free_buf(void *buf_addr, unsigned port) +{ + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct pmem *pmem_tmp; + struct venc_bufferpayload dev_buffer = {0}; + + pmem_tmp = (struct pmem *)buf_addr; + + DEBUG_PRINT_LOW("\n venc_use_buf:: pmem_tmp = %p", pmem_tmp); + + if(port == PORT_INDEX_IN) + { + dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; + dev_buffer.fd = pmem_tmp->fd; + dev_buffer.maped_size = pmem_tmp->size; + dev_buffer.sz = pmem_tmp->size; + dev_buffer.offset = pmem_tmp->offset; + ioctl_msg.in = (void*)&dev_buffer; + ioctl_msg.out = NULL; + + DEBUG_PRINT_LOW("\n venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ + dev_buffer.pbuffer, \ + dev_buffer.fd, \ + dev_buffer.offset, \ + dev_buffer.maped_size); + + if(ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FREE_INPUT_BUFFER,&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: venc_free_buf: free input buffer failed "); + return false; + } + } + else if(port == PORT_INDEX_OUT) + { + dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; + dev_buffer.fd = pmem_tmp->fd; + dev_buffer.sz = pmem_tmp->size; + dev_buffer.maped_size = pmem_tmp->size; + dev_buffer.offset = pmem_tmp->offset; + ioctl_msg.in = (void*)&dev_buffer; + ioctl_msg.out = NULL; + + DEBUG_PRINT_LOW("\n venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ + dev_buffer.pbuffer, \ + dev_buffer.fd, \ + dev_buffer.offset, \ + dev_buffer.maped_size); + + if(ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FREE_OUTPUT_BUFFER,&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: venc_free_buf: free output buffer failed "); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: venc_free_buf:Invalid Port Index "); + return false; + } + + return true; +} + +bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf,unsigned,unsigned) +{ + struct venc_buffer frameinfo; + struct pmem *temp_buffer; + struct venc_ioctl_msg ioctl_msg; + struct OMX_BUFFERHEADERTYPE *bufhdr; + + if(buffer == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: venc_etb: buffer is NULL"); + return false; + } + bufhdr = (OMX_BUFFERHEADERTYPE *)buffer; + + DEBUG_PRINT_LOW("\n Input buffer length %d",bufhdr->nFilledLen); + + if(pmem_data_buf) + { + DEBUG_PRINT_LOW("\n Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf); + frameinfo.ptrbuffer = (OMX_U8 *)pmem_data_buf; + } + else + { + DEBUG_PRINT_LOW("\n Shared PMEM addr for i/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer); + frameinfo.ptrbuffer = (OMX_U8 *)bufhdr->pBuffer; + } + + frameinfo.clientdata = (void *) buffer; + frameinfo.sz = bufhdr->nFilledLen; + frameinfo.len = bufhdr->nFilledLen; + frameinfo.flags = bufhdr->nFlags; + frameinfo.offset = bufhdr->nOffset; + frameinfo.timestamp = bufhdr->nTimeStamp; + DEBUG_PRINT_LOW("\n i/p TS = %u", (OMX_U32)frameinfo.timestamp); + ioctl_msg.in = &frameinfo; + ioctl_msg.out = NULL; + + DEBUG_PRINT_LOW("DBG: i/p frameinfo: bufhdr->pBuffer = %p, ptrbuffer = %p, offset = %u, len = %u", + bufhdr->pBuffer, frameinfo.ptrbuffer, frameinfo.offset, frameinfo.len); + if(ioctl(m_nDriver_fd,VEN_IOCTL_CMD_ENCODE_FRAME,&ioctl_msg) < 0) + { + /*Generate an async error and move to invalid state*/ + return false; + } +#ifdef INPUT_BUFFER_LOG +#ifdef MAX_RES_1080P + + int y_size = 0; + int c_offset = 0; + unsigned char *buf_addr = NULL; + + y_size = m_sVenc_cfg.input_width * m_sVenc_cfg.input_height; + //chroma offset is y_size aligned to the 2k boundary + c_offset= (y_size + 2047) & (~(2047)); + + if(pmem_data_buf) + { + DEBUG_PRINT_LOW("\n Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf); + buf_addr = (OMX_U8 *)pmem_data_buf; + } + else + { + DEBUG_PRINT_LOW("\n Shared PMEM addr for i/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer); + buf_addr = (unsigned char *)mmap(NULL, + ((encoder_media_buffer_type *)bufhdr->pBuffer)->meta_handle->data[2], + PROT_READ|PROT_WRITE, MAP_SHARED, + ((encoder_media_buffer_type *)bufhdr->pBuffer)->meta_handle->data[0], 0); + } + + if(inputBufferFile1) + { + fwrite((const char *)buf_addr, y_size, 1,inputBufferFile1); + fwrite((const char *)(buf_addr + c_offset), (y_size>>1), 1,inputBufferFile1); + } + + munmap (buf_addr, ((encoder_media_buffer_type *)bufhdr->pBuffer)->meta_handle->data[2]); +#else + if(inputBufferFile1) + { + fwrite((const char *)frameinfo.ptrbuffer, frameinfo.len, 1,inputBufferFile1); + } +#endif + +#endif + return true; +} +bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf,unsigned,unsigned) +{ + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct pmem *temp_buffer = NULL; + struct venc_buffer frameinfo; + struct OMX_BUFFERHEADERTYPE *bufhdr; + + if(buffer == NULL) + { + return false; + } + bufhdr = (OMX_BUFFERHEADERTYPE *)buffer; + + if(pmem_data_buf) + { + DEBUG_PRINT_LOW("\n Internal PMEM addr for o/p Heap UseBuf: %p", pmem_data_buf); + frameinfo.ptrbuffer = (OMX_U8 *)pmem_data_buf; + } + else + { + DEBUG_PRINT_LOW("\n Shared PMEM addr for o/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer); + frameinfo.ptrbuffer = (OMX_U8 *)bufhdr->pBuffer; + } + + frameinfo.clientdata = buffer; + frameinfo.sz = bufhdr->nAllocLen; + frameinfo.flags = bufhdr->nFlags; + frameinfo.offset = bufhdr->nOffset; + + ioctl_msg.in = &frameinfo; + ioctl_msg.out = NULL; + DEBUG_PRINT_LOW("DBG: o/p frameinfo: bufhdr->pBuffer = %p, ptrbuffer = %p, offset = %u, len = %u", + bufhdr->pBuffer, frameinfo.ptrbuffer, frameinfo.offset, frameinfo.len); + if(ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: ioctl VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER failed"); + return false; + } + + return true; +} + +bool venc_dev::venc_set_slice_delivery_mode(OMX_BOOL enable) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + DEBUG_PRINT_HIGH("Set slice_delivery_mode: %d", enable); + if(multislice.mslice_mode == VEN_MSLICE_CNT_MB) + { + if(ioctl(m_nDriver_fd, VEN_IOCTL_SET_SLICE_DELIVERY_MODE) < 0) + { + DEBUG_PRINT_ERROR("Request for setting slice delivery mode failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("WARNING: slice_mode[%d] is not VEN_MSLICE_CNT_MB to set " + "slice delivery mode to the driver.", multislice.mslice_mode); + } + return true; +} + +bool venc_dev::venc_set_extradata(OMX_U32 extra_data) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + DEBUG_PRINT_HIGH("venc_set_extradata:: %x", extra_data); + ioctl_msg.in = (void*)&extra_data; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd, VEN_IOCTL_SET_EXTRADATA, (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("ERROR: Request for setting extradata failed"); + return false; + } + + return true; +} + +bool venc_dev::venc_set_session_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_sessionqp qp = {0, 0}; + DEBUG_PRINT_LOW("venc_set_session_qp:: i_frame_qp = %d, p_frame_qp = %d", i_frame_qp, + p_frame_qp); + + qp.iframeqp = i_frame_qp; + qp.pframqp = p_frame_qp; + + ioctl_msg.in = (void*)&qp; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_SESSION_QP,(void*)&ioctl_msg)< 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting session qp failed"); + return false; + } + + session_qp.iframeqp = i_frame_qp; + session_qp.pframqp = p_frame_qp; + + return true; +} + +bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_profile requested_profile; + struct ven_profilelevel requested_level; + unsigned const int *profile_tbl = NULL; + unsigned long mb_per_frame = 0, mb_per_sec = 0; + DEBUG_PRINT_LOW("venc_set_profile_level:: eProfile = %d, Level = %d", + eProfile, eLevel); + mb_per_frame = ((m_sVenc_cfg.input_height + 15) >> 4)* + ((m_sVenc_cfg.input_width + 15) >> 4); + if((eProfile == 0) && (eLevel == 0) && m_profile_set && m_level_set) + { + DEBUG_PRINT_LOW("\n Profile/Level setting complete before venc_start"); + return true; + } + + if(eProfile && eLevel) + { + /* non-zero values will be set by user, saving the same*/ + m_eProfile = eProfile; + m_eLevel = eLevel; + DEBUG_PRINT_HIGH("Profile/Level set equal to %d/%d",m_eProfile, m_eLevel); + } + + DEBUG_PRINT_LOW("\n Validating Profile/Level from table"); + if(!venc_validate_profile_level(&eProfile, &eLevel)) + { + DEBUG_PRINT_LOW("\nERROR: Profile/Level validation failed"); + return false; + } + + if(m_sVenc_cfg.codectype == VEN_CODEC_MPEG4) + { + DEBUG_PRINT_LOW("eProfile = %d, OMX_VIDEO_MPEG4ProfileSimple = %d and " + "OMX_VIDEO_MPEG4ProfileAdvancedSimple = %d", eProfile, + OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4ProfileAdvancedSimple); + if(eProfile == OMX_VIDEO_MPEG4ProfileSimple) + { + requested_profile.profile = VEN_PROFILE_MPEG4_SP; + profile_tbl = (unsigned int const *) + (&mpeg4_profile_level_table[MPEG4_SP_START]); + profile_tbl += MPEG4_720P_LEVEL*5; + } + else if(eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) + { + requested_profile.profile = VEN_PROFILE_MPEG4_ASP; + profile_tbl = (unsigned int const *) + (&mpeg4_profile_level_table[MPEG4_ASP_START]); + profile_tbl += MPEG4_720P_LEVEL*5; + } + else + { + DEBUG_PRINT_LOW("\nERROR: Unsupported MPEG4 profile = %u", + eProfile); + return false; + } + + DEBUG_PRINT_LOW("eLevel = %d, OMX_VIDEO_MPEG4Level0 = %d, OMX_VIDEO_MPEG4Level1 = %d," + "OMX_VIDEO_MPEG4Level2 = %d, OMX_VIDEO_MPEG4Level3 = %d, OMX_VIDEO_MPEG4Level4 = %d," + "OMX_VIDEO_MPEG4Level5 = %d", eLevel, OMX_VIDEO_MPEG4Level0, OMX_VIDEO_MPEG4Level1, + OMX_VIDEO_MPEG4Level2, OMX_VIDEO_MPEG4Level3, OMX_VIDEO_MPEG4Level4, OMX_VIDEO_MPEG4Level5); + + if(mb_per_frame >= 3600) + { + if(requested_profile.profile == VEN_PROFILE_MPEG4_ASP) + requested_level.level = VEN_LEVEL_MPEG4_5; + if(requested_profile.profile == VEN_PROFILE_MPEG4_SP) + requested_level.level = VEN_LEVEL_MPEG4_6; + } + else + { + switch(eLevel) + { + case OMX_VIDEO_MPEG4Level0: + requested_level.level = VEN_LEVEL_MPEG4_0; + break; + case OMX_VIDEO_MPEG4Level1: + requested_level.level = VEN_LEVEL_MPEG4_1; + break; + case OMX_VIDEO_MPEG4Level2: + requested_level.level = VEN_LEVEL_MPEG4_2; + break; + case OMX_VIDEO_MPEG4Level3: + requested_level.level = VEN_LEVEL_MPEG4_3; + break; + case OMX_VIDEO_MPEG4Level4a: + requested_level.level = VEN_LEVEL_MPEG4_4; + break; + case OMX_VIDEO_MPEG4Level5: + mb_per_sec = mb_per_frame * (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den); + if((requested_profile.profile == VEN_PROFILE_MPEG4_SP) && (mb_per_frame >= profile_tbl[0]) && + (mb_per_sec >= profile_tbl[1])) + { + DEBUG_PRINT_LOW("\nMPEG4 Level 6 is set for 720p resolution"); + requested_level.level = VEN_LEVEL_MPEG4_6; + } + else + { + DEBUG_PRINT_LOW("\nMPEG4 Level 5 is set for non-720p resolution"); + requested_level.level = VEN_LEVEL_MPEG4_5; + } + break; + default: + return false; + // TODO update corresponding levels for MPEG4_LEVEL_3b,MPEG4_LEVEL_6 + break; + } + } + } + else if(m_sVenc_cfg.codectype == VEN_CODEC_H263) + { + if(eProfile == OMX_VIDEO_H263ProfileBaseline) + { + requested_profile.profile = VEN_PROFILE_H263_BASELINE; + } + else + { + DEBUG_PRINT_LOW("\nERROR: Unsupported H.263 profile = %u", + requested_profile.profile); + return false; + } + //profile level + switch(eLevel) + { + case OMX_VIDEO_H263Level10: + requested_level.level = VEN_LEVEL_H263_10; + break; + case OMX_VIDEO_H263Level20: + requested_level.level = VEN_LEVEL_H263_20; + break; + case OMX_VIDEO_H263Level30: + requested_level.level = VEN_LEVEL_H263_30; + break; + case OMX_VIDEO_H263Level40: + requested_level.level = VEN_LEVEL_H263_40; + break; + case OMX_VIDEO_H263Level45: + requested_level.level = VEN_LEVEL_H263_45; + break; + case OMX_VIDEO_H263Level50: + requested_level.level = VEN_LEVEL_H263_50; + break; + case OMX_VIDEO_H263Level60: + requested_level.level = VEN_LEVEL_H263_60; + break; + case OMX_VIDEO_H263Level70: + requested_level.level = VEN_LEVEL_H263_70; + break; + default: + return false; + break; + } + } + else if(m_sVenc_cfg.codectype == VEN_CODEC_H264) + { + if(eProfile == OMX_VIDEO_AVCProfileBaseline) + { + requested_profile.profile = VEN_PROFILE_H264_BASELINE; + } + else if(eProfile == OMX_VIDEO_AVCProfileMain) + { + requested_profile.profile = VEN_PROFILE_H264_MAIN; + } + else if(eProfile == OMX_VIDEO_AVCProfileHigh) + { + requested_profile.profile = VEN_PROFILE_H264_HIGH; + } + else + { + DEBUG_PRINT_LOW("\nERROR: Unsupported H.264 profile = %u", + requested_profile.profile); + return false; + } + //profile level + switch(eLevel) + { + case OMX_VIDEO_AVCLevel1: + requested_level.level = VEN_LEVEL_H264_1; + break; + case OMX_VIDEO_AVCLevel1b: + requested_level.level = VEN_LEVEL_H264_1b; + break; + case OMX_VIDEO_AVCLevel11: + requested_level.level = VEN_LEVEL_H264_1p1; + break; + case OMX_VIDEO_AVCLevel12: + requested_level.level = VEN_LEVEL_H264_1p2; + break; + case OMX_VIDEO_AVCLevel13: + requested_level.level = VEN_LEVEL_H264_1p3; + break; + case OMX_VIDEO_AVCLevel2: + requested_level.level = VEN_LEVEL_H264_2; + break; + case OMX_VIDEO_AVCLevel21: + requested_level.level = VEN_LEVEL_H264_2p1; + break; + case OMX_VIDEO_AVCLevel22: + requested_level.level = VEN_LEVEL_H264_2p2; + break; + case OMX_VIDEO_AVCLevel3: + requested_level.level = VEN_LEVEL_H264_3; + break; + case OMX_VIDEO_AVCLevel31: + requested_level.level = VEN_LEVEL_H264_3p1; + break; + case OMX_VIDEO_AVCLevel32: + requested_level.level = VEN_LEVEL_H264_3p2; + break; + case OMX_VIDEO_AVCLevel4: + requested_level.level = VEN_LEVEL_H264_4; + break; + default : + DEBUG_PRINT_ERROR("\nERROR: Unsupported H.264 level= %u", + requested_level.level); + return false; + break; + } + } + if(!m_profile_set) + { + ioctl_msg.in = (void*)&requested_profile; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_CODEC_PROFILE,(void*)&ioctl_msg)< 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting profile failed"); + return false; + } + codec_profile.profile = requested_profile.profile; + m_profile_set = true; + } + + if(!m_level_set) + { + ioctl_msg.in = (void*)&requested_level; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_PROFILE_LEVEL,(void*)&ioctl_msg)< 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting profile level failed"); + return false; + } + profile_level.level = requested_level.level; + m_level_set = true; + } + + return true; +} + +bool venc_dev::venc_set_voptiming_cfg( OMX_U32 TimeIncRes) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_voptimingcfg vop_timing_cfg; + + DEBUG_PRINT_LOW("\n venc_set_voptiming_cfg: TimeRes = %u", + TimeIncRes); + + vop_timing_cfg.voptime_resolution = TimeIncRes; + + ioctl_msg.in = (void*)&vop_timing_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_VOP_TIMING_CFG,(void*)&ioctl_msg)< 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Vop Timing failed"); + return false; + } + + voptimecfg.voptime_resolution = vop_timing_cfg.voptime_resolution; + return true; +} + +bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_intraperiod intraperiod_cfg; + + DEBUG_PRINT_LOW("\n venc_set_intra_period: nPFrames = %u", + nPFrames); + intraperiod_cfg.num_pframes = nPFrames; + if((codec_profile.profile == VEN_PROFILE_MPEG4_ASP) || + (codec_profile.profile == VEN_PROFILE_H264_MAIN) || + (codec_profile.profile == VEN_PROFILE_H264_HIGH)) + { +#ifdef MAX_RES_1080P + if (nBFrames) + { + DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported"); + intraperiod_cfg.num_bframes = 1; + } + else + intraperiod_cfg.num_bframes = 0; +#else + if(nBFrames) + { + DEBUG_PRINT_ERROR("B frames not supported"); + intraperiod_cfg.num_bframes = 0; + } + else + { + DEBUG_PRINT_ERROR("B frames not supported"); + intraperiod_cfg.num_bframes = 0; + } +#endif + } + else + intraperiod_cfg.num_bframes = 0; + + DEBUG_PRINT_ERROR("\n venc_set_intra_period: nPFrames = %u nBFrames = %u", + intraperiod_cfg.num_pframes, intraperiod_cfg.num_bframes); + ioctl_msg.in = (void*)&intraperiod_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INTRA_PERIOD,(void*)&ioctl_msg)< 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + + intra_period.num_pframes = intraperiod_cfg.num_pframes; + intra_period.num_bframes = intraperiod_cfg.num_bframes; + return true; +} + +bool venc_dev::venc_set_entropy_config(OMX_BOOL enable, OMX_U32 i_cabac_level) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_entropycfg entropy_cfg; + + memset(&entropy_cfg,0,sizeof(entropy_cfg)); + DEBUG_PRINT_LOW("\n venc_set_entropy_config: CABAC = %u level: %u", enable, i_cabac_level); + + if(enable &&(codec_profile.profile != VEN_PROFILE_H264_BASELINE)){ + entropy_cfg.longentropysel = VEN_ENTROPY_MODEL_CABAC; + if (i_cabac_level == 0) { + entropy_cfg.cabacmodel = VEN_CABAC_MODEL_0; + } +#ifdef MAX_RES_1080P + else + { + DEBUG_PRINT_HIGH("Invalid model set (%d) defaulting to model 0",i_cabac_level); + entropy_cfg.cabacmodel = VEN_CABAC_MODEL_0; + } +#else + else if (i_cabac_level == 1) { + entropy_cfg.cabacmodel = VEN_CABAC_MODEL_1; + } + else if (i_cabac_level == 2) { + entropy_cfg.cabacmodel = VEN_CABAC_MODEL_2; + } +#endif + } + else if(!enable){ + entropy_cfg.longentropysel = VEN_ENTROPY_MODEL_CAVLC; + } + else{ + DEBUG_PRINT_ERROR("\nInvalid Entropy mode for Baseline Profile"); + return false; + } + + ioctl_msg.in = (void*)&entropy_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_ENTROPY_CFG,(void*)&ioctl_msg)< 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting entropy config failed"); + return false; + } + entropy.longentropysel = entropy_cfg.longentropysel; + entropy.cabacmodel = entropy_cfg.cabacmodel; + return true; +} + +bool venc_dev::venc_set_multislice_cfg(OMX_INDEXTYPE Codec, OMX_U32 nSlicesize) // MB +{ + venc_ioctl_msg ioctl_msg = {NULL, NULL}; + bool status = true; + struct venc_multiclicecfg multislice_cfg; + + if((Codec != OMX_IndexParamVideoH263) && (nSlicesize)){ + multislice_cfg.mslice_mode = VEN_MSLICE_CNT_MB; + multislice_cfg.mslice_size = nSlicesize; + } + else{ + multislice_cfg.mslice_mode = VEN_MSLICE_OFF; + multislice_cfg.mslice_size = 0; + } + + DEBUG_PRINT_LOW("\n %s(): mode = %u, size = %u", __func__, multislice_cfg.mslice_mode, + multislice_cfg.mslice_size); + + ioctl_msg.in = (void*)&multislice_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd, VEN_IOCTL_SET_MULTI_SLICE_CFG,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting multi-slice cfg failed"); + status = false; + } + else + { + multislice.mslice_mode = multislice_cfg.mslice_mode; + multislice.mslice_size = nSlicesize; + } + return status; +} + +bool venc_dev::venc_set_intra_refresh(OMX_VIDEO_INTRAREFRESHTYPE ir_mode, OMX_U32 irMBs) +{ + venc_ioctl_msg ioctl_msg = {NULL, NULL}; + bool status = true; + struct venc_intrarefresh intraRefresh_cfg; + + // There is no disabled mode. Disabled mode is indicated by a 0 count. + if (irMBs == 0 || ir_mode == OMX_VIDEO_IntraRefreshMax) + { + intraRefresh_cfg.irmode = VEN_IR_OFF; + intraRefresh_cfg.mbcount = 0; + } + else if ((ir_mode == OMX_VIDEO_IntraRefreshCyclic) && + (irMBs < ((m_sVenc_cfg.input_width * m_sVenc_cfg.input_height)>>8))) + { + intraRefresh_cfg.irmode = VEN_IR_CYCLIC; + intraRefresh_cfg.mbcount = irMBs; + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid IntraRefresh Parameters:" + "mb count: %d, mb mode:%d", irMBs, ir_mode); + return false; + } + + ioctl_msg.in = (void*)&intraRefresh_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INTRA_REFRESH,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Intra Refresh failed"); + status = false; + } + else + { + intra_refresh.irmode = intraRefresh_cfg.irmode; + intra_refresh.mbcount = intraRefresh_cfg.mbcount; + } + return status; +} + +bool venc_dev::venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* error_resilience) +{ + venc_ioctl_msg ioctl_msg = {NULL, NULL}; + bool status = true; + struct venc_headerextension hec_cfg; + struct venc_multiclicecfg multislice_cfg; + + if (m_sVenc_cfg.codectype == OMX_VIDEO_CodingMPEG4) { + if (error_resilience->bEnableHEC) { + hec_cfg.header_extension = 1; + } + else { + hec_cfg.header_extension = 0; + } + + ioctl_msg.in = (void*)&hec_cfg; + ioctl_msg.out = NULL; + if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_HEC,(void*)&ioctl_msg) < 0) { + DEBUG_PRINT_ERROR("\nERROR: Request for setting HEader Error correction failed"); + return false; + } + hec.header_extension = error_resilience->bEnableHEC; + } + + if (error_resilience->bEnableRVLC) { + DEBUG_PRINT_ERROR("\n RVLC is not Supported"); + return false; + } + + if (( m_sVenc_cfg.codectype != OMX_VIDEO_CodingH263) && + (error_resilience->bEnableDataPartitioning)) { + DEBUG_PRINT_ERROR("\n DataPartioning are not Supported for MPEG4/H264"); + return false; + } + + if (( m_sVenc_cfg.codectype != OMX_VIDEO_CodingH263) && + (error_resilience->nResynchMarkerSpacing)) { + multislice_cfg.mslice_mode = VEN_MSLICE_CNT_BYTE; + multislice_cfg.mslice_size = error_resilience->nResynchMarkerSpacing; + } + else if (m_sVenc_cfg.codectype == OMX_VIDEO_CodingH263 && + error_resilience->bEnableDataPartitioning) { + multislice_cfg.mslice_mode = VEN_MSLICE_GOB; + multislice_cfg.mslice_size = 0; + } + else { + multislice_cfg.mslice_mode = VEN_MSLICE_OFF; + multislice_cfg.mslice_size = 0; + } + DEBUG_PRINT_LOW("\n %s(): mode = %u, size = %u", __func__, multislice_cfg.mslice_mode, + multislice_cfg.mslice_size); + ioctl_msg.in = (void*)&multislice_cfg; + ioctl_msg.out = NULL; + if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_MULTI_SLICE_CFG,(void*)&ioctl_msg) < 0) { + DEBUG_PRINT_ERROR("\nERROR: Request for setting multi-slice cfg failed"); + status = false; + } + else + { + multislice.mslice_mode = multislice_cfg.mslice_mode ; + multislice.mslice_size = multislice_cfg.mslice_size; + + } + return status; +} + +bool venc_dev::venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loopfilter) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_dbcfg filter_cfg; + + memset(&filter_cfg, 0, sizeof(filter_cfg)); + DEBUG_PRINT_LOW("\n venc_set_inloop_filter: %u",loopfilter); + + if (loopfilter == OMX_VIDEO_AVCLoopFilterEnable){ + filter_cfg.db_mode = VEN_DB_ALL_BLKG_BNDRY; + } + else if(loopfilter == OMX_VIDEO_AVCLoopFilterDisable){ + filter_cfg.db_mode = VEN_DB_DISABLE; + } + else if(loopfilter == OMX_VIDEO_AVCLoopFilterDisableSliceBoundary){ + filter_cfg.db_mode = VEN_DB_SKIP_SLICE_BNDRY; + } + filter_cfg.slicealpha_offset = filter_cfg.slicebeta_offset = 0; + + ioctl_msg.in = (void*)&filter_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_DEBLOCKING_CFG,(void*)&ioctl_msg)< 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting inloop filter failed"); + return false; + } + + dbkfilter.db_mode = filter_cfg.db_mode; + dbkfilter.slicealpha_offset = dbkfilter.slicebeta_offset = 0; + return true; +} + +bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate, OMX_U32 config) +{ + venc_ioctl_msg ioctl_msg = {NULL, NULL}; + struct venc_targetbitrate bitrate_cfg; + + DEBUG_PRINT_LOW("\n venc_set_target_bitrate: bitrate = %u", + nTargetBitrate); + bitrate_cfg.target_bitrate = nTargetBitrate ; + ioctl_msg.in = (void*)&bitrate_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_TARGET_BITRATE,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting bit rate failed"); + return false; + } + m_sVenc_cfg.targetbitrate = nTargetBitrate; + bitrate.target_bitrate = nTargetBitrate; + if(!config) + { + m_level_set = false; + if(venc_set_profile_level(0, 0)) + { + DEBUG_PRINT_LOW("Calling set level (Bitrate) with %d\n",profile_level.level); + } + } + return true; +} + +bool venc_dev::venc_set_encode_framerate(OMX_U32 encode_framerate, OMX_U32 config) +{ + venc_ioctl_msg ioctl_msg = {NULL, NULL}; + struct venc_framerate frame_rate_cfg; + + Q16ToFraction(encode_framerate,frame_rate_cfg.fps_numerator,frame_rate_cfg.fps_denominator); + + DEBUG_PRINT_LOW("\n venc_set_encode_framerate: framerate(Q16) = %u,NR: %d, DR: %d", + encode_framerate,frame_rate_cfg.fps_numerator,frame_rate_cfg.fps_denominator); + + ioctl_msg.in = (void*)&frame_rate_cfg; + ioctl_msg.out = NULL; + if(ioctl(m_nDriver_fd, VEN_IOCTL_SET_FRAME_RATE, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting framerate failed"); + return false; + } + + m_sVenc_cfg.fps_den = frame_rate_cfg.fps_denominator; + m_sVenc_cfg.fps_num = frame_rate_cfg.fps_numerator; + if(!config) + { + m_level_set = false; + if(venc_set_profile_level(0, 0)) + { + DEBUG_PRINT_LOW("Calling set level (Framerate) with %d\n",profile_level.level); + } + } + return true; +} + +bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format) +{ + venc_ioctl_msg ioctl_msg = {NULL, NULL}; + DEBUG_PRINT_LOW("\n venc_set_color_format: color_format = %u ", color_format); + + if(color_format == OMX_COLOR_FormatYUV420SemiPlanar) + { +#ifdef MAX_RES_1080P + m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12_16M2KA; +#else + m_sVenc_cfg.inputformat = VEN_INPUTFMT_NV12; +#endif + } + else + { + DEBUG_PRINT_ERROR("\nWARNING: Unsupported Color format [%d]", color_format); +#ifdef MAX_RES_1080P + m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12_16M2KA; +#else + m_sVenc_cfg.inputformat = VEN_INPUTFMT_NV12; +#endif + DEBUG_PRINT_HIGH("\n Default color format YUV420SemiPlanar is set"); + } + ioctl_msg.in = (void*)&m_sVenc_cfg; + ioctl_msg.out = NULL; + if (ioctl(m_nDriver_fd, VEN_IOCTL_SET_BASE_CFG, (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting color format failed"); + return false; + } + return true; +} + +bool venc_dev::venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh) +{ + DEBUG_PRINT_LOW("\n venc_set_intra_vop_refresh: intra_vop = %uc", intra_vop_refresh); + if(intra_vop_refresh == OMX_TRUE) + { + if(ioctl(m_nDriver_fd, VEN_IOCTL_CMD_REQUEST_IFRAME, NULL) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Intra VOP Refresh failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: VOP Refresh is False, no effect"); + } + return true; +} + +bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + bool status = true; + struct venc_ratectrlcfg ratectrl_cfg; + + //rate control + switch(eControlRate) + { + case OMX_Video_ControlRateDisable: + ratectrl_cfg.rcmode = VEN_RC_OFF; + break; + case OMX_Video_ControlRateVariableSkipFrames: + ratectrl_cfg.rcmode = VEN_RC_VBR_VFR; + break; + case OMX_Video_ControlRateVariable: + ratectrl_cfg.rcmode = VEN_RC_VBR_CFR; + break; + case OMX_Video_ControlRateConstantSkipFrames: + ratectrl_cfg.rcmode = VEN_RC_CBR_VFR; + break; + case OMX_Video_ControlRateConstant: + ratectrl_cfg.rcmode = VEN_RC_CBR_CFR; + break; + default: + status = false; + break; + } + + if(status) + { + ioctl_msg.in = (void*)&ratectrl_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_RATE_CTRL_CFG,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting rate control failed"); + status = false; + } + else + rate_ctrl.rcmode = ratectrl_cfg.rcmode; + } + return status; +} + +bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel) +{ + bool status = true; + if(eProfile == NULL || eLevel == NULL) + { + return false; + } + + if(m_sVenc_cfg.codectype == VEN_CODEC_MPEG4) + { + switch(codec_profile.profile) + { + case VEN_PROFILE_MPEG4_SP: + *eProfile = OMX_VIDEO_MPEG4ProfileSimple; + break; + case VEN_PROFILE_MPEG4_ASP: + *eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + break; + default: + *eProfile = OMX_VIDEO_MPEG4ProfileMax; + status = false; + break; + } + + if(!status) + { + return status; + } + + //profile level + switch(profile_level.level) + { + case VEN_LEVEL_MPEG4_0: + *eLevel = OMX_VIDEO_MPEG4Level0; + break; + case VEN_LEVEL_MPEG4_1: + *eLevel = OMX_VIDEO_MPEG4Level1; + break; + case VEN_LEVEL_MPEG4_2: + *eLevel = OMX_VIDEO_MPEG4Level2; + break; + case VEN_LEVEL_MPEG4_3: + *eLevel = OMX_VIDEO_MPEG4Level3; + break; + case VEN_LEVEL_MPEG4_4: + *eLevel = OMX_VIDEO_MPEG4Level4a; + break; + case VEN_LEVEL_MPEG4_5: + case VEN_LEVEL_MPEG4_6: + *eLevel = OMX_VIDEO_MPEG4Level5; + break; + default: + *eLevel = OMX_VIDEO_MPEG4LevelMax; + status = false; + break; + } + } + else if(m_sVenc_cfg.codectype == VEN_CODEC_H263) + { + if(codec_profile.profile == VEN_PROFILE_H263_BASELINE) + { + *eProfile = OMX_VIDEO_H263ProfileBaseline; + } + else + { + *eProfile = OMX_VIDEO_H263ProfileMax; + return false; + } + switch(profile_level.level) + { + case VEN_LEVEL_H263_10: + *eLevel = OMX_VIDEO_H263Level10; + break; + case VEN_LEVEL_H263_20: + *eLevel = OMX_VIDEO_H263Level20; + break; + case VEN_LEVEL_H263_30: + *eLevel = OMX_VIDEO_H263Level30; + break; + case VEN_LEVEL_H263_40: + *eLevel = OMX_VIDEO_H263Level40; + break; + case VEN_LEVEL_H263_45: + *eLevel = OMX_VIDEO_H263Level45; + break; + case VEN_LEVEL_H263_50: + *eLevel = OMX_VIDEO_H263Level50; + break; + case VEN_LEVEL_H263_60: + *eLevel = OMX_VIDEO_H263Level60; + break; + case VEN_LEVEL_H263_70: + *eLevel = OMX_VIDEO_H263Level70; + break; + default: + *eLevel = OMX_VIDEO_H263LevelMax; + status = false; + break; + } + } + else if(m_sVenc_cfg.codectype == VEN_CODEC_H264) + { + switch(codec_profile.profile) + { + case VEN_PROFILE_H264_BASELINE: + *eProfile = OMX_VIDEO_AVCProfileBaseline; + break; + case VEN_PROFILE_H264_MAIN: + *eProfile = OMX_VIDEO_AVCProfileMain; + break; + case VEN_PROFILE_H264_HIGH: + *eProfile = OMX_VIDEO_AVCProfileHigh; + break; + default: + *eProfile = OMX_VIDEO_AVCProfileMax; + status = false; + break; + } + + if(!status) + { + return status; + } + + switch(profile_level.level) + { + case VEN_LEVEL_H264_1: + *eLevel = OMX_VIDEO_AVCLevel1; + break; + case VEN_LEVEL_H264_1b: + *eLevel = OMX_VIDEO_AVCLevel1b; + break; + case VEN_LEVEL_H264_1p1: + *eLevel = OMX_VIDEO_AVCLevel11; + break; + case VEN_LEVEL_H264_1p2: + *eLevel = OMX_VIDEO_AVCLevel12; + break; + case VEN_LEVEL_H264_1p3: + *eLevel = OMX_VIDEO_AVCLevel13; + break; + case VEN_LEVEL_H264_2: + *eLevel = OMX_VIDEO_AVCLevel2; + break; + case VEN_LEVEL_H264_2p1: + *eLevel = OMX_VIDEO_AVCLevel21; + break; + case VEN_LEVEL_H264_2p2: + *eLevel = OMX_VIDEO_AVCLevel22; + break; + case VEN_LEVEL_H264_3: + *eLevel = OMX_VIDEO_AVCLevel3; + break; + case VEN_LEVEL_H264_3p1: + *eLevel = OMX_VIDEO_AVCLevel31; + break; + case VEN_LEVEL_H264_3p2: + *eLevel = OMX_VIDEO_AVCLevel32; + break; + case VEN_LEVEL_H264_4: + *eLevel = OMX_VIDEO_AVCLevel4; + break; + default : + *eLevel = OMX_VIDEO_AVCLevelMax; + status = false; + break; + } + } + return status; +} + +bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel) +{ + OMX_U32 new_profile = 0, new_level = 0; + unsigned const int *profile_tbl = NULL; + OMX_U32 mb_per_frame, mb_per_sec; + bool profile_level_found = false; + + DEBUG_PRINT_LOW("\n Init profile table for respective codec"); + //validate the ht,width,fps,bitrate and set the appropriate profile and level + if(m_sVenc_cfg.codectype == VEN_CODEC_MPEG4) + { + if(*eProfile == 0) + { + if(!m_profile_set) + { + *eProfile = OMX_VIDEO_MPEG4ProfileSimple; + } + else + { + switch(codec_profile.profile) + { + case VEN_PROFILE_MPEG4_ASP: + *eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + break; + case VEN_PROFILE_MPEG4_SP: + *eProfile = OMX_VIDEO_MPEG4ProfileSimple; + break; + default: + DEBUG_PRINT_LOW("\n %s(): Unknown Error", __func__); + return false; + } + } + } + + if(*eLevel == 0 && !m_level_set) + { + *eLevel = OMX_VIDEO_MPEG4LevelMax; + } + + if(*eProfile == OMX_VIDEO_MPEG4ProfileSimple) + { + profile_tbl = (unsigned int const *)mpeg4_profile_level_table; + } + else if(*eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) + { + profile_tbl = (unsigned int const *) + (&mpeg4_profile_level_table[MPEG4_ASP_START]); + } + else + { + DEBUG_PRINT_LOW("\n Unsupported MPEG4 profile type %lu", *eProfile); + return false; + } + } + else if(m_sVenc_cfg.codectype == VEN_CODEC_H264) + { + if(*eProfile == 0) + { + if(!m_profile_set) + { + *eProfile = OMX_VIDEO_AVCProfileBaseline; + } + else + { + switch(codec_profile.profile) + { + case VEN_PROFILE_H264_BASELINE: + *eProfile = OMX_VIDEO_AVCProfileBaseline; + break; + case VEN_PROFILE_H264_MAIN: + *eProfile = OMX_VIDEO_AVCProfileMain; + break; + case VEN_PROFILE_H264_HIGH: + *eProfile = OMX_VIDEO_AVCProfileHigh; + break; + default: + DEBUG_PRINT_LOW("\n %s(): Unknown Error", __func__); + return false; + } + } + } + + if(*eLevel == 0 && !m_level_set) + { + *eLevel = OMX_VIDEO_AVCLevelMax; + } + + if(*eProfile == OMX_VIDEO_AVCProfileBaseline) + { + profile_tbl = (unsigned int const *)h264_profile_level_table; + } + else if(*eProfile == OMX_VIDEO_AVCProfileHigh) + { + profile_tbl = (unsigned int const *) + (&h264_profile_level_table[H264_HP_START]); + } + else if(*eProfile == OMX_VIDEO_AVCProfileMain) + { + profile_tbl = (unsigned int const *) + (&h264_profile_level_table[H264_MP_START]); + } + else + { + DEBUG_PRINT_LOW("\n Unsupported AVC profile type %lu", *eProfile); + return false; + } + } + else if(m_sVenc_cfg.codectype == VEN_CODEC_H263) + { + if(*eProfile == 0) + { + if(!m_profile_set) + { + *eProfile = OMX_VIDEO_H263ProfileBaseline; + } + else + { + switch(codec_profile.profile) + { + case VEN_PROFILE_H263_BASELINE: + *eProfile = OMX_VIDEO_H263ProfileBaseline; + break; + default: + DEBUG_PRINT_LOW("\n %s(): Unknown Error", __func__); + return false; + } + } + } + + if(*eLevel == 0 && !m_level_set) + { + *eLevel = OMX_VIDEO_H263LevelMax; + } + + if(*eProfile == OMX_VIDEO_H263ProfileBaseline) + { + profile_tbl = (unsigned int const *)h263_profile_level_table; + } + else + { + DEBUG_PRINT_LOW("\n Unsupported H.263 profile type %lu", *eProfile); + return false; + } + } + else + { + DEBUG_PRINT_LOW("\n Invalid codec type"); + return false; + } + + mb_per_frame = ((m_sVenc_cfg.input_height + 15) >> 4)* + ((m_sVenc_cfg.input_width + 15)>> 4); + + if((mb_per_frame >= 3600) && (m_sVenc_cfg.codectype == VEN_CODEC_MPEG4)) + { + if(codec_profile.profile == VEN_PROFILE_MPEG4_ASP) + profile_level.level = VEN_LEVEL_MPEG4_5; + if(codec_profile.profile == VEN_PROFILE_MPEG4_SP) + profile_level.level = VEN_LEVEL_MPEG4_6; + { + new_level = profile_level.level; + new_profile = codec_profile.profile; + return true; + } + } + + mb_per_sec = mb_per_frame * m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den; + + do{ + if(mb_per_frame <= (int)profile_tbl[0]) + { + if(mb_per_sec <= (int)profile_tbl[1]) + { + if(m_sVenc_cfg.targetbitrate <= (int)profile_tbl[2]) + { + new_level = (int)profile_tbl[3]; + new_profile = (int)profile_tbl[4]; + profile_level_found = true; + DEBUG_PRINT_LOW("\n Appropriate profile/level found %d/%d\n", new_profile, new_level); + break; + } + } + } + profile_tbl = profile_tbl + 5; + }while(profile_tbl[0] != 0); + + if (profile_level_found != true) + { + DEBUG_PRINT_LOW("\n ERROR: Unsupported profile/level\n"); + return false; + } + + if((*eLevel == OMX_VIDEO_MPEG4LevelMax) || (*eLevel == OMX_VIDEO_AVCLevelMax) + || (*eLevel == OMX_VIDEO_H263LevelMax)) + { + *eLevel = new_level; + } + DEBUG_PRINT_LOW("%s: Returning with eProfile = %lu" + "Level = %lu", __func__, *eProfile, *eLevel); + + return true; +} + +bool venc_dev::venc_max_allowed_bitrate_check(OMX_U32 nTargetBitrate) +{ + unsigned const int *profile_tbl = NULL; + + switch(m_sVenc_cfg.codectype) + { + case VEN_CODEC_MPEG4: + if(m_eProfile == OMX_VIDEO_MPEG4ProfileSimple) + { + profile_tbl = (unsigned int const *)mpeg4_profile_level_table; + } + else if(m_eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) + { + profile_tbl = (unsigned int const *) + (&mpeg4_profile_level_table[MPEG4_ASP_START]); + } + else + { + DEBUG_PRINT_ERROR("Unsupported MPEG4 profile type %lu", m_eProfile); + return false; + } + break; + case VEN_CODEC_H264: + if(m_eProfile == OMX_VIDEO_AVCProfileBaseline) + { + profile_tbl = (unsigned int const *)h264_profile_level_table; + } + else if(m_eProfile == OMX_VIDEO_AVCProfileHigh) + { + profile_tbl = (unsigned int const *) + (&h264_profile_level_table[H264_HP_START]); + } + else if(m_eProfile == OMX_VIDEO_AVCProfileMain) + { + profile_tbl = (unsigned int const *) + (&h264_profile_level_table[H264_MP_START]); + } + else + { + DEBUG_PRINT_ERROR("Unsupported AVC profile type %lu", m_eProfile); + return false; + } + + break; + case VEN_CODEC_H263: + if(m_eProfile == OMX_VIDEO_H263ProfileBaseline) + { + profile_tbl = (unsigned int const *)h263_profile_level_table; + } + else + { + DEBUG_PRINT_ERROR("Unsupported H.263 profile type %lu", m_eProfile); + return false; + } + break; + default: + DEBUG_PRINT_ERROR("%s: unknown codec type", __func__); + return false; + } + while(profile_tbl[0] != 0) + { + if(profile_tbl[3] == m_eLevel) + { + if(nTargetBitrate > profile_tbl[2]) + { + DEBUG_PRINT_ERROR("Max. supported bitrate for Profile[%d] & Level[%d]" + " is %u", m_eProfile, m_eLevel, profile_tbl[2]); + return false; + } + } + profile_tbl += 5; + } + return true; +} + +#ifdef _ANDROID_ICS_ +bool venc_dev::venc_set_meta_mode(bool mode) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + ioctl_msg.in = &mode; + DEBUG_PRINT_HIGH("Set meta buffer mode: %d", mode); + if(ioctl(m_nDriver_fd,VEN_IOCTL_SET_METABUFFER_MODE,&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR(" Set meta buffer mode failed"); + return false; + } + return true; +} +#endif diff --git a/mm-video/vidc/venc/src/video_encoder_device_msm8974.cpp b/mm-video/vidc/venc/src/video_encoder_device_msm8974.cpp new file mode 100755 index 0000000..7579277 --- /dev/null +++ b/mm-video/vidc/venc/src/video_encoder_device_msm8974.cpp @@ -0,0 +1,3113 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2012, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include "video_encoder_device_msm8974.h" +#include "omx_video_encoder.h" +#include +#ifdef USE_ION +#include +#endif + +#define MPEG4_SP_START 0 +#define MPEG4_ASP_START (MPEG4_SP_START + 8) +#define MPEG4_720P_LEVEL 6 +#define H263_BP_START 0 +#define H264_BP_START 0 +#define H264_HP_START (H264_BP_START + 13) +#define H264_MP_START (H264_BP_START + 26) + +/* MPEG4 profile and level table*/ +static const unsigned int mpeg4_profile_level_table[][5]= +{ + /*max mb per frame, max mb per sec, max bitrate, level, profile*/ + {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple}, + {99,1485,64000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple}, + {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple}, + {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple}, + {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple}, + {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, + {3600,108000,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, + {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, + {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, + {0,0,0,0,0}, + + {99,1485,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {0,0,0,0,0}, +}; + +/* H264 profile and level table*/ +static const unsigned int h264_profile_level_table[][5]= +{ + /*max mb per frame, max mb per sec, max bitrate, level, profile*/ + {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline}, + {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline}, + {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline}, + {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline}, + {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline}, + {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline}, + {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline}, + {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline}, + {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline}, + {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline}, + {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileBaseline}, + {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline}, + {32400,972000,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline}, + {34560,1036800,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline}, + {0,0,0,0,0}, + + {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh}, + {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh}, + {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh}, + {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh}, + {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh}, + {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh}, + {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh}, + {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh}, + {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh}, + {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh}, + {5120,216000,25000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh}, + {8192,245760,25000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh}, + {32400,972000,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh}, + {34560,1036800,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh}, + {0,0,0,0,0}, + + {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain}, + {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain}, + {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain}, + {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain}, + {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain}, + {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain}, + {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain}, + {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain}, + {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain}, + {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain}, + {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileMain}, + {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain}, + {32400,972000,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain}, + {34560,1036800,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain}, + {0,0,0,0,0} + +}; + +/* H263 profile and level table*/ +static const unsigned int h263_profile_level_table[][5]= +{ + /*max mb per frame, max mb per sec, max bitrate, level, profile*/ + {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline}, + {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline}, + {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline}, + {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline}, + {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline}, + {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline}, + {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline}, + {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, + {32400,972000,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, + {34560,1036800,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, + + {0,0,0,0,0} +}; + +#define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } +#define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); } + +#ifdef INPUT_BUFFER_LOG +FILE *inputBufferFile1; +char inputfilename [] = "/data/input.yuv"; +#endif +#ifdef OUTPUT_BUFFER_LOG +FILE *outputBufferFile1; +char outputfilename [] = "/data/output-bitstream.\0\0\0\0"; +#endif +//constructor +venc_dev::venc_dev(class omx_venc *venc_class) +{ +//nothing to do +venc_handle = venc_class; +etb_count=0; +} + +venc_dev::~venc_dev() +{ + //nothing to do +} + +void* async_venc_message_thread (void *input) +{ + struct venc_timeout timeout; + struct venc_msg venc_msg; + omx_video* omx_venc_base = NULL; + omx_venc *omx = reinterpret_cast(input); + omx_venc_base = reinterpret_cast(input); + OMX_BUFFERHEADERTYPE* omxhdr = NULL; + + + prctl(PR_SET_NAME, (unsigned long)"VideoEncCallBackThread", 0, 0, 0); + timeout.millisec = VEN_TIMEOUT_INFINITE; + struct v4l2_plane plane; + struct pollfd pfd; + struct v4l2_buffer v4l2_buf ={0}; + struct v4l2_event dqevent; + pfd.events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI; + pfd.fd = omx->handle->m_nDriver_fd; + int error_code = 0,rc=0; + while(1) + { + rc = poll(&pfd, 1, TIMEOUT); + if (!rc) { + DEBUG_PRINT_ERROR("Poll timedout\n"); + break; + } else if (rc < 0) { + DEBUG_PRINT_ERROR("Error while polling: %d\n", rc); + break; + } + if (pfd.revents & POLLPRI){ + rc = ioctl(pfd.fd, VIDIOC_DQEVENT, &dqevent); + printf("\n Data Recieved = %d \n",dqevent.type); + if(dqevent.type == V4L2_EVENT_MSM_VIDC_CLOSE_DONE){ + printf("CLOSE DONE\n"); + break; + } + } + if ((pfd.revents & POLLIN) || (pfd.revents & POLLRDNORM)) { + v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + v4l2_buf.memory = V4L2_MEMORY_USERPTR; + v4l2_buf.length = 1; + v4l2_buf.m.planes = &plane; + rc = ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf); + if (rc) { + DEBUG_PRINT_ERROR("Failed to dequeue buf: %d from capture capability\n", rc); + break; + } + venc_msg.msgcode=VEN_MSG_OUTPUT_BUFFER_DONE; + venc_msg.statuscode=VEN_S_SUCCESS; + omxhdr=omx_venc_base->m_out_mem_ptr+v4l2_buf.index; + venc_msg.buf.len= v4l2_buf.m.planes->bytesused; + venc_msg.buf.offset = v4l2_buf.m.planes->reserved[1]; + venc_msg.buf.ptrbuffer = (OMX_U8 *)omx_venc_base->m_pOutput_pmem[v4l2_buf.index].buffer; + + venc_msg.buf.clientdata=(void*)omxhdr; + } + if((pfd.revents & POLLOUT) || (pfd.revents & POLLWRNORM)) { + v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + v4l2_buf.memory = V4L2_MEMORY_USERPTR; + v4l2_buf.m.planes = &plane; + rc = ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf); + if (rc) { + DEBUG_PRINT_ERROR("Failed to dequeue buf: %d from output capability\n", rc); + break; + } + venc_msg.msgcode=VEN_MSG_INPUT_BUFFER_DONE; + venc_msg.statuscode=VEN_S_SUCCESS; + omxhdr=omx_venc_base->m_inp_mem_ptr+v4l2_buf.index; + venc_msg.buf.clientdata=(void*)omxhdr; + } + + if(omx->async_message_process(input,&venc_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Wrong ioctl message"); + break; + } + } + DEBUG_PRINT_HIGH("omx_venc: Async Thread exit\n"); + return NULL; +} + +static OMX_ERRORTYPE subscribe_to_events(int fd) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct v4l2_event_subscription sub; + int event_type[] = { + V4L2_EVENT_MSM_VIDC_CLOSE_DONE + }; + int array_sz = sizeof(event_type)/sizeof(int); + int i,rc; + if (fd < 0) { + printf("Invalid input: %d\n", fd); + return OMX_ErrorBadParameter; + } + + for (i = 0; i < array_sz; ++i) { + memset(&sub, 0, sizeof(sub)); + sub.type = event_type[i]; + rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub); + if (rc) { + printf("Failed to subscribe event: 0x%x\n", sub.type); + break; + } + } + if (i < array_sz) { + for (;i >=0 ; i--) { + memset(&sub, 0, sizeof(sub)); + sub.type = event_type[i]; + rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); + if (rc) + printf("Failed to unsubscribe event: 0x%x\n", sub.type); + } + eRet = OMX_ErrorNotImplemented; + } + return eRet; +} + +bool venc_dev::venc_open(OMX_U32 codec) +{ + int r; + unsigned int alignment = 0,buffer_size = 0, temp =0; + + m_nDriver_fd = open ("/dev/video33",O_RDWR); + if(m_nDriver_fd == 0) + { + DEBUG_PRINT_ERROR("ERROR: Got fd as 0 for msm_vidc_enc, Opening again\n"); + m_nDriver_fd = open ("/dev/video33",O_RDWR); + } + + if((int)m_nDriver_fd < 0) + { + DEBUG_PRINT_ERROR("ERROR: Omx_venc::Comp Init Returning failure\n"); + return false; + } + + DEBUG_PRINT_LOW("\nm_nDriver_fd = %d\n", m_nDriver_fd); +#ifdef SINGLE_ENCODER_INSTANCE + OMX_U32 num_instances = 0; + if(/*ioctl (m_nDriver_fd, VEN_IOCTL_GET_NUMBER_INSTANCES, (void*)&ioctl_msg) < */0 ) + { + DEBUG_PRINT_ERROR("\nERROR: Request number of encoder instances failed"); + } + else if (num_instances > 1) + { + DEBUG_PRINT_ERROR("\nSecond encoder instance rejected!"); + venc_close(); + return false; + } +#endif + // set the basic configuration of the video encoder driver + m_sVenc_cfg.input_width = OMX_CORE_QCIF_WIDTH; + m_sVenc_cfg.input_height= OMX_CORE_QCIF_HEIGHT; + m_sVenc_cfg.dvs_width = OMX_CORE_QCIF_WIDTH; + m_sVenc_cfg.dvs_height = OMX_CORE_QCIF_HEIGHT; + m_sVenc_cfg.fps_num = 30; + m_sVenc_cfg.fps_den = 1; + m_sVenc_cfg.targetbitrate = 64000; + m_sVenc_cfg.inputformat= V4L2_PIX_FMT_NV12; + if(codec == OMX_VIDEO_CodingMPEG4) + { + m_sVenc_cfg.codectype = V4L2_PIX_FMT_MPEG4; + codec_profile.profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE; + profile_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_2; +#ifdef OUTPUT_BUFFER_LOG + strcat(outputfilename, "m4v"); +#endif + } + else if(codec == OMX_VIDEO_CodingH263) + { + m_sVenc_cfg.codectype = V4L2_PIX_FMT_H263; + codec_profile.profile = VEN_PROFILE_H263_BASELINE; + profile_level.level = VEN_LEVEL_H263_20; +#ifdef OUTPUT_BUFFER_LOG + strcat(outputfilename, "263"); +#endif + } + if(codec == OMX_VIDEO_CodingAVC) + { + m_sVenc_cfg.codectype = V4L2_PIX_FMT_H264; + codec_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE; + profile_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_1_0; +#ifdef OUTPUT_BUFFER_LOG + strcat(outputfilename, "264"); +#endif + } +if (codec == OMX_VIDEO_CodingVPX) + { + m_sVenc_cfg.codectype = V4L2_PIX_FMT_VP8; + codec_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE; + profile_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_1_0; +#ifdef OUTPUT_BUFFER_LOG + strcat(outputfilename, "ivf"); +#endif + } + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < */0 ) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting base configuration failed"); + return false; + } +#ifdef INPUT_BUFFER_LOG + inputBufferFile1 = fopen (inputfilename, "ab"); +#endif +#ifdef OUTPUT_BUFFER_LOG + outputBufferFile1 = fopen (outputfilename, "ab"); +#endif + int ret; + ret = subscribe_to_events(m_nDriver_fd); + if (ret) { + DEBUG_PRINT_ERROR("\n Subscribe Event Failed \n"); + return false; + } + struct v4l2_capability cap; + struct v4l2_fmtdesc fdesc; + struct v4l2_format fmt; + struct v4l2_requestbuffers bufreq; + + ret = ioctl(m_nDriver_fd, VIDIOC_QUERYCAP, &cap); + if (ret) { + DEBUG_PRINT_ERROR("Failed to query capabilities\n"); + } else { + DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s," + " version = %d, capabilities = %x\n", cap.driver, cap.card, + cap.bus_info, cap.version, cap.capabilities); + } + //printf(" \n VIDIOC_QUERYCAP Successful \n "); + ret=0; + fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fdesc.index=0; + while (ioctl(m_nDriver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) { + DEBUG_PRINT_LOW("fmt: description: %s, fmt: %x, flags = %x\n", fdesc.description, + fdesc.pixelformat, fdesc.flags); + fdesc.index++; + } + //printf("\n VIDIOC_ENUM_FMT CAPTURE Successful \n "); + fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fdesc.index=0; + while (ioctl(m_nDriver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) { + DEBUG_PRINT_LOW("fmt: description: %s, fmt: %x, flags = %x\n", fdesc.description, + fdesc.pixelformat, fdesc.flags); + fdesc.index++; + } + //printf(" \n VIDIOC_ENUM_FMT OUTPUT Successful \n "); + + m_sOutput_buff_property.alignment=m_sInput_buff_property.alignment=4096; + + fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; + fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12; + + ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt); + //printf(" \n VIDIOC_S_FMT OUTPUT Successful \n "); + m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage; + //printf("m_sInput_buff_property.datasize = %d\n",m_sInput_buff_property.datasize); + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; + fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; + fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype; + + ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt); + //printf(" \n VIDIOC_S_FMT CAPTURE Successful \n "); + m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage; + //printf("m_sOutput_buff_property.datasize = %d\n",m_sOutput_buff_property.datasize); +// struct v4l2_requestbuffers bufreq; + + bufreq.memory = V4L2_MEMORY_USERPTR; + bufreq.count = 2; + + bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq); + m_sInput_buff_property.mincount=m_sInput_buff_property.maxcount=m_sInput_buff_property.actualcount=bufreq.count; + //printf(" \n VIDIOC_REQBUFS OUTPUT Successful \n "); + //printf("m_sInput_buff_property.datasize = %d\n",m_sInput_buff_property.datasize); + //printf("m_sInput_buff_property.mincount = %d\n",m_sInput_buff_property.mincount); + bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + bufreq.count = 2; + ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq); + m_sOutput_buff_property.mincount=m_sOutput_buff_property.maxcount=m_sOutput_buff_property.actualcount=bufreq.count; + //printf(" \n VIDIOC_REQBUFS CAPTURE Successful \n "); + //printf("m_sInput_buff_property.mincount = %d\n",m_sOutput_buff_property.mincount); + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for getting i/p buffer requirement failed"); + return false; + } + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for getting o/p buffer requirement failed"); + return false; + } + ///printf("\n \n Setting Profile and Level \n \n "); + //m_profile_set = false; + //m_level_set = false; + if(/*venc_set_profile_level(0, 0)*/0) + { + DEBUG_PRINT_HIGH("\n %s(): Init Profile/Level setting success", + __func__); + } + recon_buffers_count = MAX_RECON_BUFFERS; + return true; +} + +void venc_dev::venc_close() +{ + DEBUG_PRINT_LOW("\nvenc_close: fd = %d", m_nDriver_fd); + if((int)m_nDriver_fd >= 0) + { + DEBUG_PRINT_HIGH("\n venc_close(): Calling VEN_IOCTL_CMD_STOP_READ_MSG"); + //(void)ioctl(m_nDriver_fd, VEN_IOCTL_CMD_STOP_READ_MSG, + // NULL); + DEBUG_PRINT_LOW("\nCalling close()\n"); + + int rc=0; + enum v4l2_buf_type btype; + btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + rc = ioctl(m_nDriver_fd, VIDIOC_STREAMOFF, &btype); + if (rc) { + /* STREAMOFF will never fail */ + DEBUG_PRINT_ERROR("\n Failed to call streamoff on OUTPUT Port \n"); + } + btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + + rc = ioctl(m_nDriver_fd, VIDIOC_STREAMOFF, &btype); + if (rc) { + /* STREAMOFF will never fail */ + DEBUG_PRINT_ERROR("\n Failed to call streamoff on CAPTURE Port \n"); + } + struct v4l2_event_subscription sub; + sub.type=V4L2_EVENT_ALL; + rc = ioctl(m_nDriver_fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub); + if (rc) { + DEBUG_PRINT_ERROR("Failed to get control\n"); + return ; + } + close(m_nDriver_fd); + m_nDriver_fd = -1; + } +#ifdef INPUT_BUFFER_LOG + fclose (inputBufferFile1); +#endif +#ifdef OUTPUT_BUFFER_LOG + fclose (outputBufferFile1); +#endif +} + +bool venc_dev::venc_set_buf_req(unsigned long *min_buff_count, + unsigned long *actual_buff_count, + unsigned long *buff_size, + unsigned long port) +{ + + unsigned long temp_count = 0; + + if(port == 0) + { + if(*actual_buff_count > m_sInput_buff_property.mincount) + { + temp_count = m_sInput_buff_property.actualcount; + m_sInput_buff_property.actualcount = *actual_buff_count; + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting i/p buffer requirement failed"); + m_sInput_buff_property.actualcount = temp_count; + return false; + } + DEBUG_PRINT_LOW("\n I/P Count set to %lu\n", *actual_buff_count); + } + } + else + { + if(*actual_buff_count > m_sOutput_buff_property.mincount) + { + temp_count = m_sOutput_buff_property.actualcount; + m_sOutput_buff_property.actualcount = *actual_buff_count; + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting o/p buffer requirement failed"); + m_sOutput_buff_property.actualcount = temp_count; + return false; + } + DEBUG_PRINT_LOW("\n O/P Count set to %lu\n", *actual_buff_count); + } + } + + return true; + +} + +bool venc_dev::venc_loaded_start() +{ + return true; +} + +bool venc_dev::venc_loaded_stop() +{ + return true; +} + +bool venc_dev::venc_loaded_start_done() +{ + return true; +} + +bool venc_dev::venc_loaded_stop_done() +{ + return true; +} + +bool venc_dev::venc_get_seq_hdr(void *buffer, + unsigned buffer_size, unsigned *header_len) +{ + return true; +} + +bool venc_dev::venc_get_buf_req(unsigned long *min_buff_count, + unsigned long *actual_buff_count, + unsigned long *buff_size, + unsigned long port) +{ + struct v4l2_format fmt; + struct v4l2_requestbuffers bufreq; + int ret; + if(port == 0) + { + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for getting i/p buffer requirement failed"); + return false; + } + + fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; + fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12; + ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt); + //printf(" \n VIDIOC_S_FMT OUTPUT Successful \n "); + m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage; + +bufreq.memory = V4L2_MEMORY_USERPTR; + bufreq.count = 2; + + bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq); + m_sInput_buff_property.mincount=m_sInput_buff_property.maxcount=m_sInput_buff_property.actualcount=bufreq.count; + + + *min_buff_count = m_sInput_buff_property.mincount; + *actual_buff_count = m_sInput_buff_property.actualcount; +#ifdef USE_ION + // For ION memory allocations of the allocated buffer size + // must be 4k aligned, hence aligning the input buffer + // size to 4k. + m_sInput_buff_property.datasize = (m_sInput_buff_property.datasize + 4095) + & (~4095); +#endif + *buff_size = m_sInput_buff_property.datasize; + } + else + { + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for getting o/p buffer requirement failed"); + return false; + } + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; + fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; + fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype; + + ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt); + //printf(" \n VIDIOC_S_FMT CAPTURE Successful \n "); + m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; + fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; + fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype; + + ret = ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt); + //printf(" \n VIDIOC_S_FMT CAPTURE Successful \n "); + m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage; + + + *min_buff_count = m_sOutput_buff_property.mincount; + *actual_buff_count = m_sOutput_buff_property.actualcount; + *buff_size = m_sOutput_buff_property.datasize; + } + + return true; + +} + +bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) +{ + DEBUG_PRINT_LOW("venc_set_param:: venc-720p\n"); + struct v4l2_format fmt; + struct v4l2_requestbuffers bufreq; + int ret; + switch(index) + { + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefn; + portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; + DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition\n"); + if(portDefn->nPortIndex == PORT_INDEX_IN) + { + if(!venc_set_color_format(portDefn->format.video.eColorFormat)) + { + return false; + } + if(m_sVenc_cfg.input_height != portDefn->format.video.nFrameHeight || + m_sVenc_cfg.input_width != portDefn->format.video.nFrameWidth) + { + DEBUG_PRINT_LOW("\n Basic parameter has changed"); + m_sVenc_cfg.input_height = portDefn->format.video.nFrameHeight; + m_sVenc_cfg.input_width = portDefn->format.video.nFrameWidth; + fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; + fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12; + ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt); + m_sInput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage; + bufreq.memory = V4L2_MEMORY_USERPTR; + bufreq.count = 2; + bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq); + if(ret) + printf("\n VIDIOC_REQBUFS OUTPUT_MPLANE Failed \n "); + m_sInput_buff_property.mincount=m_sInput_buff_property.maxcount=m_sInput_buff_property.actualcount=bufreq.count; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.height = m_sVenc_cfg.input_height; + fmt.fmt.pix_mp.width = m_sVenc_cfg.input_width; + fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype; + ret = ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt); + m_sOutput_buff_property.datasize=fmt.fmt.pix_mp.plane_fmt[0].sizeimage; + struct v4l2_requestbuffers bufreq; + bufreq.memory = V4L2_MEMORY_USERPTR; + bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + bufreq.count = 2; + ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq); + if(ret) + printf("\n VIDIOC_REQBUFS CAPTURE_MPLANE Failed \n "); + m_sOutput_buff_property.mincount=m_sOutput_buff_property.maxcount=m_sOutput_buff_property.actualcount=bufreq.count; + + } + } + else if(portDefn->nPortIndex == PORT_INDEX_OUT) + { + if(!venc_set_encode_framerate(portDefn->format.video.xFramerate, 0)) + { + return false; + } + + if(!venc_set_target_bitrate(portDefn->format.video.nBitrate, 0)) + { + return false; + } + + if( (portDefn->nBufferCountActual >= m_sOutput_buff_property.mincount) + && + (m_sOutput_buff_property.maxcount >= portDefn->nBufferCountActual) + && + (m_sOutput_buff_property.datasize == portDefn->nBufferSize) + ) + { + m_sOutput_buff_property.actualcount = portDefn->nBufferCountActual; + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: ioctl VEN_IOCTL_SET_OUTPUT_BUFFER_REQ failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Setting Output buffer requirements failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamPortDefinition"); + } + break; + } + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt; + portFmt =(OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; + DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoPortFormat\n"); + + if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) + { + if(!venc_set_color_format(portFmt->eColorFormat)) + { + return false; + } + } + else if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(!venc_set_encode_framerate(portFmt->xFramerate, 0)) + { + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoPortFormat"); + } + break; + } + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE* pParam; + pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData; + DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoBitrate\n"); + + if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(!venc_set_target_bitrate(pParam->nTargetBitrate, 0)) + { + DEBUG_PRINT_ERROR("\nERROR: Target Bit Rate setting failed"); + return false; + } + if(!venc_set_ratectrl_cfg(pParam->eControlRate)) + { + DEBUG_PRINT_ERROR("\nERROR: Rate Control setting failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoBitrate"); + } + break; + } + case OMX_IndexParamVideoMpeg4: + { + OMX_VIDEO_PARAM_MPEG4TYPE* pParam; + OMX_U32 bFrames = 0; + + pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData; + DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoMpeg4\n"); + if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(!venc_set_voptiming_cfg(pParam->nTimeIncRes)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting vop_timing failed"); + return false; + } + m_profile_set = false; + m_level_set = false; + if(!venc_set_profile_level (pParam->eProfile, pParam->eLevel)) + { + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating Profile and level"); + return false; + } + else { + if(pParam->eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) + { + if(pParam->nBFrames) + { + DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported"); + bFrames = 1; + } + } + else + { + if(pParam->nBFrames) + { + DEBUG_PRINT_ERROR("Warning: B frames not supported\n"); + bFrames = 0; + } + } + } + if(!venc_set_intra_period (pParam->nPFrames,bFrames)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + if(!venc_set_multislice_cfg(OMX_IndexParamVideoMpeg4,pParam->nSliceHeaderSpacing)) + { + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating slice_config"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoMpeg4"); + } + break; + } + case OMX_IndexParamVideoH263: + { + OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData; + DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoH263\n"); + OMX_U32 bFrames = 0; + if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + m_profile_set = false; + m_level_set = false; + if(!venc_set_profile_level (pParam->eProfile, pParam->eLevel)) + { + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating Profile and level"); + return false; + } + if (pParam->nBFrames) + DEBUG_PRINT_ERROR("\nWARNING: B frame not supported for H.263"); + + if(venc_set_intra_period (pParam->nPFrames, bFrames) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoH263"); + } + break; + } + case OMX_IndexParamVideoAvc: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoAvc\n"); + OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData; + OMX_U32 bFrames = 0; + + if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + DEBUG_PRINT_LOW("pParam->eProfile :%d ,pParam->eLevel %d\n", + pParam->eProfile,pParam->eLevel); + + m_profile_set = false; + m_level_set = false; + + if(!venc_set_profile_level (pParam->eProfile,pParam->eLevel)) + { + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating Profile and level %d, %d", + pParam->eProfile, pParam->eLevel); + return false; + } + else { + if(pParam->eProfile != OMX_VIDEO_AVCProfileBaseline) + { + if(pParam->nBFrames) + { + DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported"); + bFrames = 1; + } + } + else + { + if(pParam->nBFrames) + { + DEBUG_PRINT_ERROR("Warning: B frames not supported\n"); + bFrames = 0; + } + } + } + if(!venc_set_intra_period (pParam->nPFrames, bFrames)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + if(!venc_set_entropy_config (pParam->bEntropyCodingCABAC, pParam->nCabacInitIdc)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Entropy failed"); + return false; + } + if(!venc_set_inloop_filter (pParam->eLoopFilterMode)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Inloop filter failed"); + return false; + } + if(!venc_set_multislice_cfg(OMX_IndexParamVideoAvc, pParam->nSliceHeaderSpacing)) + { + DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating slice_config"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoAvc"); + } + //TBD, lot of other variables to be updated, yet to decide + break; + } + case OMX_IndexParamVideoIntraRefresh: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoIntraRefresh\n"); + OMX_VIDEO_PARAM_INTRAREFRESHTYPE *intra_refresh = + (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)paramData; + if(intra_refresh->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(venc_set_intra_refresh(intra_refresh->eRefreshMode, intra_refresh->nCirMBs) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Intra refresh failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoIntraRefresh"); + } + break; + } + case OMX_IndexParamVideoErrorCorrection: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoErrorCorrection\n"); + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *error_resilience = + (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)paramData; + if(error_resilience->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(venc_set_error_resilience(error_resilience) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Intra refresh failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoErrorCorrection"); + } + break; + } + case OMX_IndexParamVideoProfileLevelCurrent: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoProfileLevelCurrent\n"); + OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = + (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData; + if(profile_level->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + m_profile_set = false; + m_level_set = false; + if(!venc_set_profile_level (profile_level->eProfile, + profile_level->eLevel)) + { + DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating Profile and level"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoProfileLevelCurrent"); + } + break; + } + case OMX_IndexParamVideoQuantization: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoQuantization\n"); + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = + (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)paramData; + if(session_qp->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(venc_set_session_qp (session_qp->nQpI, + session_qp->nQpP, + session_qp->nQpB) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Session QP failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoQuantization"); + } + break; + } + case OMX_IndexParamVideoSliceFMO: + default: + DEBUG_PRINT_ERROR("\nERROR: Unsupported parameter in venc_set_param: %u", + index); + break; + //case + } + + return true; +} + +bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) +{ + + DEBUG_PRINT_LOW("\n Inside venc_set_config"); + + switch(index) + { + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *bit_rate = (OMX_VIDEO_CONFIG_BITRATETYPE *) + configData; + DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigVideoBitrate"); + if(bit_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) + { + if(venc_set_target_bitrate(bit_rate->nEncodeBitrate, 1) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Target Bit rate failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexConfigVideoBitrate"); + } + break; + } + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *frame_rate = (OMX_CONFIG_FRAMERATETYPE *) + configData; + DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigVideoFramerate"); + if(frame_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) + { + if(venc_set_encode_framerate(frame_rate->xEncodeFramerate, 1) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Encode Framerate failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate"); + } + break; + } + case QOMX_IndexConfigVideoIntraperiod: + { + DEBUG_PRINT_LOW("venc_set_param:QOMX_IndexConfigVideoIntraperiod\n"); + QOMX_VIDEO_INTRAPERIODTYPE *intraperiod = + (QOMX_VIDEO_INTRAPERIODTYPE *)configData; + if(intraperiod->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(venc_set_intra_period(intraperiod->nPFrames, intraperiod->nBFrames) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + } + break; + } + case OMX_IndexConfigVideoIntraVOPRefresh: + { + OMX_CONFIG_INTRAREFRESHVOPTYPE *intra_vop_refresh = (OMX_CONFIG_INTRAREFRESHVOPTYPE *) + configData; + DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigVideoIntraVOPRefresh"); + if(intra_vop_refresh->nPortIndex == (OMX_U32)PORT_INDEX_OUT) + { + if(venc_set_intra_vop_refresh(intra_vop_refresh->IntraRefreshVOP) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Encode Framerate failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate"); + } + break; + } + case OMX_IndexConfigCommonRotate: + { + OMX_CONFIG_ROTATIONTYPE *config_rotation = + reinterpret_cast(configData); + OMX_U32 nFrameWidth; + + DEBUG_PRINT_HIGH("\nvenc_set_config: updating the new Dims"); + nFrameWidth = m_sVenc_cfg.input_width; + m_sVenc_cfg.input_width = m_sVenc_cfg.input_height; + m_sVenc_cfg.input_height = nFrameWidth; + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < */0) { + DEBUG_PRINT_ERROR("\nERROR: Dimension Change for Rotation failed"); + return false; + } + break; + } + default: + DEBUG_PRINT_ERROR("\n Unsupported config index = %u", index); + break; + } + + return true; +} + +unsigned venc_dev::venc_stop( void) +{ + pmem_free(); + return 0; +} + +unsigned venc_dev::venc_pause(void) +{ + return 0; +} + +unsigned venc_dev::venc_resume(void) +{ + return 0; +} + +unsigned venc_dev::venc_start_done(void) +{ + struct venc_msg venc_msg; + venc_msg.msgcode=VEN_MSG_START; + venc_msg.statuscode=VEN_S_SUCCESS; + venc_handle->async_message_process(venc_handle,&venc_msg); + return 0; +} + +unsigned venc_dev::venc_stop_done(void) +{ + struct venc_msg venc_msg; + venc_msg.msgcode=VEN_MSG_STOP; + venc_msg.statuscode=VEN_S_SUCCESS; + venc_handle->async_message_process(venc_handle,&venc_msg); + return 0; +} + +unsigned venc_dev::venc_start(void) +{ + enum v4l2_buf_type buf_type; + int ret,r; + DEBUG_PRINT_HIGH("\n %s(): Check Profile/Level set in driver before start", + __func__); + if (!venc_set_profile_level(0, 0)) + { + DEBUG_PRINT_ERROR("\n ERROR: %s(): Driver Profile/Level is NOT SET", + __func__); + } + else + { + DEBUG_PRINT_HIGH("\n %s(): Driver Profile[%lu]/Level[%lu] successfully SET", + __func__, codec_profile.profile, profile_level.level); + } + venc_config_print(); + + + if((codec_profile.profile == V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE) || + (codec_profile.profile == V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) || + (codec_profile.profile == VEN_PROFILE_H263_BASELINE)) + recon_buffers_count = MAX_RECON_BUFFERS - 2; + else + recon_buffers_count = MAX_RECON_BUFFERS; + + buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n"); + + ret=ioctl(m_nDriver_fd, VIDIOC_STREAMON,&buf_type); + + if (ret) { + return -1; + } + else { + return 0; + } +} + +OMX_U32 venc_dev::pmem_allocate(OMX_U32 size, OMX_U32 alignment, OMX_U32 count) +{ + OMX_U32 pmem_fd = -1; + OMX_U32 width, height; + void *buf_addr = NULL; + struct venc_recon_addr recon_addr; + int rc = 0; +#ifndef USE_ION + struct pmem_allocation allocation; +#endif + +#ifdef USE_ION + recon_buff[count].ion_device_fd = open (MEM_DEVICE,O_RDONLY|O_DSYNC); + if(recon_buff[count].ion_device_fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: ION Device open() Failed"); + return -1; + } + + recon_buff[count].alloc_data.len = size; + recon_buff[count].alloc_data.flags = 0x1 << MEM_HEAP_ID; + recon_buff[count].alloc_data.align = clip2(alignment); + if (recon_buff[count].alloc_data.align != 8192) + recon_buff[count].alloc_data.align = 8192; + + rc = ioctl(recon_buff[count].ion_device_fd,ION_IOC_ALLOC,&recon_buff[count].alloc_data); + if(rc || !recon_buff[count].alloc_data.handle) { + DEBUG_PRINT_ERROR("\n ION ALLOC memory failed "); + recon_buff[count].alloc_data.handle=NULL; + return -1; + } + + recon_buff[count].ion_alloc_fd.handle = recon_buff[count].alloc_data.handle; + rc = ioctl(recon_buff[count].ion_device_fd,ION_IOC_MAP,&recon_buff[count].ion_alloc_fd); + if(rc) { + DEBUG_PRINT_ERROR("\n ION MAP failed "); + recon_buff[count].ion_alloc_fd.fd =-1; + recon_buff[count].ion_alloc_fd.fd =-1; + return -1; + } + pmem_fd = recon_buff[count].ion_alloc_fd.fd; +#else + pmem_fd = open(MEM_DEVICE, O_RDWR); + + if ((int)(pmem_fd) < 0) + { + DEBUG_PRINT_ERROR("\n Failed to get an pmem handle"); + return -1; + } + + allocation.size = size; + allocation.align = clip2(alignment); + + if (allocation.align != 8192) + allocation.align = 8192; + + if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) + { + DEBUG_PRINT_ERROR("\n Aligment(%u) failed with pmem driver Sz(%lu)", + allocation.align, allocation.size); + return -1; + } +#endif + buf_addr = mmap(NULL, size, + PROT_READ | PROT_WRITE, + MAP_SHARED, pmem_fd, 0); + + if (buf_addr == (void*) MAP_FAILED) + { + close(pmem_fd); + pmem_fd = -1; + DEBUG_PRINT_ERROR("Error returned in allocating recon buffers buf_addr: %p\n",buf_addr); +#ifdef USE_ION + if(ioctl(recon_buff[count].ion_device_fd,ION_IOC_FREE, + &recon_buff[count].alloc_data.handle)) { + DEBUG_PRINT_ERROR("ion recon buffer free failed"); + } + recon_buff[count].alloc_data.handle = NULL; + recon_buff[count].ion_alloc_fd.fd =-1; + close(recon_buff[count].ion_device_fd); + recon_buff[count].ion_device_fd =-1; +#endif + return -1; + } + + DEBUG_PRINT_HIGH("\n Allocated virt:%p, FD: %d of size %d \n", buf_addr, pmem_fd, size); + + recon_addr.buffer_size = size; + recon_addr.pmem_fd = pmem_fd; + recon_addr.offset = 0; + recon_addr.pbuffer = (unsigned char *)buf_addr; + + + if (/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_RECON_BUFFER, (void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("Failed to set the Recon_buffers\n"); + return -1; + } + + recon_buff[count].virtual_address = (unsigned char *) buf_addr; + recon_buff[count].size = size; + recon_buff[count].offset = 0; + recon_buff[count].pmem_fd = pmem_fd; + + DEBUG_PRINT_ERROR("\n Allocated virt:%p, FD: %d of size %d at index: %d\n", recon_buff[count].virtual_address, + recon_buff[count].pmem_fd, recon_buff[count].size, count); + return 0; +} + +OMX_U32 venc_dev::pmem_free() +{ + int cnt = 0; + struct venc_recon_addr recon_addr; + for (cnt = 0; cnt < recon_buffers_count; cnt++) + { + if(recon_buff[cnt].pmem_fd) + { + recon_addr.pbuffer = recon_buff[cnt].virtual_address; + recon_addr.offset = recon_buff[cnt].offset; + recon_addr.pmem_fd = recon_buff[cnt].pmem_fd; + recon_addr.buffer_size = recon_buff[cnt].size; + if(/*ioctl(m_nDriver_fd, VEN_IOCTL_FREE_RECON_BUFFER ,&ioctl_msg) < */0) + DEBUG_PRINT_ERROR("VEN_IOCTL_FREE_RECON_BUFFER failed"); + munmap(recon_buff[cnt].virtual_address, recon_buff[cnt].size); + close(recon_buff[cnt].pmem_fd); +#ifdef USE_ION + if(ioctl(recon_buff[cnt].ion_device_fd,ION_IOC_FREE, + &recon_buff[cnt].alloc_data.handle)) { + DEBUG_PRINT_ERROR("ion recon buffer free failed"); + } + recon_buff[cnt].alloc_data.handle = NULL; + recon_buff[cnt].ion_alloc_fd.fd =-1; + close(recon_buff[cnt].ion_device_fd); + recon_buff[cnt].ion_device_fd =-1; +#endif + DEBUG_PRINT_LOW("\n cleaning Index %d of size %d \n",cnt,recon_buff[cnt].size); + recon_buff[cnt].pmem_fd = -1; + recon_buff[cnt].virtual_address = NULL; + recon_buff[cnt].offset = 0; + recon_buff[cnt].alignment = 0; + recon_buff[cnt].size = 0; + } + } + return 0; +} +void venc_dev::venc_config_print() +{ + + DEBUG_PRINT_HIGH("\nENC_CONFIG: Codec: %d, Profile %d, level : %d", + m_sVenc_cfg.codectype, codec_profile.profile, profile_level.level); + + DEBUG_PRINT_HIGH("\n ENC_CONFIG: Width: %d, Height:%d, Fps: %d", + m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, + m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: Bitrate: %d, RC: %d, I-Period: %d", + bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: qpI: %d, qpP: %d, qpb: %d", + session_qp.iframeqp, session_qp.pframqp,session_qp.bframqp); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: VOP_Resolution: %d, Slice-Mode: %d, Slize_Size: %d", + voptimecfg.voptime_resolution, multislice.mslice_mode, + multislice.mslice_size); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: EntropyMode: %d, CabacModel: %d", + entropy.longentropysel, entropy.cabacmodel); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: DB-Mode: %d, alpha: %d, Beta: %d\n", + dbkfilter.db_mode, dbkfilter.slicealpha_offset, + dbkfilter.slicebeta_offset); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: IntraMB/Frame: %d, HEC: %d\n", + intra_refresh.mbcount, hec.header_extension); +} + +unsigned venc_dev::venc_flush( unsigned port) +{ + struct venc_bufferflush buffer_index; + + if(port == PORT_INDEX_IN) + { + int rc=0; + enum v4l2_buf_type btype; + btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + rc = ioctl(m_nDriver_fd, VIDIOC_STREAMOFF, &btype); + if (rc) { + /* STREAMOFF should never fail */ + DEBUG_PRINT_ERROR("\n Failed to call streamoff on OUTPUT Port \n"); + return -1; + } + + return 0; + } + else if(port == PORT_INDEX_OUT) + { + int rc=0; + enum v4l2_buf_type btype; + btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + rc = ioctl(m_nDriver_fd, VIDIOC_STREAMOFF, &btype); + if (rc) { + /* STREAMOFF should never fail */ + DEBUG_PRINT_ERROR("\n Failed to call streamoff on OUTPUT Port \n"); + return -1; + } + + return 0; + + } + else + { + return -1; + } +} + +//allocating I/P memory from pmem and register with the device + + +bool venc_dev::venc_use_buf(void *buf_addr, unsigned port,unsigned index) +{ + + struct pmem *pmem_tmp; + + struct v4l2_buffer buf; + struct v4l2_plane plane; + int rc=0; + + pmem_tmp = (struct pmem *)buf_addr; + + DEBUG_PRINT_LOW("\n venc_use_buf:: pmem_tmp = %p", pmem_tmp); + + if(port == PORT_INDEX_IN) + { + + buf.index = index; + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + plane.length = pmem_tmp->size; + plane.m.userptr = (unsigned long)pmem_tmp->buffer; + plane.reserved[0] = pmem_tmp->fd; + plane.reserved[1] = 0; + plane.data_offset = pmem_tmp->offset; + buf.m.planes = &plane; + buf.length = 1; + + + rc = ioctl(m_nDriver_fd, VIDIOC_PREPARE_BUF, &buf); + + if (rc) { + DEBUG_PRINT_ERROR("VIDIOC_PREPARE_BUF Failed\n"); + } + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER,&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: venc_use_buf:set input buffer failed "); + return false; + } + } + else if(port == PORT_INDEX_OUT) + { + + buf.index = index; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + plane.length = pmem_tmp->size; + plane.m.userptr = (unsigned long)pmem_tmp->buffer; + plane.reserved[0] = pmem_tmp->fd; + plane.reserved[1] = 0; + plane.data_offset = pmem_tmp->offset; + buf.m.planes = &plane; + buf.length = 1; + + rc = ioctl(m_nDriver_fd, VIDIOC_PREPARE_BUF, &buf); + + if (rc) { + DEBUG_PRINT_ERROR("VIDIOC_PREPARE_BUF Failed\n"); + } + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER,&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: venc_use_buf:set output buffer failed "); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: venc_use_buf:Invalid Port Index "); + return false; + } + + return true; +} + +bool venc_dev::venc_free_buf(void *buf_addr, unsigned port) +{ + struct pmem *pmem_tmp; + struct venc_bufferpayload dev_buffer = {0}; + + pmem_tmp = (struct pmem *)buf_addr; + + DEBUG_PRINT_LOW("\n venc_use_buf:: pmem_tmp = %p", pmem_tmp); + + if(port == PORT_INDEX_IN) + { + dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; + dev_buffer.fd = pmem_tmp->fd; + dev_buffer.maped_size = pmem_tmp->size; + dev_buffer.sz = pmem_tmp->size; + dev_buffer.offset = pmem_tmp->offset; + DEBUG_PRINT_LOW("\n venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ + dev_buffer.pbuffer, \ + dev_buffer.fd, \ + dev_buffer.offset, \ + dev_buffer.maped_size); + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FREE_INPUT_BUFFER,&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: venc_free_buf: free input buffer failed "); + return false; + } + } + else if(port == PORT_INDEX_OUT) + { + dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; + dev_buffer.fd = pmem_tmp->fd; + dev_buffer.sz = pmem_tmp->size; + dev_buffer.maped_size = pmem_tmp->size; + dev_buffer.offset = pmem_tmp->offset; + + DEBUG_PRINT_LOW("\n venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ + dev_buffer.pbuffer, \ + dev_buffer.fd, \ + dev_buffer.offset, \ + dev_buffer.maped_size); + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FREE_OUTPUT_BUFFER,&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: venc_free_buf: free output buffer failed "); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: venc_free_buf:Invalid Port Index "); + return false; + } + + return true; +} + +bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf,unsigned index,unsigned fd) +{ + struct pmem *temp_buffer; + + struct v4l2_buffer buf = {0}; + struct v4l2_plane plane = {0}; + int rc=0; + struct OMX_BUFFERHEADERTYPE *bufhdr; + + temp_buffer = (struct pmem *)buffer; + + + if(buffer == NULL) + { + DEBUG_PRINT_ERROR("\nERROR: venc_etb: buffer is NULL"); + return false; + } + bufhdr = (OMX_BUFFERHEADERTYPE *)buffer; + +DEBUG_PRINT_LOW("\n Input buffer length %d",bufhdr->nFilledLen); + + if(pmem_data_buf) + { + DEBUG_PRINT_LOW("\n Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf); + plane.m.userptr = (unsigned long)pmem_data_buf; + } + else + { + DEBUG_PRINT_LOW("\n Shared PMEM addr for i/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer); + plane.m.userptr = (unsigned long)bufhdr->pBuffer; + } + + buf.index = index; + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + plane.length = bufhdr->nAllocLen; + plane.bytesused = bufhdr->nFilledLen; + plane.reserved[0] = fd; + plane.reserved[1] = 0; + plane.data_offset = bufhdr->nOffset; + buf.m.planes = &plane; + buf.length = 1; + buf.flags = bufhdr->nFlags; + buf.timestamp.tv_usec=bufhdr->nTimeStamp; + + rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf); + if (rc) { + DEBUG_PRINT_ERROR("Failed to qbuf (etb) to driver"); + return false; + } + + etb_count++; + + if(etb_count == 1) + { + enum v4l2_buf_type buf_type; + buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + int ret; + ret = ioctl(m_nDriver_fd, VIDIOC_STREAMON, &buf_type); + if (ret) { + DEBUG_PRINT_ERROR("Failed to call streamon\n"); + } + + } + + if(/*ioctl(m_nDriver_fd,VEN_IOCTL_CMD_ENCODE_FRAME,&ioctl_msg) < */0) + { + /*Generate an async error and move to invalid state*/ + return false; + } +#ifdef INPUT_BUFFER_LOG + + int y_size = 0; + int c_offset = 0; + + y_size = m_sVenc_cfg.input_width * m_sVenc_cfg.input_height; + //chroma offset is y_size aligned to the 2k boundary + c_offset= (y_size + 2047) & (~(2047)); + + if(inputBufferFile1) + { + fwrite((const char *)frameinfo.ptrbuffer, y_size, 1,inputBufferFile1); + fwrite((const char *)(frameinfo.ptrbuffer + c_offset), (y_size>>1), 1,inputBufferFile1); + } +#endif + + return true; +} +bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf,unsigned index,unsigned fd) +{ + + struct pmem *temp_buffer = NULL; + struct venc_buffer frameinfo; + struct v4l2_buffer buf; + struct v4l2_plane plane; + int rc=0; + struct OMX_BUFFERHEADERTYPE *bufhdr; + + if(buffer == NULL) + { + return false; + } + bufhdr = (OMX_BUFFERHEADERTYPE *)buffer; + +if(pmem_data_buf) + { + DEBUG_PRINT_LOW("\n Internal PMEM addr for o/p Heap UseBuf: %p", pmem_data_buf); + plane.m.userptr = (unsigned long)pmem_data_buf; + } + else + { + DEBUG_PRINT_LOW("\n Shared PMEM addr for o/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer); + plane.m.userptr = (unsigned long)bufhdr->pBuffer; + } + + buf.index = index; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + plane.length = bufhdr->nAllocLen; + plane.bytesused = bufhdr->nFilledLen; + plane.reserved[0] = fd; + plane.reserved[1] = 0; + plane.data_offset = bufhdr->nOffset; + buf.m.planes = &plane; + buf.length = 1; + + rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf); + if (rc) { + DEBUG_PRINT_ERROR("Failed to qbuf (ftb) to driver"); + return false; + } + + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER,&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: ioctl VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER failed"); + return false; + } + + return true; +} + +bool venc_dev::venc_set_session_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp,OMX_U32 b_frame_qp) +{ + int rc; + struct v4l2_control control; + + control.id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP; + control.value = i_frame_qp; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + session_qp.iframeqp = control.value; + + control.id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP; + control.value = p_frame_qp; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + + session_qp.pframqp = control.value; + + if((codec_profile.profile == V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) || + (codec_profile.profile == V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)) + { + + control.id = V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP; + control.value = b_frame_qp; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + + session_qp.bframqp = control.value; + } + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_SESSION_QP,(void*)&ioctl_msg)< */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting session qp failed"); + return false; + } + return true; +} + +bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel) +{ + struct venc_profile requested_profile = {0}; + struct ven_profilelevel requested_level = {0}; + unsigned const int *profile_tbl = NULL; + unsigned long mb_per_frame = 0, mb_per_sec = 0; + DEBUG_PRINT_LOW("venc_set_profile_level:: eProfile = %d, Level = %d", + eProfile, eLevel); + mb_per_frame = ((m_sVenc_cfg.input_height + 15) >> 4)* + ((m_sVenc_cfg.input_width + 15) >> 4); + if((eProfile == 0) && (eLevel == 0) && m_profile_set && m_level_set) + { + DEBUG_PRINT_LOW("\n Profile/Level setting complete before venc_start"); + return true; + } + + DEBUG_PRINT_LOW("\n Validating Profile/Level from table"); + if(!venc_validate_profile_level(&eProfile, &eLevel)) + { + DEBUG_PRINT_LOW("\nERROR: Profile/Level validation failed"); + return false; + } + + if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4) + { + DEBUG_PRINT_LOW("eProfile = %d, OMX_VIDEO_MPEG4ProfileSimple = %d and " + "OMX_VIDEO_MPEG4ProfileAdvancedSimple = %d", eProfile, + OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4ProfileAdvancedSimple); + if(eProfile == OMX_VIDEO_MPEG4ProfileSimple) + { + requested_profile.profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE; + profile_tbl = (unsigned int const *) + (&mpeg4_profile_level_table[MPEG4_SP_START]); + profile_tbl += MPEG4_720P_LEVEL*5; + } + else if(eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) + { + requested_profile.profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE; + profile_tbl = (unsigned int const *) + (&mpeg4_profile_level_table[MPEG4_ASP_START]); + profile_tbl += MPEG4_720P_LEVEL*5; + } + else + { + DEBUG_PRINT_LOW("\nERROR: Unsupported MPEG4 profile = %u", + eProfile); + return false; + } + + DEBUG_PRINT_LOW("eLevel = %d, OMX_VIDEO_MPEG4Level0 = %d, OMX_VIDEO_MPEG4Level1 = %d," + "OMX_VIDEO_MPEG4Level2 = %d, OMX_VIDEO_MPEG4Level3 = %d, OMX_VIDEO_MPEG4Level4 = %d," + "OMX_VIDEO_MPEG4Level5 = %d", eLevel, OMX_VIDEO_MPEG4Level0, OMX_VIDEO_MPEG4Level1, + OMX_VIDEO_MPEG4Level2, OMX_VIDEO_MPEG4Level3, OMX_VIDEO_MPEG4Level4, OMX_VIDEO_MPEG4Level5); + + if(mb_per_frame >= 3600) + { + if(requested_profile.profile == V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE) + requested_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5; + if(requested_profile.profile == V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE) + requested_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5; + } + else + { + switch(eLevel) + { + case OMX_VIDEO_MPEG4Level0: + requested_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0; + break; + case OMX_VIDEO_MPEG4Level0b: + requested_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B; + break; + case OMX_VIDEO_MPEG4Level1: + requested_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_1; + break; + case OMX_VIDEO_MPEG4Level2: + requested_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_2; + break; + case OMX_VIDEO_MPEG4Level3: + requested_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_3; + break; + case OMX_VIDEO_MPEG4Level4a: + requested_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_4; + break; + case OMX_VIDEO_MPEG4Level5: + mb_per_sec = mb_per_frame * (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den); + if((requested_profile.profile == V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE) && (mb_per_frame >= profile_tbl[0]) && + (mb_per_sec >= profile_tbl[1])) + { + DEBUG_PRINT_LOW("\nMPEG4 Level 6 is set for 720p resolution"); + requested_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5; + } + else + { + DEBUG_PRINT_LOW("\nMPEG4 Level 5 is set for non-720p resolution"); + requested_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5; + } + break; + default: + return false; + // TODO update corresponding levels for MPEG4_LEVEL_3b,MPEG4_LEVEL_6 + break; + } + } + } + else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263) + { + + switch (eProfile) { + case OMX_VIDEO_H263ProfileBaseline: + requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE; + break; + case OMX_VIDEO_H263ProfileH320Coding: + requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_H320CODING; + break; + case OMX_VIDEO_H263ProfileBackwardCompatible: + requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BACKWARDCOMPATIBLE; + break; + case OMX_VIDEO_H263ProfileISWV2: + requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV2; + break; + case OMX_VIDEO_H263ProfileISWV3: + requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV3; + break; + case OMX_VIDEO_H263ProfileHighCompression: + requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHCOMPRESSION; + break; + case OMX_VIDEO_H263ProfileInternet: + requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERNET; + break; + case OMX_VIDEO_H263ProfileInterlace: + requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERLACE; + break; + case OMX_VIDEO_H263ProfileHighLatency: + requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY; + break; + default: + DEBUG_PRINT_LOW("\nERROR: Unsupported H.263 profile = %u", + requested_profile.profile); + return false; + } + //profile level + switch(eLevel) + { + case OMX_VIDEO_H263Level10: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0; + break; + case OMX_VIDEO_H263Level20: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_2_0; + break; + case OMX_VIDEO_H263Level30: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_3_0; + break; + case OMX_VIDEO_H263Level40: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_0; + break; + case OMX_VIDEO_H263Level45: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_5; + break; + case OMX_VIDEO_H263Level50: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_5_0; + break; + case OMX_VIDEO_H263Level60: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_6_0; + break; + case OMX_VIDEO_H263Level70: + requested_level.level = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0; + break; + default: + return false; + break; + } + } + else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) + { + if(eProfile == OMX_VIDEO_AVCProfileBaseline) + { + requested_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE; + } + else if(eProfile == OMX_VIDEO_AVCProfileMain) + { + requested_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN; + } + else if(eProfile == OMX_VIDEO_AVCProfileExtended) + { + requested_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED; + } + else if(eProfile == OMX_VIDEO_AVCProfileHigh) + { + requested_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH; + } + else if(eProfile == OMX_VIDEO_AVCProfileHigh10) + { + requested_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10; + } + else if(eProfile == OMX_VIDEO_AVCProfileHigh422) + { + requested_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422; + } + else if(eProfile == OMX_VIDEO_AVCProfileHigh444) + { + requested_profile.profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE; + } + else + { + DEBUG_PRINT_LOW("\nERROR: Unsupported H.264 profile = %u", + requested_profile.profile); + return false; + } + //profile level + switch(eLevel) + { + case OMX_VIDEO_AVCLevel1: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_1_0; + break; + case OMX_VIDEO_AVCLevel1b: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_1B; + break; + case OMX_VIDEO_AVCLevel11: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_1_1; + break; + case OMX_VIDEO_AVCLevel12: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_1_2; + break; + case OMX_VIDEO_AVCLevel13: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_1_3; + break; + case OMX_VIDEO_AVCLevel2: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_2_0; + break; + case OMX_VIDEO_AVCLevel21: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_2_1; + break; + case OMX_VIDEO_AVCLevel22: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_2_2; + break; + case OMX_VIDEO_AVCLevel3: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_3_0; + break; + case OMX_VIDEO_AVCLevel31: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_3_1; + break; + case OMX_VIDEO_AVCLevel32: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_3_2; + break; + case OMX_VIDEO_AVCLevel4: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; + break; + case OMX_VIDEO_AVCLevel41: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_4_1; + break; + case OMX_VIDEO_AVCLevel42: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_4_2; + break; + case OMX_VIDEO_AVCLevel5: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_5_0; + break; + case OMX_VIDEO_AVCLevel51: + requested_level.level = V4L2_MPEG_VIDEO_H264_LEVEL_5_1; + break; + default : + DEBUG_PRINT_ERROR("\nERROR: Unsupported H.264 level= %u", + requested_level.level); + return false; + break; + } + } + if(!m_profile_set) + { + int rc; + struct v4l2_control control; + if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { + control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE; + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4) { + control.id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE; + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263) { + control.id = V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE; + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) { + DEBUG_PRINT_ERROR("\n No Profile and LEVEL Setting for VP8 \n"); + m_profile_set = true; + m_level_set = true; + return true; + } else { + DEBUG_PRINT_ERROR("\n Wrong CODEC \n"); + return false; + } + + control.value = requested_profile.profile; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_CODEC_PROFILE,(void*)&ioctl_msg)< */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting profile failed"); + return false; + } + codec_profile.profile = control.value; + m_profile_set = true; + } + + if(!m_level_set) + { + int rc; + struct v4l2_control control; + if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { + control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL; + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4) { + control.id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL; + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263) { + control.id = V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL; + } else { + DEBUG_PRINT_ERROR("\n Wrong CODEC \n"); + return false; + } + + control.value = requested_level.level; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_PROFILE_LEVEL,(void*)&ioctl_msg)< */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting profile level failed"); + return false; + } + profile_level.level = control.value; + m_level_set = true; + } + + return true; +} + +bool venc_dev::venc_set_voptiming_cfg( OMX_U32 TimeIncRes) +{ + + struct venc_voptimingcfg vop_timing_cfg; + + DEBUG_PRINT_LOW("\n venc_set_voptiming_cfg: TimeRes = %u", + TimeIncRes); + + vop_timing_cfg.voptime_resolution = TimeIncRes; + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_VOP_TIMING_CFG,(void*)&ioctl_msg)< */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Vop Timing failed"); + return false; + } + + voptimecfg.voptime_resolution = vop_timing_cfg.voptime_resolution; + return true; +} + +bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames) +{ + + DEBUG_PRINT_LOW("\n venc_set_intra_period: nPFrames = %u", + nPFrames); + int rc; + struct v4l2_control control; + if((codec_profile.profile != V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE) && + (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) && + (codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)) + { + nBFrames=0; + } + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES; + control.value = nPFrames; + + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + + intra_period.num_pframes = control.value; + control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES; + control.value = nBFrames; + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_INTRA_PERIOD,(void*)&ioctl_msg)< */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + intra_period.num_bframes = control.value; + return true; +} + +bool venc_dev::venc_set_entropy_config(OMX_BOOL enable, OMX_U32 i_cabac_level) +{ + //struct venc_entropycfg entropy_cfg; + + // memset(&entropy_cfg,0,sizeof(entropy_cfg)); + int rc; + struct v4l2_control control; + + DEBUG_PRINT_LOW("\n venc_set_entropy_config: CABAC = %u level: %u", enable, i_cabac_level); + + if(enable &&(codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE)){ + + control.value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC; + control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + entropy.longentropysel = control.value; + if (i_cabac_level == 0) { + control.value = V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_0; + } + else if (i_cabac_level == 1) { + control.value = V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_1; + } + else if (i_cabac_level == 2) { + control.value = V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_2; + } + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL; + //control.value = entropy_cfg.cabacmodel; + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + entropy.longentropysel=control.value; + } + else if(!enable){ + control.value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC; + control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE; + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + entropy.longentropysel=control.value; + //entropy_cfg.longentropysel = control.value; + } + else{ + DEBUG_PRINT_ERROR("\nInvalid Entropy mode for Baseline Profile"); + return false; + } + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_ENTROPY_CFG,(void*)&ioctl_msg)< */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting entropy config failed"); + return false; + } + //entropy.longentropysel = entropy_cfg.longentropysel; + //entropy.cabacmodel = entropy_cfg.cabacmodel; + return true; +} + +bool venc_dev::venc_set_multislice_cfg(OMX_INDEXTYPE Codec, OMX_U32 nSlicesize) // MB +{ + int rc; + struct v4l2_control control; + bool status = true; + //struct venc_multiclicecfg multislice_cfg; + + if((Codec != OMX_IndexParamVideoH263) && (nSlicesize)){ + // multislice_cfg.mslice_mode = VEN_MSLICE_CNT_MB; + //multislice_cfg.mslice_size = nSlicesize; + control.value = V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB; + } + else{ + control.value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE; + //multislice_cfg.mslice_mode = VEN_MSLICE_OFF; + //multislice_cfg.mslice_size = 0; + } + control.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE; + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + multislice.mslice_mode=control.value; + + if(multislice.mslice_mode!=V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE){ + + control.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB; + control.value = nSlicesize; + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + multislice.mslice_size=control.value; + + } + + + if(/*ioctl (m_nDriver_fd, VEN_IOCTL_SET_MULTI_SLICE_CFG,(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting multi-slice cfg failed"); + status = false; + } + else + { + //multislice.mslice_mode = multislice_cfg.mslice_mode; + //multislice.mslice_size = nSlicesize; + } + return status; +} + +bool venc_dev::venc_set_intra_refresh(OMX_VIDEO_INTRAREFRESHTYPE ir_mode, OMX_U32 irMBs) +{ + bool status = true; + int rc; + struct v4l2_control control_mode,control_mbs; + control_mode.id = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE; + // There is no disabled mode. Disabled mode is indicated by a 0 count. + if (irMBs == 0 || ir_mode == OMX_VIDEO_IntraRefreshMax) + { + control_mode.value = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_NONE; + } + else if ((ir_mode == OMX_VIDEO_IntraRefreshCyclic) && + (irMBs < ((m_sVenc_cfg.input_width * m_sVenc_cfg.input_height)>>8))) + { + control_mode.value = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_CYCLIC; + control_mbs.id=V4L2_CID_MPEG_VIDC_VIDEO_CIR_MBS; + control_mbs.value=irMBs; + } + else if ((ir_mode == OMX_VIDEO_IntraRefreshAdaptive) && + (irMBs < ((m_sVenc_cfg.input_width * m_sVenc_cfg.input_height)>>8))) + { + control_mode.value = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_ADAPTIVE; + control_mbs.id=V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS; + control_mbs.value=irMBs; + } + else if ((ir_mode == OMX_VIDEO_IntraRefreshBoth) && + (irMBs < ((m_sVenc_cfg.input_width * m_sVenc_cfg.input_height)>>8))) + { + control_mode.value = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_CYCLIC_ADAPTIVE; + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid IntraRefresh Parameters:" + "mb count: %d, mb mode:%d", irMBs, ir_mode); + return false; + } + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control_mode.id, control_mode.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control_mode); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control_mode.id, control_mode.value); + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control_mbs.id, control_mbs.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control_mbs); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control_mbs.id, control_mbs.value); + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_INTRA_REFRESH,(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Intra Refresh failed"); + status = false; + } + else + { + intra_refresh.irmode = control_mode.value; + intra_refresh.mbcount = control_mbs.value; + } + return status; +} + +bool venc_dev::venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* error_resilience) +{ + bool status = true; + struct venc_headerextension hec_cfg; + struct venc_multiclicecfg multislice_cfg; + int rc; + struct v4l2_control control; + if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4) { + if (error_resilience->bEnableHEC) { + hec_cfg.header_extension = 1; + } + else { + hec_cfg.header_extension = 0; + } + + if (/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_HEC,(void*)&ioctl_msg) < */0) { + DEBUG_PRINT_ERROR("\nERROR: Request for setting HEader Error correction failed"); + return false; + } + hec.header_extension = error_resilience->bEnableHEC; + } + + if (error_resilience->bEnableRVLC) { + DEBUG_PRINT_ERROR("\n RVLC is not Supported"); + return false; + } + + if (( m_sVenc_cfg.codectype != V4L2_PIX_FMT_H263) && + (error_resilience->bEnableDataPartitioning)) { + DEBUG_PRINT_ERROR("\n DataPartioning are not Supported for MPEG4/H264"); + return false; + } + + if (( m_sVenc_cfg.codectype != V4L2_PIX_FMT_H263) && + (error_resilience->nResynchMarkerSpacing)) { + multislice_cfg.mslice_mode = VEN_MSLICE_CNT_BYTE; + multislice_cfg.mslice_size = error_resilience->nResynchMarkerSpacing; + } + else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263 && + error_resilience->bEnableDataPartitioning) { + multislice_cfg.mslice_mode = VEN_MSLICE_GOB; + multislice_cfg.mslice_size = 0; + } + else { + multislice_cfg.mslice_mode = VEN_MSLICE_OFF; + multislice_cfg.mslice_size = 0; + } + DEBUG_PRINT_LOW("\n %s(): mode = %u, size = %u", __func__, multislice_cfg.mslice_mode, + multislice_cfg.mslice_size); + if(error_resilience->nResynchMarkerSpacing) { + control.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE; + control.value = V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES; + printf("Calling IOCTL set control for id=%x, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + printf("Failed to set Slice mode control\n"); + return false; + } + printf("Success IOCTL set control for id=%x, value=%d\n", control.id, control.value); + multislice.mslice_mode=control.value; + + control.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES; + control.value = error_resilience->nResynchMarkerSpacing; + printf("Calling IOCTL set control for id=%x, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + printf("Failed to set MAX MB control\n"); + return false; + } + printf("Success IOCTL set control for id=%x, value=%d\n", control.id, control.value); + } + if (/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_MULTI_SLICE_CFG,(void*)&ioctl_msg) < */0) { + DEBUG_PRINT_ERROR("\nERROR: Request for setting multi-slice cfg failed"); + status = false; + } + else + { + multislice.mslice_mode = multislice_cfg.mslice_mode ; + multislice.mslice_size = multislice_cfg.mslice_size; + + } + return status; +} + +bool venc_dev::venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loopfilter) +{ + int rc; + struct v4l2_control control; + control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE; + if (loopfilter == OMX_VIDEO_AVCLoopFilterEnable){ + control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED; + } + else if(loopfilter == OMX_VIDEO_AVCLoopFilterDisable){ + control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED; + } + else if(loopfilter == OMX_VIDEO_AVCLoopFilterDisableSliceBoundary){ + control.value=V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY; + } + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + + dbkfilter.db_mode=control.value; + + control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA; + control.value=0; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + control.id=V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA; + control.value=0; + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_DEBLOCKING_CFG,(void*)&ioctl_msg)< */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting inloop filter failed"); + return false; + } + + dbkfilter.slicealpha_offset = dbkfilter.slicebeta_offset = 0; + return true; +} + +bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate, OMX_U32 config) +{ + DEBUG_PRINT_LOW("\n venc_set_target_bitrate: bitrate = %u", + nTargetBitrate); + struct v4l2_control control; + int rc; + control.id = V4L2_CID_MPEG_VIDEO_BITRATE; + control.value = nTargetBitrate/1000; + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_TARGET_BITRATE,(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting bit rate failed"); + return false; + } + m_sVenc_cfg.targetbitrate = control.value*1000; + bitrate.target_bitrate = control.value*1000; + if(!config) + { + m_level_set = false; + if(venc_set_profile_level(0, 0)) + { + DEBUG_PRINT_HIGH("Calling set level (Bitrate) with %d\n",profile_level.level); + } + } + return true; +} + +bool venc_dev::venc_set_encode_framerate(OMX_U32 encode_framerate, OMX_U32 config) +{ + + struct v4l2_control control; + int rc; + struct venc_framerate frame_rate_cfg; + Q16ToFraction(encode_framerate,frame_rate_cfg.fps_numerator,frame_rate_cfg.fps_denominator); + control.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE; + control.value = frame_rate_cfg.fps_numerator; + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + if(//ioctl(m_nDriver_fd, VEN_IOCTL_SET_FRAME_RATE, + /*(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting framerate failed"); + return false; + } + + m_sVenc_cfg.fps_den = 1; + m_sVenc_cfg.fps_num = control.value; + if(!config) + { + m_level_set = false; + if(venc_set_profile_level(0, 0)) + { + DEBUG_PRINT_HIGH("Calling set level (Framerate) with %d\n",profile_level.level); + } + } + return true; +} + +bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format) +{ + DEBUG_PRINT_LOW("\n venc_set_color_format: color_format = %u ", color_format); + + if(color_format == OMX_COLOR_FormatYUV420SemiPlanar) + { + m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12_16M2KA; + } + else + { + DEBUG_PRINT_ERROR("\nWARNING: Unsupported Color format [%d]", color_format); + m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12_16M2KA; + DEBUG_PRINT_HIGH("\n Default color format YUV420SemiPlanar is set"); + } + if (/*ioctl(m_nDriver_fd, VEN_IOCTL_SET_BASE_CFG, (void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting color format failed"); + return false; + } + return true; +} + +bool venc_dev::venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh) +{ + DEBUG_PRINT_LOW("\n venc_set_intra_vop_refresh: intra_vop = %uc", intra_vop_refresh); + if(intra_vop_refresh == OMX_TRUE) + { + struct v4l2_control control; + int rc; + control.id = V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME; + control.value = 1; + printf("Calling IOCTL set control for id=%x, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + printf("Failed to set Intra Frame Request control\n"); + return false; + } + printf("Success IOCTL set control for id=%x, value=%d\n", control.id, control.value); + + if(/*ioctl(m_nDriver_fd, VEN_IOCTL_CMD_REQUEST_IFRAME, NULL) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Intra VOP Refresh failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: VOP Refresh is False, no effect"); + } + return true; +} + +bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate) +{ + bool status = true; + struct v4l2_control control; + int rc; + control.id = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL; + switch(eControlRate) + { + case OMX_Video_ControlRateDisable: + control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_OFF; + break; + case OMX_Video_ControlRateVariableSkipFrames: + control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR; + break; + case OMX_Video_ControlRateVariable: + control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR; + break; + case OMX_Video_ControlRateConstantSkipFrames: + control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR; + break; + case OMX_Video_ControlRateConstant: + control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR; + break; + default: + status = false; + break; + } + + if(status) + { + + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d\n", control.id, control.value); + rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (rc) { + DEBUG_PRINT_ERROR("Failed to set control\n"); + return false; + } + DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); + + + if(/*ioctl (m_nDriver_fd,VEN_IOCTL_SET_RATE_CTRL_CFG,(void*)&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting rate control failed"); + status = false; + } + else + rate_ctrl.rcmode = control.value; + } + return status; +} + +bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel) +{ + bool status = true; + if(eProfile == NULL || eLevel == NULL) + { + return false; + } + + if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4) + { + switch(codec_profile.profile) + { + case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE: + *eProfile = OMX_VIDEO_MPEG4ProfileSimple; + break; + case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE: + *eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + break; + default: + *eProfile = OMX_VIDEO_MPEG4ProfileMax; + status = false; + break; + } + + if(!status) + { + return status; + } + + //profile level + switch(profile_level.level) + { + case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0: + *eLevel = OMX_VIDEO_MPEG4Level0; + break; + case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B: + *eLevel = OMX_VIDEO_MPEG4Level0b; + break; + case V4L2_MPEG_VIDEO_MPEG4_LEVEL_1: + *eLevel = OMX_VIDEO_MPEG4Level1; + break; + case V4L2_MPEG_VIDEO_MPEG4_LEVEL_2: + *eLevel = OMX_VIDEO_MPEG4Level2; + break; + case V4L2_MPEG_VIDEO_MPEG4_LEVEL_3: + *eLevel = OMX_VIDEO_MPEG4Level3; + break; + case V4L2_MPEG_VIDEO_MPEG4_LEVEL_4: + *eLevel = OMX_VIDEO_MPEG4Level4; + break; + case V4L2_MPEG_VIDEO_MPEG4_LEVEL_5: + *eLevel = OMX_VIDEO_MPEG4Level5; + break; + default: + *eLevel = OMX_VIDEO_MPEG4LevelMax; + status = false; + break; + } + } + else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263) + { + if(codec_profile.profile == VEN_PROFILE_H263_BASELINE) + { + *eProfile = OMX_VIDEO_H263ProfileBaseline; + } + else + { + *eProfile = OMX_VIDEO_H263ProfileMax; + return false; + } + switch(profile_level.level) + { + case VEN_LEVEL_H263_10: + *eLevel = OMX_VIDEO_H263Level10; + break; + case VEN_LEVEL_H263_20: + *eLevel = OMX_VIDEO_H263Level20; + break; + case VEN_LEVEL_H263_30: + *eLevel = OMX_VIDEO_H263Level30; + break; + case VEN_LEVEL_H263_40: + *eLevel = OMX_VIDEO_H263Level40; + break; + case VEN_LEVEL_H263_45: + *eLevel = OMX_VIDEO_H263Level45; + break; + case VEN_LEVEL_H263_50: + *eLevel = OMX_VIDEO_H263Level50; + break; + case VEN_LEVEL_H263_60: + *eLevel = OMX_VIDEO_H263Level60; + break; + case VEN_LEVEL_H263_70: + *eLevel = OMX_VIDEO_H263Level70; + break; + default: + *eLevel = OMX_VIDEO_H263LevelMax; + status = false; + break; + } + } + else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) + { + switch(codec_profile.profile) + { + case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: + *eProfile = OMX_VIDEO_AVCProfileBaseline; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: + *eProfile = OMX_VIDEO_AVCProfileMain; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: + *eProfile = OMX_VIDEO_AVCProfileHigh; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED: + *eProfile = OMX_VIDEO_AVCProfileExtended; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10: + *eProfile = OMX_VIDEO_AVCProfileHigh10; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422: + *eProfile = OMX_VIDEO_AVCProfileHigh422; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE: + *eProfile = OMX_VIDEO_AVCProfileHigh444; + break; + default: + *eProfile = OMX_VIDEO_AVCProfileMax; + status = false; + break; + } + + if(!status) + { + return status; + } + + switch(profile_level.level) + { + case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: + *eLevel = OMX_VIDEO_AVCLevel1; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_1B: + *eLevel = OMX_VIDEO_AVCLevel1b; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: + *eLevel = OMX_VIDEO_AVCLevel11; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: + *eLevel = OMX_VIDEO_AVCLevel12; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: + *eLevel = OMX_VIDEO_AVCLevel13; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: + *eLevel = OMX_VIDEO_AVCLevel2; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: + *eLevel = OMX_VIDEO_AVCLevel21; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: + *eLevel = OMX_VIDEO_AVCLevel22; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: + *eLevel = OMX_VIDEO_AVCLevel3; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: + *eLevel = OMX_VIDEO_AVCLevel31; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: + *eLevel = OMX_VIDEO_AVCLevel32; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: + *eLevel = OMX_VIDEO_AVCLevel4; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_4_1: + *eLevel = OMX_VIDEO_AVCLevel41; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_4_2: + *eLevel = OMX_VIDEO_AVCLevel42; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_5_0: + *eLevel = OMX_VIDEO_AVCLevel5; + break; + case V4L2_MPEG_VIDEO_H264_LEVEL_5_1: + *eLevel = OMX_VIDEO_AVCLevel51; + break; + default : + *eLevel = OMX_VIDEO_AVCLevelMax; + status = false; + break; + } + } + return status; +} + +bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel) +{ + OMX_U32 new_profile = 0, new_level = 0; + unsigned const int *profile_tbl = NULL; + OMX_U32 mb_per_frame, mb_per_sec; + bool profile_level_found = false; + + DEBUG_PRINT_LOW("\n Init profile table for respective codec"); + //validate the ht,width,fps,bitrate and set the appropriate profile and level + if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4) + { + if(*eProfile == 0) + { + if(!m_profile_set) + { + *eProfile = OMX_VIDEO_MPEG4ProfileSimple; + } + else + { + switch(codec_profile.profile) + { + case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE: + *eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + break; + case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE: + *eProfile = OMX_VIDEO_MPEG4ProfileSimple; + break; + default: + DEBUG_PRINT_LOW("\n %s(): Unknown Error", __func__); + return false; + } + } + } + + if(*eLevel == 0 && !m_level_set) + { + *eLevel = OMX_VIDEO_MPEG4LevelMax; + } + + if(*eProfile == OMX_VIDEO_MPEG4ProfileSimple) + { + profile_tbl = (unsigned int const *)mpeg4_profile_level_table; + } + else if(*eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) + { + profile_tbl = (unsigned int const *) + (&mpeg4_profile_level_table[MPEG4_ASP_START]); + } + else + { + DEBUG_PRINT_LOW("\n Unsupported MPEG4 profile type %lu", *eProfile); + return false; + } + } + else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) + { + if(*eProfile == 0) + { + if(!m_profile_set) + { + *eProfile = OMX_VIDEO_AVCProfileBaseline; + } + else + { + switch(codec_profile.profile) + { + case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: + *eProfile = OMX_VIDEO_AVCProfileBaseline; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: + *eProfile = OMX_VIDEO_AVCProfileMain; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED: + *eProfile = OMX_VIDEO_AVCProfileExtended; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: + *eProfile = OMX_VIDEO_AVCProfileHigh; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10: + *eProfile = OMX_VIDEO_AVCProfileHigh10; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422: + *eProfile = OMX_VIDEO_AVCProfileHigh422; + break; + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE: + *eProfile = OMX_VIDEO_AVCProfileHigh444; + break; + default: + DEBUG_PRINT_LOW("\n %s(): Unknown Error", __func__); + return false; + } + } + } + + if(*eLevel == 0 && !m_level_set) + { + *eLevel = OMX_VIDEO_AVCLevelMax; + } + + if(*eProfile == OMX_VIDEO_AVCProfileBaseline) + { + profile_tbl = (unsigned int const *)h264_profile_level_table; + } + else if(*eProfile == OMX_VIDEO_AVCProfileHigh) + { + profile_tbl = (unsigned int const *) + (&h264_profile_level_table[H264_HP_START]); + } + else if(*eProfile == OMX_VIDEO_AVCProfileMain) + { + profile_tbl = (unsigned int const *) + (&h264_profile_level_table[H264_MP_START]); + } + else + { + DEBUG_PRINT_LOW("\n Unsupported AVC profile type %lu", *eProfile); + return false; + } + } + else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263) + { + if(*eProfile == 0) + { + if(!m_profile_set) + { + *eProfile = OMX_VIDEO_H263ProfileBaseline; + } + else + { + switch(codec_profile.profile) + { + case VEN_PROFILE_H263_BASELINE: + *eProfile = OMX_VIDEO_H263ProfileBaseline; + break; + default: + DEBUG_PRINT_LOW("\n %s(): Unknown Error", __func__); + return false; + } + } + } + + if(*eLevel == 0 && !m_level_set) + { + *eLevel = OMX_VIDEO_H263LevelMax; + } + + if(*eProfile == OMX_VIDEO_H263ProfileBaseline) + { + profile_tbl = (unsigned int const *)h263_profile_level_table; + } + else + { + DEBUG_PRINT_LOW("\n Unsupported H.263 profile type %lu", *eProfile); + return false; + } + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) { + DEBUG_PRINT_HIGH("Disregarding profile/level setting for VP8\n"); + return true; + } + else + { + DEBUG_PRINT_LOW("\n Invalid codec type"); + return false; + } + + mb_per_frame = ((m_sVenc_cfg.input_height + 15) >> 4)* + ((m_sVenc_cfg.input_width + 15)>> 4); + + if((mb_per_frame >= 3600) && (m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4)) + { + if(codec_profile.profile == V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE) + profile_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5; + if(codec_profile.profile == V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE) + profile_level.level = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5; + { + new_level = profile_level.level; + new_profile = codec_profile.profile; + return true; + } + } + + mb_per_sec = mb_per_frame * m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den; + + do{ + if(mb_per_frame <= (int)profile_tbl[0]) + { + if(mb_per_sec <= (int)profile_tbl[1]) + { + if(m_sVenc_cfg.targetbitrate <= (int)profile_tbl[2]) + { + new_level = (int)profile_tbl[3]; + new_profile = (int)profile_tbl[4]; + profile_level_found = true; + DEBUG_PRINT_LOW("\n Appropriate profile/level found %d/%d\n", new_profile, new_level); + break; + } + } + } + profile_tbl = profile_tbl + 5; + }while(profile_tbl[0] != 0); + + if (profile_level_found != true) + { + DEBUG_PRINT_LOW("\n ERROR: Unsupported profile/level\n"); + return false; + } + + if((*eLevel == OMX_VIDEO_MPEG4LevelMax) || (*eLevel == OMX_VIDEO_AVCLevelMax) + || (*eLevel == OMX_VIDEO_H263LevelMax)) + { + *eLevel = new_level; + } + DEBUG_PRINT_HIGH("%s: Returning with eProfile = %lu" + "Level = %lu", __func__, *eProfile, *eLevel); + + return true; +} +#ifdef _ANDROID_ICS_ +bool venc_dev::venc_set_meta_mode(bool mode) +{ + if(/*ioctl(m_nDriver_fd,VEN_IOCTL_SET_METABUFFER_MODE,&ioctl_msg) < */0) + { + DEBUG_PRINT_ERROR(" Set meta buffer mode failed"); + return false; + } + return true; +} +#endif diff --git a/mm-video/vidc/venc/test/camera_test.cpp b/mm-video/vidc/venc/test/camera_test.cpp new file mode 100755 index 0000000..1c4f8ae --- /dev/null +++ b/mm-video/vidc/venc/test/camera_test.cpp @@ -0,0 +1,93 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include "camera_test.h" +// #include "camera_class.h" + +EXTERN_C_START + +// static android::Camera* pCamera = NULL; + +int CameraTest_Initialize(int nFrameRate, + int nFrameWidth, + int nFrameHeight, + CameraPreviewCallback pfnPreviewCallback) +{ + int result = 0; + +// pCamera = new android::Camera; +// if (!pCamera) +// return 1; + +// pCamera->init_camera(nFrameWidth, +// nFrameHeight, +// nFrameRate, +// pfnPreviewCallback); + + return result; +} + +int CameraTest_Run() +{ + int result = 0; + +// if (pCamera) +// pCamera->startPreview(); +// else +// return 1; + + return result; +} + +int CameraTest_ReleaseFrame(void* pPhys, void* pVirt) +{ + int result = 0; + +// if (pCamera) +// pCamera->releaseFrame(pPhys, pVirt); +// else +// return 1; + + return result; +} + +int CameraTest_Exit() +{ + int result = 0; + +// if (pCamera) +// { +// pCamera->stopPreview(); +// delete pCamera; +// } +// pCamera = NULL; + + return result; +} + + +EXTERN_C_END diff --git a/mm-video/vidc/venc/test/fb_test.c b/mm-video/vidc/venc/test/fb_test.c new file mode 100755 index 0000000..6bbe088 --- /dev/null +++ b/mm-video/vidc/venc/test/fb_test.c @@ -0,0 +1,48 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include "fb_test.h" + +int FBTest_Initialize(int nFrameWidth, + int nFrameHeight) +{ + return 0; +} +int FBTest_DisplayImage(int nPmemFd, int nOffset) +{ + return 0; +} + +int FBTest_Exit() +{ + return 0; +} + +int FBTest_RunTest() +{ + return 0; +} diff --git a/mm-video/vidc/venc/test/queue.c b/mm-video/vidc/venc/test/queue.c new file mode 100755 index 0000000..98c27da --- /dev/null +++ b/mm-video/vidc/venc/test/queue.c @@ -0,0 +1,174 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include "queue.h" + +int check_if_queue_empty ( unsigned int queuetocheck, void* queuecontext ) +{ + struct video_queue_context *ptr_q = NULL; + /* + * queuetocheck - 0 command queue + * queuetocheck - 1 data queue + */ + if ( queuecontext == NULL || (queuetocheck > 1 ) ) + { + return 1; + } + ptr_q = (struct video_queue_context *)queuecontext; + + if (queuetocheck == 0) + { + if (ptr_q->read_comq == ptr_q->write_comq) + { + return 1; + } + } + else if (queuetocheck == 1) + { + if (ptr_q->write_dataq == ptr_q->read_dataq) + { + return 1; + } + } + + return 0; +} + + + +struct video_msgq * queue_get_cmd (void* queuecontext ) +{ + struct video_queue_context *ptr_q = NULL; + struct video_msgq *pitem = NULL; + + if( NULL == queuecontext ) + { + printf("\n queue_get_cmd: Invalid Input parameter\n"); + return NULL; + } + + ptr_q = (struct video_queue_context *)queuecontext; + + /* Wait on the semaphore till it is released */ + sem_wait(&ptr_q->sem_message); + + /* Lock the mutex to protect the critical section */ + pthread_mutex_lock(&ptr_q->mutex); + + if (ptr_q->read_comq != ptr_q->write_comq) + { + pitem = &ptr_q->ptr_cmdq [ptr_q->read_comq]; + ptr_q->read_comq = (ptr_q->read_comq + 1) % \ + ptr_q->commandq_size; + } + else if (ptr_q->write_dataq != ptr_q->read_dataq) + { + pitem = &ptr_q->ptr_dataq [ptr_q->read_dataq]; + ptr_q->read_dataq = (ptr_q->read_dataq + 1) % \ + ptr_q->dataq_size; + } + + /* Unlock the mutex to release the critical section */ + pthread_mutex_unlock(&ptr_q->mutex); + + return pitem; +} + + +int queue_post_cmdq ( void* queuecontext, + struct video_msgq *pitem + ) +{ + struct video_queue_context *ptr_q = NULL; + + if (pitem == NULL || queuecontext == NULL) + { + return -1; + } + ptr_q = (struct video_queue_context *)queuecontext; + + /* Lock the mutex to protect the critical section */ + pthread_mutex_lock(&ptr_q->mutex); + + if ((ptr_q->write_comq + 1) % ptr_q->commandq_size == ptr_q->read_comq) + { + printf("\n QUEUE is FULL"); + return 0; + } + else + { + /* Store the command in the Message Queue & increment write offset */ + memcpy ( &ptr_q->ptr_cmdq [ptr_q->write_comq],pitem, \ + sizeof (struct video_msgq)); + ptr_q->write_comq = (ptr_q->write_comq + 1) % ptr_q->commandq_size; + } + + /* Unlock the mutex to release the critical section */ + pthread_mutex_unlock(&ptr_q->mutex); + + /* Post the semaphore */ + sem_post(&ptr_q->sem_message); + return 1; +} + + +int queue_post_dataq ( void *queuecontext, + struct video_msgq *pitem + ) +{ + struct video_queue_context *ptr_q = NULL; + + if (pitem == NULL || queuecontext == NULL) + { + return -1; + } + ptr_q = (struct video_queue_context *)queuecontext; + + /* Lock the mutex to protect the critical section */ + pthread_mutex_lock(&ptr_q->mutex); + + if ((ptr_q->write_dataq + 1) % ptr_q->dataq_size == ptr_q->read_dataq) + { + printf("\n QUEUE is FULL"); + return 0; + } + else + { + /* Store the command in the Message Queue & increment write offset */ + memcpy ( &ptr_q->ptr_dataq [ptr_q->write_dataq],pitem, \ + sizeof (struct video_msgq)); + ptr_q->write_dataq = (ptr_q->write_dataq + 1) % ptr_q->dataq_size; + } + + /* Unlock the mutex to release the critical section */ + pthread_mutex_unlock(&ptr_q->mutex); + + /* Post the semaphore */ + sem_post(&ptr_q->sem_message); + return 1; + +} diff --git a/mm-video/vidc/venc/test/venc_test.cpp b/mm-video/vidc/venc/test/venc_test.cpp new file mode 100755 index 0000000..68f9819 --- /dev/null +++ b/mm-video/vidc/venc/test/venc_test.cpp @@ -0,0 +1,2405 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + V E N C _ T E S T. C P P + +DESCRIPTION + + This is the OMX test app . + +REFERENCES + +============================================================================*/ + +//usage +// FILE QVGA MP4 24 384000 100 enc_qvga.yuv QVGA_24.m4v +// FILE QCIF MP4 15 96000 0 foreman.qcif.yuv output_qcif.m4v +// FILE VGA MP4 24 1200000 218 enc_vga.yuv vga_output.m4v +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +//#include +#include "OMX_QCOMExtns.h" +#include "OMX_Core.h" + +#define QCOM_EXT 1 + +#include "OMX_Core.h" +#include "OMX_Video.h" +#include "OMX_Component.h" +#include "camera_test.h" +#include "fb_test.h" +#include "venc_util.h" +#include "extra_data_handler.h" +#ifdef USE_ION +#include +#endif + +////////////////////////// +// MACROS +////////////////////////// + +#define CHK(result) if (result != OMX_ErrorNone) { E("*************** error *************"); exit(0); } +#define TEST_LOG +#ifdef VENC_SYSLOG +#include "cutils/log.h" +/// Debug message macro +#define D(fmt, ...) LOGE("venc_test Debug %s::%d "fmt"\n", \ + __FUNCTION__, __LINE__, \ + ## __VA_ARGS__) + +/// Error message macro +#define E(fmt, ...) LOGE("venc_test Error %s::%d "fmt"\n", \ + __FUNCTION__, __LINE__, \ + ## __VA_ARGS__) + +#else + #ifdef TEST_LOG + #define D(fmt, ...) fprintf(stderr, "venc_test Debug %s::%d "fmt"\n", \ + __FUNCTION__, __LINE__, \ + ## __VA_ARGS__) + + /// Error message macro + #define E(fmt, ...) fprintf(stderr, "venc_test Error %s::%d "fmt"\n", \ + __FUNCTION__, __LINE__, \ + ## __VA_ARGS__) + #else + #define D(fmt, ...) + #define E(fmt, ...) + #endif + +#endif + +////////////////////////// +// CONSTANTS +////////////////////////// +static const int MAX_MSG = 100; +//#warning do not hardcode these use port definition +static const int PORT_INDEX_IN = 0; +static const int PORT_INDEX_OUT = 1; + +static const int NUM_IN_BUFFERS = 10; +static const int NUM_OUT_BUFFERS = 10; + +unsigned int num_in_buffers = 0; +unsigned int num_out_buffers = 0; + +////////////////////////// +/* MPEG4 profile and level table*/ +static const unsigned int mpeg4_profile_level_table[][5]= +{ + /*max mb per frame, max mb per sec, max bitrate, level, profile*/ + {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple}, + {99,1485,64000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple}, + {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple}, + {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple}, + {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple}, + {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, + {3600,108000,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, +#ifdef _MSM8974_ + {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, + {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, +#endif + {0,0,0,0,0}, + + {99,1485,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, +#ifdef _MSM8974_ + {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, +#endif + {0,0,0,0,0}, +}; + +/* H264 profile and level table*/ +static const unsigned int h264_profile_level_table[][5]= +{ + /*max mb per frame, max mb per sec, max bitrate, level, profile*/ + {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline}, + {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline}, + {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline}, + {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline}, + {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline}, + {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline}, + {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline}, + {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline}, + {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline}, + {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline}, + {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileBaseline}, + {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline}, +#ifdef _MSM8974_ + {32400,972000,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline}, + {34560,1036800,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline}, +#endif + {0,0,0,0,0}, + + {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh}, + {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh}, + {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh}, + {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh}, + {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh}, + {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh}, + {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh}, + {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh}, + {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh}, + {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh}, + {5120,216000,25000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh}, + {8192,245760,25000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh}, +#ifdef _MSM8974_ + {32400,972000,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh}, + {34560,1036800,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh}, +#endif + {0,0,0,0,0}, + + {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain}, + {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain}, + {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain}, + {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain}, + {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain}, + {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain}, + {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain}, + {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain}, + {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain}, + {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain}, + {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileMain}, + {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain}, +#ifdef _MSM8974_ + {32400,972000,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain}, + {34560,1036800,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain}, +#endif + {0,0,0,0,0} + +}; + +/* H263 profile and level table*/ +static const unsigned int h263_profile_level_table[][5]= +{ + /*max mb per frame, max mb per sec, max bitrate, level, profile*/ + {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline}, + {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline}, + {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline}, + {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline}, + {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline}, + {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline}, + {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline}, + {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, +#ifdef _MSM8974_ + {32400,972000,20000000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline}, + {34560,1036800,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, +#endif + {0,0,0,0,0} +}; +#ifdef _MSM8974_ +static const unsigned int VP8_profile_level_table[][5]= +{ + /*max mb per frame, max mb per sec, max bitrate, level, profile*/ + {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline}, + {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline}, + {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline}, + {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline}, + {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline}, + {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline}, + {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline}, + {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, + {32400,972000,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, + {34560,1036800,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, + {0,0,0,0,0} +}; +#endif + +#define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } +#define FractionToQ16(q,num,den) { OMX_U32 power; Log2(den,power); q = num << (16 - power); } + +////////////////////////// +// TYPES +////////////////////////// +struct ProfileType +{ + OMX_VIDEO_CODINGTYPE eCodec; + OMX_VIDEO_MPEG4LEVELTYPE eLevel; + OMX_VIDEO_CONTROLRATETYPE eControlRate; + OMX_VIDEO_AVCSLICEMODETYPE eSliceMode; + OMX_U32 nFrameWidth; + OMX_U32 nFrameHeight; + OMX_U32 nFrameBytes; +#ifdef _MSM8974_ + OMX_U32 nFramestride; + OMX_U32 nFrameScanlines; + OMX_U32 nFrameRead; +#endif + OMX_U32 nBitrate; + float nFramerate; + char* cInFileName; + char* cOutFileName; + OMX_U32 nUserProfile; +}; + +enum MsgId +{ + MSG_ID_OUTPUT_FRAME_DONE, + MSG_ID_INPUT_FRAME_DONE, + MSG_ID_MAX +}; +union MsgData +{ + struct + { + OMX_BUFFERHEADERTYPE* pBuffer; + } sBitstreamData; +}; +struct Msg +{ + MsgId id; + MsgData data; +}; +struct MsgQ +{ + Msg q[MAX_MSG]; + int head; + int size; +}; + +enum Mode +{ + MODE_PREVIEW, + MODE_DISPLAY, + MODE_PROFILE, + MODE_FILE_ENCODE, + MODE_LIVE_ENCODE +}; + +enum ResyncMarkerType +{ + RESYNC_MARKER_NONE, ///< No resync marker + RESYNC_MARKER_BYTE, ///< BYTE Resync marker for MPEG4, H.264 + RESYNC_MARKER_MB, ///< MB resync marker for MPEG4, H.264 + RESYNC_MARKER_GOB ///< GOB resync marker for H.263 +}; + +union DynamicConfigData +{ + OMX_VIDEO_CONFIG_BITRATETYPE bitrate; + OMX_CONFIG_FRAMERATETYPE framerate; + QOMX_VIDEO_INTRAPERIODTYPE intraperiod; + OMX_CONFIG_INTRAREFRESHVOPTYPE intravoprefresh; + OMX_CONFIG_ROTATIONTYPE rotation; + float f_framerate; +}; + +struct DynamicConfig +{ + bool pending; + unsigned frame_num; + OMX_INDEXTYPE config_param; + union DynamicConfigData config_data; +}; + +#ifdef USE_ION +struct enc_ion +{ + int ion_device_fd; + struct ion_allocation_data alloc_data; + struct ion_fd_data ion_alloc_fd; +}; +#endif + +////////////////////////// +// MODULE VARS +////////////////////////// +static pthread_mutex_t m_mutex; +static pthread_cond_t m_signal; +static MsgQ m_sMsgQ; + +//#warning determine how many buffers we really have +OMX_STATETYPE m_eState = OMX_StateInvalid; +OMX_COMPONENTTYPE m_sComponent; +OMX_HANDLETYPE m_hHandle = NULL; +OMX_BUFFERHEADERTYPE* m_pOutBuffers[NUM_OUT_BUFFERS] = {NULL}; +OMX_BUFFERHEADERTYPE* m_pInBuffers[NUM_IN_BUFFERS] = {NULL}; +OMX_BOOL m_bInFrameFree[NUM_IN_BUFFERS]; + +ProfileType m_sProfile; + +static int m_nFramePlay = 0; +static int m_eMode = MODE_PREVIEW; +static int m_nInFd = -1; +static int m_nOutFd = -1; +static int m_nTimeStamp = 0; +static int m_nFrameIn = 0; // frames pushed to encoder +static int m_nFrameOut = 0; // frames returned by encoder +static int m_nAVCSliceMode = 0; +static bool m_bWatchDogKicked = false; +FILE *m_pDynConfFile = NULL; +static struct DynamicConfig dynamic_config; + +/* Statistics Logging */ +static long long tot_bufsize = 0; +int ebd_cnt=0, fbd_cnt=0; + +#ifdef USE_ION +static const char* PMEM_DEVICE = "/dev/ion"; +#elif MAX_RES_720P +static const char* PMEM_DEVICE = "/dev/pmem_adsp"; +#elif MAX_RES_1080P_EBI +static const char* PMEM_DEVICE = "/dev/pmem_adsp"; +#elif MAX_RES_1080P +static const char* PMEM_DEVICE = "/dev/pmem_smipool"; +#else +#error PMEM_DEVICE cannot be determined. +#endif + +#ifdef USE_ION +struct enc_ion ion_data; +#endif +////////////////////////// +// MODULE FUNCTIONS +////////////////////////// + +void* PmemMalloc(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem, int nSize) +{ + void *pvirt = NULL; + int rc = 0; + + if (!pMem) + return NULL; + +#ifdef USE_ION + ion_data.ion_device_fd = open (PMEM_DEVICE, O_RDONLY|O_DSYNC); + if(ion_data.ion_device_fd < 0) + { + E("\nERROR: ION Device open() Failed"); + return NULL; + } + nSize = (nSize + 4095) & (~4095); + ion_data.alloc_data.len = nSize; + ion_data.alloc_data.flags = 0x1 << ION_CP_MM_HEAP_ID; + ion_data.alloc_data.align = 4096; + + rc = ioctl(ion_data.ion_device_fd,ION_IOC_ALLOC,&ion_data.alloc_data); + if(rc || !ion_data.alloc_data.handle) { + E("\n ION ALLOC memory failed "); + ion_data.alloc_data.handle=NULL; + return NULL; + } + + ion_data.ion_alloc_fd.handle = ion_data.alloc_data.handle; + rc = ioctl(ion_data.ion_device_fd,ION_IOC_MAP,&ion_data.ion_alloc_fd); + if(rc) { + E("\n ION MAP failed "); + ion_data.ion_alloc_fd.fd =-1; + ion_data.ion_alloc_fd.fd =-1; + return NULL; + } + pMem->pmem_fd = ion_data.ion_alloc_fd.fd; +#else + pMem->pmem_fd = open(PMEM_DEVICE, O_RDWR); + if ((int)(pMem->pmem_fd) < 0) + return NULL; + nSize = (nSize + 4095) & (~4095); +#endif + pMem->offset = 0; + pvirt = mmap(NULL, nSize, + PROT_READ | PROT_WRITE, + MAP_SHARED, pMem->pmem_fd, pMem->offset); + if (pvirt == (void*) MAP_FAILED) + { + close(pMem->pmem_fd); + pMem->pmem_fd = -1; +#ifdef USE_ION + if(ioctl(ion_data.ion_device_fd,ION_IOC_FREE, + &ion_data.alloc_data.handle)) { + E("ion recon buffer free failed"); + } + ion_data.alloc_data.handle = NULL; + ion_data.ion_alloc_fd.fd =-1; + close(ion_data.ion_device_fd); + ion_data.ion_device_fd =-1; +#endif + return NULL; + } + D("allocated pMem->fd = %d pvirt=0x%x, pMem->phys=0x%x, size = %d", pMem->pmem_fd, + pvirt, pMem->offset, nSize); + return pvirt; +} + +int PmemFree(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem, void* pvirt, int nSize) +{ + if (!pMem || !pvirt) + return -1; + + nSize = (nSize + 4095) & (~4095); + munmap(pvirt, nSize); + close(pMem->pmem_fd); + pMem->pmem_fd = -1; +#ifdef USE_ION + if(ioctl(ion_data.ion_device_fd,ION_IOC_FREE, + &ion_data.alloc_data.handle)) { + E("ion recon buffer free failed"); + } + ion_data.alloc_data.handle = NULL; + ion_data.ion_alloc_fd.fd =-1; + close(ion_data.ion_device_fd); + ion_data.ion_device_fd =-1; +#endif + return 0; +} +void PrintFramePackArrangement(OMX_QCOM_FRAME_PACK_ARRANGEMENT framePackingArrangement) +{ + printf("id (%d)\n", + framePackingArrangement.id); + printf("cancel_flag (%d)\n", + framePackingArrangement.cancel_flag); + printf("type (%d)\n", + framePackingArrangement.type); + printf("quincunx_sampling_flag (%d)\n", + framePackingArrangement.quincunx_sampling_flag); + printf("content_interpretation_type (%d)\n", + framePackingArrangement.content_interpretation_type); + printf("spatial_flipping_flag (%d)\n", + framePackingArrangement.spatial_flipping_flag); + printf("frame0_flipped_flag (%d)\n", + framePackingArrangement.frame0_flipped_flag); + printf("field_views_flag (%d)\n", + framePackingArrangement.field_views_flag); + printf("current_frame_is_frame0_flag (%d)\n", + framePackingArrangement.current_frame_is_frame0_flag); + printf("frame0_self_contained_flag (%d)\n", + framePackingArrangement.frame0_self_contained_flag); + printf("frame1_self_contained_flag (%d)\n", + framePackingArrangement.frame1_self_contained_flag); + printf("frame0_grid_position_x (%d)\n", + framePackingArrangement.frame0_grid_position_x); + printf("frame0_grid_position_y (%d)\n", + framePackingArrangement.frame0_grid_position_y); + printf("frame1_grid_position_x (%d)\n", + framePackingArrangement.frame1_grid_position_x); + printf("frame1_grid_position_y (%d)\n", + framePackingArrangement.frame1_grid_position_y); + printf("reserved_byte (%d)\n", + framePackingArrangement.reserved_byte); + printf("repetition_period (%d)\n", + framePackingArrangement.repetition_period); + printf("extension_flag (%d)\n", + framePackingArrangement.extension_flag); +} +void SetState(OMX_STATETYPE eState) +{ +#define GOTO_STATE(eState) \ + case eState: \ + { \ + D("Going to state " # eState"..."); \ + OMX_SendCommand(m_hHandle, \ + OMX_CommandStateSet, \ + (OMX_U32) eState, \ + NULL); \ + while (m_eState != eState) \ + { \ + sleep(1); \ + } \ + D("Now in state " # eState); \ + break; \ + } + + switch (eState) + { + GOTO_STATE(OMX_StateLoaded); + GOTO_STATE(OMX_StateIdle); + GOTO_STATE(OMX_StateExecuting); + GOTO_STATE(OMX_StateInvalid); + GOTO_STATE(OMX_StateWaitForResources); + GOTO_STATE(OMX_StatePause); + } +} +//////////////////////////////////////////////////////////////////////////////// +OMX_ERRORTYPE ConfigureEncoder() +{ + OMX_ERRORTYPE result = OMX_ErrorNone; + unsigned const int *profile_tbl = (unsigned int const *)mpeg4_profile_level_table; + OMX_U32 mb_per_sec, mb_per_frame; + bool profile_level_found = false; + OMX_U32 eProfile,eLevel; + + OMX_PARAM_PORTDEFINITIONTYPE portdef; // OMX_IndexParamPortDefinition +#ifdef QCOM_EXT + OMX_QCOM_PARAM_PORTDEFINITIONTYPE qPortDefnType; +#endif + portdef.nPortIndex = (OMX_U32) 0; // input + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamPortDefinition, + &portdef); + E("\n OMX_IndexParamPortDefinition Get Paramter on input port"); + CHK(result); + portdef.format.video.nFrameWidth = m_sProfile.nFrameWidth; + portdef.format.video.nFrameHeight = m_sProfile.nFrameHeight; + + E ("\n Height %d width %d bit rate %d",portdef.format.video.nFrameHeight + ,portdef.format.video.nFrameWidth,portdef.format.video.nBitrate); + result = OMX_SetParameter(m_hHandle, + OMX_IndexParamPortDefinition, + &portdef); + E("\n OMX_IndexParamPortDefinition Set Paramter on input port"); + CHK(result); + // once more to get proper buffer size + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamPortDefinition, + &portdef); + E("\n OMX_IndexParamPortDefinition Get Paramter on input port, 2nd pass"); + CHK(result); + // update size accordingly + m_sProfile.nFrameBytes = portdef.nBufferSize; + portdef.nPortIndex = (OMX_U32) 1; // output + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamPortDefinition, + &portdef); + E("\n OMX_IndexParamPortDefinition Get Paramter on output port"); + CHK(result); + portdef.format.video.nFrameWidth = m_sProfile.nFrameWidth; + portdef.format.video.nFrameHeight = m_sProfile.nFrameHeight; + portdef.format.video.nBitrate = m_sProfile.nBitrate; + FractionToQ16(portdef.format.video.xFramerate,(int) (m_sProfile.nFramerate * 2),2); + result = OMX_SetParameter(m_hHandle, + OMX_IndexParamPortDefinition, + &portdef); + E("\n OMX_IndexParamPortDefinition Set Paramter on output port"); + CHK(result); + +#ifdef QCOM_EXT + +qPortDefnType.nPortIndex = PORT_INDEX_IN; +qPortDefnType.nMemRegion = OMX_QCOM_MemRegionEBI1; +qPortDefnType.nSize = sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE); + +result = OMX_SetParameter(m_hHandle, + (OMX_INDEXTYPE)OMX_QcomIndexPortDefn, + &qPortDefnType); + +#endif + if (!m_sProfile.nUserProfile) // profile not set by user, go ahead with table calculation + { + //validate the ht,width,fps,bitrate and set the appropriate profile and level + if(m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) + { + profile_tbl = (unsigned int const *)mpeg4_profile_level_table; + } + else if(m_sProfile.eCodec == OMX_VIDEO_CodingAVC) + { + profile_tbl = (unsigned int const *)h264_profile_level_table; + } + else if(m_sProfile.eCodec == OMX_VIDEO_CodingH263) + { + profile_tbl = (unsigned int const *)h263_profile_level_table; + } +#ifdef _MSM8974_ + else if(m_sProfile.eCodec == OMX_VIDEO_CodingVPX) + { + profile_tbl = (unsigned int const *)VP8_profile_level_table; + } +#endif + mb_per_frame = ((m_sProfile.nFrameHeight+15)>>4)* + ((m_sProfile.nFrameWidth+15)>>4); + + mb_per_sec = mb_per_frame*(m_sProfile.nFramerate); + + do{ + if(mb_per_frame <= (int)profile_tbl[0]) + { + if(mb_per_sec <= (int)profile_tbl[1]) + { + if(m_sProfile.nBitrate <= (int)profile_tbl[2]) + { + eLevel = (int)profile_tbl[3]; + eProfile = (int)profile_tbl[4]; + E("\n profile/level found: %d/%d\n",eProfile/eLevel); + profile_level_found = true; + break; + } + } + } + profile_tbl = profile_tbl + 5; + }while(profile_tbl[0] != 0); + + if ( profile_level_found != true ) + { + E("\n Error: Unsupported profile/level\n"); + return OMX_ErrorNone; + } + } + else // Profile set by user! + { + eProfile = m_sProfile.nUserProfile; + eLevel = 0; + } + if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) + { + D("Configuring H263..."); + + OMX_VIDEO_PARAM_H263TYPE h263; + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamVideoH263, + &h263); + CHK(result); + h263.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + h263.nPFrames = m_sProfile.nFramerate * 2 - 1; // intra period + h263.nBFrames = 0; + h263.eProfile = (OMX_VIDEO_H263PROFILETYPE)eProfile; + h263.eLevel = (OMX_VIDEO_H263LEVELTYPE)eLevel; + h263.bPLUSPTYPEAllowed = OMX_FALSE; + h263.nAllowedPictureTypes = 2; + h263.bForceRoundingTypeToZero = OMX_TRUE; + h263.nPictureHeaderRepetition = 0; + h263.nGOBHeaderInterval = 1; + result = OMX_SetParameter(m_hHandle, + OMX_IndexParamVideoH263, + &h263); + } + else + { + D("Configuring MP4/H264..."); + + OMX_VIDEO_PARAM_PROFILELEVELTYPE profileLevel; // OMX_IndexParamVideoProfileLevelCurrent + profileLevel.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + profileLevel.eProfile = eProfile; + profileLevel.eLevel = eLevel; + result = OMX_SetParameter(m_hHandle, + OMX_IndexParamVideoProfileLevelCurrent, + &profileLevel); + E("\n OMX_IndexParamVideoProfileLevelCurrent Set Paramter port"); + CHK(result); + //profileLevel.eLevel = (OMX_U32) m_sProfile.eLevel; + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamVideoProfileLevelCurrent, + &profileLevel); + E("\n OMX_IndexParamVideoProfileLevelCurrent Get Paramter port"); + D ("\n Profile = %d level = %d",profileLevel.eProfile,profileLevel.eLevel); + CHK(result); + + if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) + { + OMX_VIDEO_PARAM_MPEG4TYPE mp4; // OMX_IndexParamVideoMpeg4 + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamVideoMpeg4, + &mp4); + CHK(result); + mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + mp4.nTimeIncRes = 1000; + result = OMX_SetParameter(m_hHandle, + OMX_IndexParamVideoMpeg4, + &mp4); + CHK(result); + } + } + if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC) + { +#if 1 +/////////////C A B A C ///A N D/////D E B L O C K I N G ///////////////// + + OMX_VIDEO_PARAM_AVCTYPE avcdata; + avcdata.nPortIndex = (OMX_U32)PORT_INDEX_OUT; + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamVideoAvc, + &avcdata); + CHK(result); +// TEST VALUES (CHANGE FOR DIFF CONFIG's) + avcdata.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; +// avcdata.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterDisable; +// avcdata.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterDisableSliceBoundary; + avcdata.bEntropyCodingCABAC = OMX_FALSE; +// avcdata.bEntropyCodingCABAC = OMX_TRUE; + avcdata.nCabacInitIdc = 1; +/////////////////////////////////////////////// + + result = OMX_SetParameter(m_hHandle, + OMX_IndexParamVideoAvc, + &avcdata); + CHK(result); + +/////////////C A B A C ///A N D/////D E B L O C K I N G ///////////////// +#endif + } + + OMX_VIDEO_PARAM_BITRATETYPE bitrate; // OMX_IndexParamVideoBitrate + bitrate.nPortIndex = (OMX_U32)PORT_INDEX_OUT; + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamVideoBitrate, + &bitrate); + E("\n OMX_IndexParamVideoBitrate Get Paramter port"); + CHK(result); + bitrate.eControlRate = m_sProfile.eControlRate; + bitrate.nTargetBitrate = m_sProfile.nBitrate; + result = OMX_SetParameter(m_hHandle, + OMX_IndexParamVideoBitrate, + &bitrate); + E("\n OMX_IndexParamVideoBitrate Set Paramter port"); + CHK(result); + + OMX_VIDEO_PARAM_PORTFORMATTYPE framerate; // OMX_IndexParamVidePortFormat + framerate.nPortIndex = 0; + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamVideoPortFormat, + &framerate); + E("\n OMX_IndexParamVideoPortFormat Get Paramter port"); + CHK(result); + FractionToQ16(framerate.xFramerate,(int) (m_sProfile.nFramerate * 2),2); + result = OMX_SetParameter(m_hHandle, + OMX_IndexParamVideoPortFormat, + &framerate); + E("\n OMX_IndexParamVideoPortFormat Set Paramter port"); + CHK(result); + +#if 1 +///////////////////I N T R A P E R I O D /////////////////// + + QOMX_VIDEO_INTRAPERIODTYPE intra; + + intra.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output + result = OMX_GetConfig(m_hHandle, + (OMX_INDEXTYPE) QOMX_IndexConfigVideoIntraperiod, + (OMX_PTR) &intra); + + if (result == OMX_ErrorNone) + { + intra.nPFrames = (OMX_U32) (2 * m_sProfile.nFramerate - 1); //setting I + //frame interval to + //2 x framerate + intra.nIDRPeriod = 1; //every I frame is an IDR + intra.nPortIndex = (OMX_U32) PORT_INDEX_OUT; + result = OMX_SetConfig(m_hHandle, + (OMX_INDEXTYPE) QOMX_IndexConfigVideoIntraperiod, + (OMX_PTR) &intra); + } + else + { + E("failed to get state", 0, 0, 0); + } + + +///////////////////I N T R A P E R I O D /////////////////// +#endif + +#if 1 +///////////////////E R R O R C O R R E C T I O N /////////////////// + + ResyncMarkerType eResyncMarkerType = RESYNC_MARKER_NONE; + unsigned long int nResyncMarkerSpacing = 0; + OMX_BOOL enableHEC = OMX_FALSE; + +//For Testing ONLY + if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) + { +// MPEG4 +// eResyncMarkerType = RESYNC_MARKER_BYTE; +// nResyncMarkerSpacing = 1920; + eResyncMarkerType = RESYNC_MARKER_MB; + nResyncMarkerSpacing = 50; + enableHEC = OMX_TRUE; + } + else if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) + { +//H263 + eResyncMarkerType = RESYNC_MARKER_GOB; + nResyncMarkerSpacing = 0; + } + else if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC) + { +//H264 +// eResyncMarkerType = RESYNC_MARKER_BYTE; +// nResyncMarkerSpacing = 1920; + + //nResyncMarkerSpacing sets the slice size in venc_set_multislice_cfg + // + //As of 9/24/10, it is known that the firmware has a bitstream + //corruption issue when RateControl and multislice are enabled for 720P + //So, disabling multislice for 720P when ratecontrol is enabled until + //the firmware issue is resolved. + + if ( ( (m_sProfile.nFrameWidth == 1280) && (m_sProfile.nFrameHeight = 720) ) && + (m_sProfile.eControlRate != OMX_Video_ControlRateDisable) ) + { + eResyncMarkerType = RESYNC_MARKER_NONE; + nResyncMarkerSpacing = 0; + } + else + { + eResyncMarkerType = RESYNC_MARKER_MB; + nResyncMarkerSpacing = 50; + } + } + + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrection; //OMX_IndexParamVideoErrorCorrection + errorCorrection.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output + result = OMX_GetParameter(m_hHandle, + (OMX_INDEXTYPE) OMX_IndexParamVideoErrorCorrection, + (OMX_PTR) &errorCorrection); + + errorCorrection.bEnableRVLC = OMX_FALSE; + errorCorrection.bEnableDataPartitioning = OMX_FALSE; + + if ((eResyncMarkerType == RESYNC_MARKER_BYTE) && + (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4)){ + errorCorrection.bEnableResync = OMX_TRUE; + errorCorrection.nResynchMarkerSpacing = nResyncMarkerSpacing; + errorCorrection.bEnableHEC = enableHEC; + } + else if ((eResyncMarkerType == RESYNC_MARKER_BYTE) && + (m_sProfile.eCodec == OMX_VIDEO_CodingAVC)){ + errorCorrection.bEnableResync = OMX_TRUE; + errorCorrection.nResynchMarkerSpacing = nResyncMarkerSpacing; + } + else if ((eResyncMarkerType == RESYNC_MARKER_GOB) && + (m_sProfile.eCodec == OMX_VIDEO_CodingH263)){ + errorCorrection.bEnableResync = OMX_FALSE; + errorCorrection.nResynchMarkerSpacing = nResyncMarkerSpacing; + errorCorrection.bEnableDataPartitioning = OMX_TRUE; + } + + result = OMX_SetParameter(m_hHandle, + (OMX_INDEXTYPE) OMX_IndexParamVideoErrorCorrection, + (OMX_PTR) &errorCorrection); + CHK(result); + + if (eResyncMarkerType == RESYNC_MARKER_MB){ + if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC){ + OMX_VIDEO_PARAM_AVCTYPE avcdata; + avcdata.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamVideoAvc, + (OMX_PTR) &avcdata); + CHK(result); + if (result == OMX_ErrorNone) + { + avcdata.nSliceHeaderSpacing = nResyncMarkerSpacing; + result = OMX_SetParameter(m_hHandle, + OMX_IndexParamVideoAvc, + (OMX_PTR) &avcdata); + CHK(result); + + } + } + else if(m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4){ + OMX_VIDEO_PARAM_MPEG4TYPE mp4; + mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamVideoMpeg4, + (OMX_PTR) &mp4); + CHK(result); + + if (result == OMX_ErrorNone) + { + mp4.nSliceHeaderSpacing = nResyncMarkerSpacing; + result = OMX_SetParameter(m_hHandle, + OMX_IndexParamVideoMpeg4, + (OMX_PTR) &mp4); + CHK(result); + } + } + } + +///////////////////E R R O R C O R R E C T I O N /////////////////// +#endif + +#if 1 +///////////////////I N T R A R E F R E S H/////////////////// + bool bEnableIntraRefresh = OMX_TRUE; + + if (result == OMX_ErrorNone) + { + OMX_VIDEO_PARAM_INTRAREFRESHTYPE ir; // OMX_IndexParamVideoIntraRefresh + ir.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output + result = OMX_GetParameter(m_hHandle, + OMX_IndexParamVideoIntraRefresh, + (OMX_PTR) &ir); + if (result == OMX_ErrorNone) + { + if (bEnableIntraRefresh) + { + ir.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic; + ir.nCirMBs = 5; + result = OMX_SetParameter(m_hHandle, + OMX_IndexParamVideoIntraRefresh, + (OMX_PTR) &ir); + CHK(result); + } + } + } +#endif +#if 1 +///////////////////FRAMEPACKING DATA/////////////////// + OMX_QCOM_FRAME_PACK_ARRANGEMENT framePackingArrangement; + FILE *m_pConfigFile; + char m_configFilename [128] = "/data/configFile.cfg"; + memset(&framePackingArrangement, 0, sizeof(framePackingArrangement)); + m_pConfigFile = fopen(m_configFilename, "r"); + if (m_pConfigFile != NULL) + { + //read all frame packing data + framePackingArrangement.nPortIndex = (OMX_U32)PORT_INDEX_OUT; + int totalSizeToRead = FRAME_PACK_SIZE * sizeof(OMX_U32); + char *pFramePack = (char *) &(framePackingArrangement.id); + while ( ( (fscanf(m_pConfigFile, "%d", pFramePack)) != EOF ) && + (totalSizeToRead != 0) ) + { + //printf("Addr = %p, Value read = %d, sizeToRead remaining=%d\n", + // pFramePack, *pFramePack, totalSizeToRead); + pFramePack += sizeof(OMX_U32); + totalSizeToRead -= sizeof(OMX_U32); + } + //close the file. + fclose(m_pConfigFile); + + printf("Frame Packing data from config file:\n"); + PrintFramePackArrangement(framePackingArrangement); + } + else + { + D("\n Config file does not exist or could not be opened."); + //set the default values + framePackingArrangement.nPortIndex = (OMX_U32)PORT_INDEX_OUT; + framePackingArrangement.id = 123; + framePackingArrangement.cancel_flag = false; + framePackingArrangement.type = 3; + framePackingArrangement.quincunx_sampling_flag = false; + framePackingArrangement.content_interpretation_type = 0; + framePackingArrangement.spatial_flipping_flag = true; + framePackingArrangement.frame0_flipped_flag = false; + framePackingArrangement.field_views_flag = false; + framePackingArrangement.current_frame_is_frame0_flag = false; + framePackingArrangement.frame0_self_contained_flag = true; + framePackingArrangement.frame1_self_contained_flag = false; + framePackingArrangement.frame0_grid_position_x = 3; + framePackingArrangement.frame0_grid_position_y = 15; + framePackingArrangement.frame1_grid_position_x = 11; + framePackingArrangement.frame1_grid_position_y = 7; + framePackingArrangement.reserved_byte = 0; + framePackingArrangement.repetition_period = 16381; + framePackingArrangement.extension_flag = false; + + printf("Frame Packing Defaults :\n"); + PrintFramePackArrangement(framePackingArrangement); + } + result = OMX_SetConfig(m_hHandle, + (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement, + (OMX_PTR) &framePackingArrangement); + CHK(result); + +//////////////////////OMX_VIDEO_PARAM_INTRAREFRESHTYPE/////////////////// +#endif + + OMX_CONFIG_FRAMERATETYPE enc_framerate; // OMX_IndexConfigVideoFramerate + enc_framerate.nPortIndex = (OMX_U32)PORT_INDEX_OUT; + result = OMX_GetConfig(m_hHandle, + OMX_IndexConfigVideoFramerate, + &enc_framerate); + CHK(result); + FractionToQ16(enc_framerate.xEncodeFramerate,(int) (m_sProfile.nFramerate * 2),2); + result = OMX_SetConfig(m_hHandle, + OMX_IndexConfigVideoFramerate, + &enc_framerate); + CHK(result); + return OMX_ErrorNone; +} +//////////////////////////////////////////////////////////////////////////////// +void SendMessage(MsgId id, MsgData* data) +{ + pthread_mutex_lock(&m_mutex); + if (m_sMsgQ.size >= MAX_MSG) + { + E("main msg m_sMsgQ is full"); + return; + } + m_sMsgQ.q[(m_sMsgQ.head + m_sMsgQ.size) % MAX_MSG].id = id; + if (data) + m_sMsgQ.q[(m_sMsgQ.head + m_sMsgQ.size) % MAX_MSG].data = *data; + ++m_sMsgQ.size; + pthread_cond_signal(&m_signal); + pthread_mutex_unlock(&m_mutex); +} +//////////////////////////////////////////////////////////////////////////////// +void PopMessage(Msg* msg) +{ + pthread_mutex_lock(&m_mutex); + while (m_sMsgQ.size == 0) + { + pthread_cond_wait(&m_signal, &m_mutex); + } + *msg = m_sMsgQ.q[m_sMsgQ.head]; + --m_sMsgQ.size; + m_sMsgQ.head = (m_sMsgQ.head + 1) % MAX_MSG; + pthread_mutex_unlock(&m_mutex); +} +//////////////////////////////////////////////////////////////////////////////// +OMX_ERRORTYPE EVT_CB(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, + OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData) +{ +#define SET_STATE(eState) \ + case eState: \ + { \ + D("" # eState " complete"); \ + m_eState = eState; \ + break; \ + } + + if (eEvent == OMX_EventCmdComplete) + { + if ((OMX_COMMANDTYPE) nData1 == OMX_CommandStateSet) + { + switch ((OMX_STATETYPE) nData2) + { + SET_STATE(OMX_StateLoaded); + SET_STATE(OMX_StateIdle); + SET_STATE(OMX_StateExecuting); + SET_STATE(OMX_StateInvalid); + SET_STATE(OMX_StateWaitForResources); + SET_STATE(OMX_StatePause); + default: + E("invalid state %d", (int) nData2); + } + } + } + + else if (eEvent == OMX_EventError) + { + E("OMX_EventError"); + } + + else + { + E("unexpected event %d", (int) eEvent); + } + return OMX_ErrorNone; +} +//////////////////////////////////////////////////////////////////////////////// +OMX_ERRORTYPE EBD_CB(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) +{ + D("Got EBD callback ts=%lld", pBuffer->nTimeStamp); + + for (int i = 0; i < num_in_buffers; i++) + { + // mark this buffer ready for use again + if (m_pInBuffers[i] == pBuffer) + { + + D("Marked input buffer idx %d as free, buf %p", i, pBuffer->pBuffer); + m_bInFrameFree[i] = OMX_TRUE; + break; + } + } + + if (m_eMode == MODE_LIVE_ENCODE) + { + CameraTest_ReleaseFrame(pBuffer->pBuffer, + ((OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*)pBuffer->pAppPrivate)); + } + else + { + // wake up main thread and tell it to send next frame + MsgData data; + data.sBitstreamData.pBuffer = pBuffer; + SendMessage(MSG_ID_INPUT_FRAME_DONE, + &data); + + } + return OMX_ErrorNone; +} +//////////////////////////////////////////////////////////////////////////////// +OMX_ERRORTYPE FBD_CB(OMX_OUT OMX_HANDLETYPE hComponent, + OMX_OUT OMX_PTR pAppData, + OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) +{ + D("Got FBD callback ts=%lld", pBuffer->nTimeStamp); + + static long long prevTime = 0; + long long currTime = GetTimeStamp(); + + m_bWatchDogKicked = true; + + /* Empty Buffers should not be counted */ + if(pBuffer->nFilledLen !=0) + { + /* Counting Buffers supplied from OpneMax Encoder */ + fbd_cnt++; + tot_bufsize += pBuffer->nFilledLen; + } + if (prevTime != 0) + { + long long currTime = GetTimeStamp(); + D("FBD_DELTA = %lld\n", currTime - prevTime); + } + prevTime = currTime; + + if (m_eMode == MODE_PROFILE) + { + // if we are profiling we are not doing file I/O + // so just give back to encoder + if (OMX_FillThisBuffer(m_hHandle, pBuffer) != OMX_ErrorNone) + { + E("empty buffer failed for profiling"); + } + } + else + { + // wake up main thread and tell it to write to file + MsgData data; + data.sBitstreamData.pBuffer = pBuffer; + SendMessage(MSG_ID_OUTPUT_FRAME_DONE, + &data); + } + return OMX_ErrorNone; +} +//////////////////////////////////////////////////////////////////////////////// +OMX_ERRORTYPE VencTest_Initialize() +{ + OMX_ERRORTYPE result = OMX_ErrorNone; + static OMX_CALLBACKTYPE sCallbacks = {EVT_CB, EBD_CB, FBD_CB}; + int i; + + for (i = 0; i < num_in_buffers; i++) + { + m_pInBuffers[i] = NULL; + } + + result = OMX_Init(); + CHK(result); + + if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) + { + result = OMX_GetHandle(&m_hHandle, + "OMX.qcom.video.encoder.mpeg4", + NULL, + &sCallbacks); + // CHK(result); + } + else if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) + { + result = OMX_GetHandle(&m_hHandle, + "OMX.qcom.video.encoder.h263", + NULL, + &sCallbacks); + CHK(result); + } +#ifdef _MSM8974_ + else if (m_sProfile.eCodec == OMX_VIDEO_CodingVPX) + { + result = OMX_GetHandle(&m_hHandle, + "OMX.qcom.video.encoder.vp8", + NULL, + &sCallbacks); + CHK(result); + } +#endif + else + { + result = OMX_GetHandle(&m_hHandle, + "OMX.qcom.video.encoder.avc", + NULL, + &sCallbacks); + CHK(result); + } + + + result = ConfigureEncoder(); + CHK(result); + + return result; +} + +//////////////////////////////////////////////////////////////////////////////// +OMX_ERRORTYPE VencTest_RegisterYUVBuffer(OMX_BUFFERHEADERTYPE** ppBufferHeader, + OMX_U8 *pBuffer, + OMX_PTR pAppPrivate) +{ + OMX_ERRORTYPE result = OMX_ErrorNone; +#if 0 + D("register buffer"); + if ((result = OMX_AllocateBuffer(m_hHandle, + ppBufferHeader, + (OMX_U32) PORT_INDEX_IN, + pAppPrivate, + m_sProfile.nFrameBytes + )) != OMX_ErrorNone) + { + E("use buffer failed"); + } + else + { + E("Allocate Buffer Success %x", (*ppBufferHeader)->pBuffer); + } + #endif + D("register buffer"); + D("Calling UseBuffer for Input port"); + if ((result = OMX_UseBuffer(m_hHandle, + ppBufferHeader, + (OMX_U32) PORT_INDEX_IN, + pAppPrivate, + m_sProfile.nFrameBytes, + pBuffer)) != OMX_ErrorNone) + { + E("use buffer failed"); + } + + return result; +} +//////////////////////////////////////////////////////////////////////////////// +OMX_ERRORTYPE VencTest_EncodeFrame(void* pYUVBuff, + long long nTimeStamp) +{ + OMX_ERRORTYPE result = OMX_ErrorUndefined; + D("calling OMX empty this buffer"); + for (int i = 0; i < num_in_buffers; i++) + { + if (pYUVBuff == m_pInBuffers[i]->pBuffer) + { + m_pInBuffers[i]->nTimeStamp = nTimeStamp; + D("Sending Buffer - %x", m_pInBuffers[i]->pBuffer); + result = OMX_EmptyThisBuffer(m_hHandle, + m_pInBuffers[i]); + /* Counting Buffers supplied to OpenMax Encoder */ + if(OMX_ErrorNone == result) + ebd_cnt++; + CHK(result); + break; + } + } + return result; +} +//////////////////////////////////////////////////////////////////////////////// +OMX_ERRORTYPE VencTest_Exit(void) +{ + int i; + OMX_ERRORTYPE result = OMX_ErrorNone; + D("trying to exit venc"); + + D("going to idle state"); + SetState(OMX_StateIdle); + + + D("going to loaded state"); + //SetState(OMX_StateLoaded); + OMX_SendCommand(m_hHandle, + OMX_CommandStateSet, + (OMX_U32) OMX_StateLoaded, + NULL); + + for (i = 0; i < num_in_buffers; i++) + { + D("free buffer"); + if (m_pInBuffers[i]->pBuffer) + { + // free(m_pInBuffers[i]->pBuffer); + result = OMX_FreeBuffer(m_hHandle, + PORT_INDEX_IN, + m_pInBuffers[i]); + CHK(result); + } + else + { + E("buffer %d is null", i); + result = OMX_ErrorUndefined; + CHK(result); + } + } + for (i = 0; i < num_out_buffers; i++) + { + D("free buffer"); + if (m_pOutBuffers[i]->pBuffer) + { + free(m_pOutBuffers[i]->pBuffer); + result = OMX_FreeBuffer(m_hHandle, + PORT_INDEX_OUT, + m_pOutBuffers[i]); + CHK(result); + + } + else + { + E("buffer %d is null", i); + result = OMX_ErrorUndefined; + CHK(result); + } + } + + while (m_eState != OMX_StateLoaded) + { + sleep(1); + } + D("component_deinit..."); + result = OMX_Deinit(); + CHK(result); + + D("venc is exiting..."); + return result; +} +//////////////////////////////////////////////////////////////////////////////// + +void VencTest_ReadDynamicConfigMsg() +{ + char frame_n[8], config[16], param[8]; + char *dest = frame_n; + bool end = false; + int cntr, nparam = 0; + memset(&dynamic_config, 0, sizeof(struct DynamicConfig)); + do + { + cntr = -1; + do + { + dest[++cntr] = fgetc(m_pDynConfFile); + } while(dest[cntr] != ' ' && dest[cntr] != '\t' && dest[cntr] != '\n' && dest[cntr] != '\r' && !feof(m_pDynConfFile)); + if (dest[cntr] == '\n' || dest[cntr] == '\r') + end = true; + dest[cntr] = NULL; + if (dest == frame_n) + dest = config; + else if (dest == config) + dest = param; + else + end = true; + nparam++; + } while (!end && !feof(m_pDynConfFile)); + + if (nparam > 1) + { + dynamic_config.pending = true; + dynamic_config.frame_num = atoi(frame_n); + if (!strcmp(config, "bitrate")) + { + dynamic_config.config_param = OMX_IndexConfigVideoBitrate; + dynamic_config.config_data.bitrate.nPortIndex = PORT_INDEX_OUT; + dynamic_config.config_data.bitrate.nEncodeBitrate = strtoul(param, NULL, 10); + } + else if (!strcmp(config, "framerate")) + { + dynamic_config.config_param = OMX_IndexConfigVideoFramerate; + dynamic_config.config_data.framerate.nPortIndex = PORT_INDEX_OUT; + dynamic_config.config_data.f_framerate = atof(param); + } + else if (!strcmp(config, "iperiod")) + { + dynamic_config.config_param = (OMX_INDEXTYPE)QOMX_IndexConfigVideoIntraperiod; + dynamic_config.config_data.intraperiod.nPortIndex = PORT_INDEX_OUT; + dynamic_config.config_data.intraperiod.nPFrames = strtoul(param, NULL, 10) - 1; + dynamic_config.config_data.intraperiod.nIDRPeriod = 1; // This value is ignored in OMX component + } + else if (!strcmp(config, "ivoprefresh")) + { + dynamic_config.config_param = OMX_IndexConfigVideoIntraVOPRefresh; + dynamic_config.config_data.intravoprefresh.nPortIndex = PORT_INDEX_OUT; + dynamic_config.config_data.intravoprefresh.IntraRefreshVOP = OMX_TRUE; + } + else if (!strcmp(config, "rotation")) + { + dynamic_config.config_param = OMX_IndexConfigCommonRotate; + dynamic_config.config_data.rotation.nPortIndex = PORT_INDEX_OUT; + dynamic_config.config_data.rotation.nRotation = strtoul(param, NULL, 10); + } + else + { + E("UNKNOWN CONFIG PARAMETER: %s!", config); + dynamic_config.pending = false; + } + } + else if (feof(m_pDynConfFile)) + { + fclose(m_pDynConfFile); + m_pDynConfFile = NULL; + } +} + +void VencTest_ProcessDynamicConfigurationFile() +{ + do + { + if (dynamic_config.pending) + { + if(m_nFrameIn == dynamic_config.frame_num) + { + if (dynamic_config.config_param == OMX_IndexConfigVideoFramerate) + { + m_sProfile.nFramerate = dynamic_config.config_data.f_framerate; + FractionToQ16(dynamic_config.config_data.framerate.xEncodeFramerate, + (int)(m_sProfile.nFramerate * 2), 2); + } + if (OMX_SetConfig(m_hHandle, dynamic_config.config_param, + &dynamic_config.config_data) != OMX_ErrorNone) + E("ERROR: Setting dynamic config to OMX param[0x%x]", dynamic_config.config_param); + dynamic_config.pending = false; + } + else if (m_nFrameIn > dynamic_config.frame_num) + { + E("WARNING: Config change requested in passed frame(%d)", dynamic_config.frame_num); + dynamic_config.pending = false; + } + } + if (!dynamic_config.pending) + VencTest_ReadDynamicConfigMsg(); + } while (!dynamic_config.pending && m_pDynConfFile); +} + +//////////////////////////////////////////////////////////////////////////////// +OMX_ERRORTYPE VencTest_ReadAndEmpty(OMX_BUFFERHEADERTYPE* pYUVBuffer) +{ + OMX_ERRORTYPE result = OMX_ErrorNone; +#ifdef T_ARM +#ifdef MAX_RES_720P + if (read(m_nInFd, + pYUVBuffer->pBuffer, + m_sProfile.nFrameBytes) != m_sProfile.nFrameBytes) + { + return OMX_ErrorUndefined; + } +#elif _MSM8974_ + int bytes; + bytes = read(m_nInFd, pYUVBuffer->pBuffer, m_sProfile.nFrameRead); + if (bytes != m_sProfile.nFrameRead) { + E("read failed: %d != %d\n", read, m_sProfile.nFrameRead); + return OMX_ErrorUndefined; + } + E("\n\nRead %d bytes\n\n\n", m_sProfile.nFrameRead); +#else + OMX_U32 bytestoread = m_sProfile.nFrameWidth*m_sProfile.nFrameHeight; + // read Y first + if (read(m_nInFd, + pYUVBuffer->pBuffer, + bytestoread) != bytestoread) + return OMX_ErrorUndefined; + + // check alignment for offset to C + OMX_U32 offset_to_c = m_sProfile.nFrameWidth * m_sProfile.nFrameHeight; + + const OMX_U32 C_2K = (1024*2), + MASK_2K = C_2K-1, + IMASK_2K = ~MASK_2K; + + if (offset_to_c & MASK_2K) + { + // offset to C is not 2k aligned, adjustment is required + offset_to_c = (offset_to_c & IMASK_2K) + C_2K; + } + + bytestoread = m_sProfile.nFrameWidth*m_sProfile.nFrameHeight/2; + // read C + if (read(m_nInFd, + pYUVBuffer->pBuffer + offset_to_c, + bytestoread)!= bytestoread) + return OMX_ErrorUndefined; +#endif +#else + { + char * pInputbuf = (char *)(pYUVBuffer->pBuffer) ; + read(m_nInFd,pInputbuf,m_sProfile.nFrameBytes) ; + + } +#endif + if (m_pDynConfFile) + VencTest_ProcessDynamicConfigurationFile(); + D("about to call VencTest_EncodeFrame..."); + pthread_mutex_lock(&m_mutex); + ++m_nFrameIn; +#ifdef _MSM8974_ + pYUVBuffer->nFilledLen = m_sProfile.nFrameRead; +#else + pYUVBuffer->nFilledLen = m_sProfile.nFrameBytes; +#endif + D("Called Buffer with Data filled length %d",pYUVBuffer->nFilledLen); + + result = VencTest_EncodeFrame(pYUVBuffer->pBuffer, + m_nTimeStamp); + + m_nTimeStamp += (1000000) / m_sProfile.nFramerate; + CHK(result); + pthread_mutex_unlock(&m_mutex); + return result; +} +//////////////////////////////////////////////////////////////////////////////// +void PreviewCallback(int nFD, + int nOffset, + void* pPhys, + void* pVirt, + long long nTimeStamp) +{ + + D("================= preview frame %d, phys=0x%x, nTimeStamp(millis)=%lld", + m_nFrameIn+1, pPhys, (nTimeStamp / 1000)); + + if (m_nFrameIn == m_nFramePlay && + m_nFramePlay != 0) + { + // we will stop camera after last frame is encoded. + // for now just ignore input frames + + CameraTest_ReleaseFrame(pPhys, pVirt); + return; + } + + // see if we should stop + pthread_mutex_lock(&m_mutex); + ++m_nFrameIn; + pthread_mutex_unlock(&m_mutex); + + + if (m_eMode == MODE_LIVE_ENCODE) + { + + OMX_ERRORTYPE result; + + // register new camera buffers with encoder + int i; + for (i = 0; i < num_in_buffers; i++) + { + if (m_pInBuffers[i] != NULL && + m_pInBuffers[i]->pBuffer == pPhys) + { + break; + } + else if (m_pInBuffers[i] == NULL) + { + D("registering buffer..."); + result = VencTest_RegisterYUVBuffer(&m_pInBuffers[i], + (OMX_U8*) pPhys, + (OMX_PTR) pVirt); // store virt in app private field + D("register done"); + CHK(result); + break; + } + } + + if (i == num_in_buffers) + { + E("There are more camera buffers than we thought"); + CHK(1); + } + + // encode the yuv frame + + D("StartEncodeTime=%lld", GetTimeStamp()); + result = VencTest_EncodeFrame(pPhys, + nTimeStamp); + CHK(result); + // FBTest_DisplayImage(nFD, nOffset); + } + else + { + // FBTest_DisplayImage(nFD, nOffset); + CameraTest_ReleaseFrame(pPhys, pVirt); + } +} +//////////////////////////////////////////////////////////////////////////////// +void usage(char* filename) +{ + char* fname = strrchr(filename, (int) '/'); + fname = (fname == NULL) ? filename : fname; + + fprintf(stderr, "usage: %s LIVE \n", fname); + fprintf(stderr, "usage: %s FILE ", fname); + fprintf(stderr, " \n", fname); + fprintf(stderr, "usage: %s PROFILE \n", fname); + fprintf(stderr, "usage: %s PREVIEW \n", fname); + fprintf(stderr, "usage: %s DISPLAY \n", fname); + fprintf(stderr, "\n BITRATE - bitrate in kbps\n"); + fprintf(stderr, " FPS - frames per second\n"); + fprintf(stderr, " NFRAMES - number of frames to play, 0 for infinite\n"); + fprintf(stderr, " RateControl (Values 0 - 4 for RC_OFF, RC_CBR_CFR, RC_CBR_VFR, RC_VBR_CFR, RC_VBR_VFR\n"); + exit(1); +} + +bool parseWxH(char *str, OMX_U32 *width, OMX_U32 *height) +{ + bool parseOK = false; + const char delimiters[] = " x*,"; + char *token, *dupstr, *temp; + OMX_U32 w, h; + + dupstr = strdup(str); + token = strtok_r(dupstr, delimiters, &temp); + if (token) + { + w = strtoul(token, NULL, 10); + token = strtok_r(NULL, delimiters, &temp); + if (token) + { + h = strtoul(token, NULL, 10); + if (w != ULONG_MAX && h != ULONG_MAX) + { +#ifdef MAX_RES_720P + if ((w * h >> 8) <= 3600) + { + parseOK = true; + *width = w; + *height = h; + } +#else + if ((w * h >> 8) <= 8160) + { + parseOK = true; + *width = w; + *height = h; + } +#endif + else + E("\nInvalid dimensions %dx%d",w,h); + } + } + } + free(dupstr); + return parseOK; +} + +//////////////////////////////////////////////////////////////////////////////// +void parseArgs(int argc, char** argv) +{ + int dyn_file_arg = argc; + if (argc == 1) + { + usage(argv[0]); + } + else if (strcmp("PREVIEW", argv[1]) == 0 || + strcmp("preview", argv[1]) == 0) + { + m_eMode = MODE_PREVIEW; + if (argc != 5) + { + usage(argv[0]); + } + } + else if (strcmp("DISPLAY", argv[1]) == 0 || + strcmp("display", argv[1]) == 0) + { + m_eMode = MODE_DISPLAY; + if (argc != 6) + { + usage(argv[0]); + } + m_sProfile.cInFileName = argv[5]; + m_sProfile.cOutFileName = NULL; + } + else if (strcmp("LIVE", argv[1]) == 0 || + strcmp("live", argv[1]) == 0) + {//263 + m_eMode = MODE_LIVE_ENCODE; + if (argc != 8) + { + usage(argv[0]); + } + m_sProfile.cInFileName = NULL; + m_sProfile.cOutFileName = argv[7]; + } + else if (strcmp("FILE", argv[1]) == 0 || + strcmp("file", argv[1]) == 0) + {//263 + m_eMode = MODE_FILE_ENCODE; + + if(argc < 9 || argc > 13) + { + usage(argv[0]); + } + else + { + if (argc > 9) + dyn_file_arg = 9; + + if (argc > 10) + { + m_sProfile.eControlRate = OMX_Video_ControlRateVariable; + int RC = atoi(argv[10]); + + switch (RC) + { + case 0: + m_sProfile.eControlRate = OMX_Video_ControlRateDisable ;//VENC_RC_NONE + break; + case 1: + m_sProfile.eControlRate = OMX_Video_ControlRateConstant;//VENC_RC_CBR_CFR + break; + + case 2: + m_sProfile.eControlRate = OMX_Video_ControlRateConstantSkipFrames;//VENC_RC_CBR_VFR + break; + + case 3: + m_sProfile.eControlRate =OMX_Video_ControlRateVariable ;//VENC_RC_VBR_CFR + break; + + case 4: + m_sProfile.eControlRate = OMX_Video_ControlRateVariableSkipFrames;//VENC_RC_VBR_VFR + break; + + default: + E("invalid rate control selection"); + m_sProfile.eControlRate = OMX_Video_ControlRateVariable; //VENC_RC_VBR_CFR + break; + } + } + + if (argc > 11) + { + int profile_argi = 11; + if(!strcmp(argv[3], "H264") || !strcmp(argv[3], "h264")) + { + profile_argi = 12; + D("\nSetting AVCSliceMode ... "); + int AVCSliceMode = atoi(argv[11]); + switch(AVCSliceMode) + { + case 0: + m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault; + break; + + case 1: + m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCMBSlice; + break; + + case 2: + m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCByteSlice; + break; + + default: + E("invalid Slice Mode"); + m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault; + break; + } + } + if (profile_argi < argc) + { + if (!strncmp(argv[profile_argi], "0x", 2) || !strncmp(argv[profile_argi], "0x", 2)) + { + m_sProfile.nUserProfile = strtoul(argv[profile_argi], NULL, 16); + } + else + { + m_sProfile.nUserProfile = strtoul(argv[profile_argi], NULL, 10); + } + if (!m_sProfile.nUserProfile || m_sProfile.nUserProfile == ULONG_MAX) + { + E("invalid specified Profile %s, using default", argv[profile_argi]); + m_sProfile.nUserProfile = 0; + } + } + } + } + m_sProfile.cInFileName = argv[7]; + m_sProfile.cOutFileName = argv[8]; + } + else if (strcmp("PROFILE", argv[1]) == 0 || + strcmp("profile", argv[1]) == 0) + {//263 + m_eMode = MODE_PROFILE; + if (argc != 8) + { + usage(argv[0]); + } + m_sProfile.cInFileName = argv[7]; + m_sProfile.cOutFileName = NULL; + } + else + { + usage(argv[0]); + } + + + if (strcmp("QCIF", argv[2]) == 0 || + strcmp("qcif", argv[2]) == 0) + { + m_sProfile.nFrameWidth = 176; + m_sProfile.nFrameHeight = 144; + m_sProfile.nFrameBytes = 176*144*3/2; + m_sProfile.eLevel = OMX_VIDEO_MPEG4Level0; + } + else if (strcmp("QVGA", argv[2]) == 0 || + strcmp("qvga", argv[2]) == 0) + { + m_sProfile.nFrameWidth = 320; + m_sProfile.nFrameHeight = 240; + m_sProfile.nFrameBytes = 320*240*3/2; + m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; + } + + + else if (strcmp("VGA", argv[2]) == 0 || + strcmp("vga", argv[2]) == 0) + { + m_sProfile.nFrameWidth = 640; + m_sProfile.nFrameHeight = 480; + m_sProfile.nFrameBytes = 640*480*3/2; + m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; + } + + else if (strcmp("WVGA", argv[2]) == 0 || + strcmp("wvga", argv[2]) == 0) + { + m_sProfile.nFrameWidth = 800; + m_sProfile.nFrameHeight = 480; + m_sProfile.nFrameBytes = 800*480*3/2; + m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; + } + else if (strcmp("CIF", argv[2]) == 0 || + strcmp("cif", argv[2]) == 0) + { + m_sProfile.nFrameWidth = 352; + m_sProfile.nFrameHeight = 288; + m_sProfile.nFrameBytes = 352*288*3/2; + m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; + } + else if (strcmp("720", argv[2]) == 0) + { + m_sProfile.nFrameWidth = 1280; + m_sProfile.nFrameHeight = 720; + m_sProfile.nFrameBytes = 720*1280*3/2; + m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; + } + else if (strcmp("1080", argv[2]) == 0) + { + m_sProfile.nFrameWidth = 1920; + m_sProfile.nFrameHeight = 1080; + m_sProfile.nFrameBytes = 1920*1080*3/2; + m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; + } +#ifdef _MSM8974_ + else if (strcmp("4K2K", argv[2]) == 0) + { + m_sProfile.nFrameWidth = 4096; + m_sProfile.nFrameHeight = 2160; + m_sProfile.nFrameBytes = 4096*2160*3/2; + m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; + } + else if (strcmp("2160P", argv[2]) == 0) + { + m_sProfile.nFrameWidth = 3840; + m_sProfile.nFrameHeight = 2160; + m_sProfile.nFrameBytes = 3840*2160*3/2; + m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; + } +#endif + else if (parseWxH(argv[2], &m_sProfile.nFrameWidth, &m_sProfile.nFrameHeight)) + { + m_sProfile.nFrameBytes = m_sProfile.nFrameWidth*m_sProfile.nFrameHeight*3/2; + m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1; + } + else + { + usage(argv[0]); + } + +#ifdef _MSM8974_ + m_sProfile.nFramestride = (m_sProfile.nFrameWidth + 31) & (~31); + m_sProfile.nFrameScanlines = (m_sProfile.nFrameHeight + 31) & (~31); + m_sProfile.nFrameBytes = ((m_sProfile.nFramestride * m_sProfile.nFrameScanlines * 3/2) + 4095) & (~4095); + m_sProfile.nFrameRead = m_sProfile.nFramestride * m_sProfile.nFrameScanlines * 3/2; +#endif + if (m_eMode == MODE_DISPLAY || + m_eMode == MODE_PREVIEW) + { + m_sProfile.nFramerate = atof(argv[3]); + m_nFramePlay = atoi(argv[4]); + + } + else if (m_eMode == MODE_LIVE_ENCODE || + m_eMode == MODE_FILE_ENCODE || + m_eMode == MODE_PROFILE) + { + if ((!strcmp(argv[3], "MP4")) || (!strcmp(argv[3], "mp4"))) + { + m_sProfile.eCodec = OMX_VIDEO_CodingMPEG4; + } + else if ((!strcmp(argv[3], "H263")) || (!strcmp(argv[3], "h263"))) + { + m_sProfile.eCodec = OMX_VIDEO_CodingH263; + } + else if ((!strcmp(argv[3], "H264")) || (!strcmp(argv[3], "h264"))) + { + m_sProfile.eCodec = OMX_VIDEO_CodingAVC; + } +#ifdef _MSM8974_ + else if ((!strcmp(argv[3], "VP8")) || (!strcmp(argv[3], "vp8"))) + { + m_sProfile.eCodec = OMX_VIDEO_CodingVPX; + } +#endif + else + { + usage(argv[0]); + } + + m_sProfile.nFramerate = atof(argv[4]); + m_sProfile.nBitrate = atoi(argv[5]); +// m_sProfile.eControlRate = OMX_Video_ControlRateVariable; + m_nFramePlay = atoi(argv[6]); + if (dyn_file_arg < argc) + { + m_pDynConfFile = fopen(argv[dyn_file_arg], "r"); + if (!m_pDynConfFile) + E("ERROR: Cannot open dynamic config file: %s", argv[dyn_file_arg]); + else + { + memset(&dynamic_config, 0, sizeof(struct DynamicConfig)); + } + } + } +} + +void* Watchdog(void* data) +{ + while (1) + { + sleep(1000); + if (m_bWatchDogKicked == true) + m_bWatchDogKicked = false; + else + E("watchdog has not been kicked. we may have a deadlock"); + } + return NULL; +} + +int main(int argc, char** argv) +{ + OMX_U8* pvirt = NULL; + int result; + float enc_time_sec=0.0,enc_time_usec=0.0; + + m_nInFd = -1; + m_nOutFd = -1; + m_nTimeStamp = 0; + m_nFrameIn = 0; + m_nFrameOut = 0; + + memset(&m_sMsgQ, 0, sizeof(MsgQ)); + parseArgs(argc, argv); + + D("fps=%d, bitrate=%d, width=%d, height=%d", + m_sProfile.nFramerate, + m_sProfile.nBitrate, + m_sProfile.nFrameWidth, + m_sProfile.nFrameHeight); + + + //if (m_eMode != MODE_PREVIEW && m_eMode != MODE_DISPLAY) + //{ + // pthread_t wd; + // pthread_create(&wd, NULL, Watchdog, NULL); + //} + + for (int x = 0; x < num_in_buffers; x++) + { + // mark all buffers as ready to use + m_bInFrameFree[x] = OMX_TRUE; + } + + + if (m_eMode != MODE_PROFILE) + { + #if T_ARM + m_nOutFd = open(m_sProfile.cOutFileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); + #else + m_nOutFd = open(m_sProfile.cOutFileName,0); + #endif + if (m_nOutFd < 0) + { + E("could not open output file %s", m_sProfile.cOutFileName); + CHK(1); + } + } + + pthread_mutex_init(&m_mutex, NULL); + pthread_cond_init(&m_signal, NULL); + + if (m_eMode != MODE_PREVIEW) + { + VencTest_Initialize(); + } + + //////////////////////////////////////// + // Camera + Encode + //////////////////////////////////////// + if (m_eMode == MODE_LIVE_ENCODE) + { + CameraTest_Initialize(m_sProfile.nFramerate, + m_sProfile.nFrameWidth, + m_sProfile.nFrameHeight, + PreviewCallback); + CameraTest_Run(); + } + + if (m_eMode == MODE_FILE_ENCODE || + m_eMode == MODE_PROFILE) + { + int i; + #if T_ARM + m_nInFd = open(m_sProfile.cInFileName, O_RDONLY); + #else + m_nInFd = open(m_sProfile.cInFileName,1); + #endif + if (m_nInFd < 0) + { + E("could not open input file"); + CHK(1); + + } + D("going to idle state"); + //SetState(OMX_StateIdle); + OMX_SendCommand(m_hHandle, + OMX_CommandStateSet, + (OMX_U32) OMX_StateIdle, + NULL); + + OMX_PARAM_PORTDEFINITIONTYPE portDef; + + portDef.nPortIndex = 0; + result = OMX_GetParameter(m_hHandle, OMX_IndexParamPortDefinition, &portDef); + CHK(result); + + D("allocating Input buffers"); + num_in_buffers = portDef.nBufferCountActual; + for (i = 0; i < portDef.nBufferCountActual; i++) + { + OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem = new OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO; + pvirt = (OMX_U8*)PmemMalloc(pMem, m_sProfile.nFrameBytes); + + if(pvirt == NULL) + { + CHK(1); + } + result = VencTest_RegisterYUVBuffer(&m_pInBuffers[i], + (OMX_U8*) pvirt, + (OMX_PTR) pMem); + CHK(result); + } + } + else if (m_eMode == MODE_LIVE_ENCODE) + { + D("going to idle state"); + //SetState(OMX_StateIdle); + OMX_SendCommand(m_hHandle, + OMX_CommandStateSet, + (OMX_U32) OMX_StateIdle, + NULL); + } + + int i; + OMX_PARAM_PORTDEFINITIONTYPE portDef; + + portDef.nPortIndex = 1; + result = OMX_GetParameter(m_hHandle, OMX_IndexParamPortDefinition, &portDef); + CHK(result); + + D("allocating & calling usebuffer for Output port"); + num_out_buffers = portDef.nBufferCountActual; + for (i = 0; i < portDef.nBufferCountActual; i++) + { + void* pBuff; + + pBuff = malloc(portDef.nBufferSize); + D("portDef.nBufferSize = %d ",portDef.nBufferSize); + result = OMX_UseBuffer(m_hHandle, + &m_pOutBuffers[i], + (OMX_U32) PORT_INDEX_OUT, + NULL, + portDef.nBufferSize, + (OMX_U8*) pBuff); + CHK(result); + } + D("allocate done"); + + // D("Going to state " # eState"..."); + + while (m_eState != OMX_StateIdle) + { + sleep(1); + } + //D("Now in state " # eState); + + + D("going to executing state"); + SetState(OMX_StateExecuting); + for (i = 0; i < num_out_buffers; i++) + { + D("filling buffer %d", i); + result = OMX_FillThisBuffer(m_hHandle, m_pOutBuffers[i]); + //sleep(1000); + CHK(result); + } + + if (m_eMode == MODE_FILE_ENCODE) + { + // encode the first frame to kick off the whole process + VencTest_ReadAndEmpty(m_pInBuffers[0]); + // FBTest_DisplayImage(((PmemBuffer*) m_pInBuffers[0]->pAppPrivate)->fd,0); + } + + if (m_eMode == MODE_PROFILE) + { + int i; + + // read several frames into memory + D("reading frames into memory"); + for (i = 0; i < num_in_buffers; i++) + { + D("[%d] address 0x%x",i, m_pInBuffers[i]->pBuffer); +#ifdef MAX_RES_720P + read(m_nInFd, + m_pInBuffers[i]->pBuffer, + m_sProfile.nFrameBytes); +#else + // read Y first + read(m_nInFd, + m_pInBuffers[i]->pBuffer, + m_sProfile.nFrameWidth*m_sProfile.nFrameHeight); + + // check alignment for offset to C + OMX_U32 offset_to_c = m_sProfile.nFrameWidth * m_sProfile.nFrameHeight; + + const OMX_U32 C_2K = (1024*2), + MASK_2K = C_2K-1, + IMASK_2K = ~MASK_2K; + + if (offset_to_c & MASK_2K) + { + // offset to C is not 2k aligned, adjustment is required + offset_to_c = (offset_to_c & IMASK_2K) + C_2K; + } + + // read C + read(m_nInFd, + m_pInBuffers[i]->pBuffer + offset_to_c, + m_sProfile.nFrameWidth*m_sProfile.nFrameHeight/2); +#endif + + } + + // FBTest_Initialize(m_sProfile.nFrameWidth, m_sProfile.nFrameHeight); + + // loop over the mem-resident frames and encode them + D("beging playing mem-resident frames..."); + for (i = 0; m_nFramePlay == 0 || i < m_nFramePlay; i++) + { + int idx = i % num_in_buffers; + if (m_bInFrameFree[idx] == OMX_FALSE) + { + int j; + E("the expected buffer is not free, but lets find another"); + + idx = -1; + + // lets see if we can find another free buffer + for (j = 0; j < num_in_buffers; j++) + { + if(m_bInFrameFree[j]) + { + idx = j; + break; + } + } + } + + // if we have a free buffer let's encode it + if (idx >= 0) + { + D("encode frame %d...m_pInBuffers[idx]->pBuffer=0x%x", i,m_pInBuffers[idx]->pBuffer); + m_bInFrameFree[idx] = OMX_FALSE; + VencTest_EncodeFrame(m_pInBuffers[idx]->pBuffer, + m_nTimeStamp); + D("display frame %d...", i); + // FBTest_DisplayImage(((PmemBuffer*) m_pInBuffers[idx]->pAppPrivate)->fd,0); + m_nTimeStamp += 1000000 / m_sProfile.nFramerate; + } + else + { + E("wow, no buffers are free, performance " + "is not so good. lets just sleep some more"); + + } + D("sleep for %d microsec", 1000000/m_sProfile.nFramerate); + sleep (1000000 / m_sProfile.nFramerate); + } + // FBTest_Exit(); + } + + Msg msg; + bool bQuit = false; + while ((m_eMode == MODE_FILE_ENCODE || m_eMode == MODE_LIVE_ENCODE) && + !bQuit) + { + PopMessage(&msg); + switch (msg.id) + { + ////////////////////////////////// + // FRAME IS ENCODED + ////////////////////////////////// + case MSG_ID_INPUT_FRAME_DONE: + /*pthread_mutex_lock(&m_mutex); + ++m_nFrameOut; + if (m_nFrameOut == m_nFramePlay && m_nFramePlay != 0) + { + bQuit = true; + } + pthread_mutex_unlock(&m_mutex);*/ + + if (!bQuit && m_eMode == MODE_FILE_ENCODE) + { + D("pushing another frame down to encoder"); + if (VencTest_ReadAndEmpty(msg.data.sBitstreamData.pBuffer)) + { + // we have read the last frame + D("main is exiting..."); + bQuit = true; + } + } + break; + case MSG_ID_OUTPUT_FRAME_DONE: + D("================ writing frame %d = %d bytes to output file", + m_nFrameOut+1, + msg.data.sBitstreamData.pBuffer->nFilledLen); + D("StopEncodeTime=%lld", GetTimeStamp()); + + + write(m_nOutFd, + msg.data.sBitstreamData.pBuffer->pBuffer, + msg.data.sBitstreamData.pBuffer->nFilledLen); + + + result = OMX_FillThisBuffer(m_hHandle, + msg.data.sBitstreamData.pBuffer); + + if (result != OMX_ErrorNone) + { + CHK(result); + } + + pthread_mutex_lock(&m_mutex); + ++m_nFrameOut; + if (m_nFrameOut == m_nFramePlay && m_nFramePlay != 0) + { + bQuit = true; + } + pthread_mutex_unlock(&m_mutex); + break; + + default: + E("invalid msg id %d", (int) msg.id); + } // end switch (msg.id) + +/* // TO UNCOMMENT FOR PAUSE TESTINGS + if(m_nFrameOut == 10) + { + E("\nGoing to Pause state\n"); + SetState(OMX_StatePause); + sleep(3); +//REQUEST AN I FRAME AFTER PAUSE + OMX_CONFIG_INTRAREFRESHVOPTYPE voprefresh; + voprefresh.nPortIndex = (OMX_U32)PORT_INDEX_OUT; + voprefresh.IntraRefreshVOP = OMX_TRUE; + result = OMX_SetConfig(m_hHandle, + OMX_IndexConfigVideoIntraVOPRefresh, + &voprefresh); + E("\n OMX_IndexConfigVideoIntraVOPRefresh Set Paramter port"); + CHK(result); + E("\nGoing to executing state\n"); + SetState(OMX_StateExecuting); + } +*/ + } // end while (!bQuit) + + + if (m_eMode == MODE_LIVE_ENCODE) + { + CameraTest_Exit(); + close(m_nOutFd); + } + else if (m_eMode == MODE_FILE_ENCODE || + m_eMode == MODE_PROFILE) + { + // deallocate pmem buffers + for (int i = 0; i < num_in_buffers; i++) + { + PmemFree((OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*)m_pInBuffers[i]->pAppPrivate, + m_pInBuffers[i]->pBuffer, + m_sProfile.nFrameBytes); + delete (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*) m_pInBuffers[i]->pAppPrivate; + } + close(m_nInFd); + + if (m_eMode == MODE_FILE_ENCODE) + { + close(m_nOutFd); + } + if (m_pDynConfFile) + { + fclose(m_pDynConfFile); + m_pDynConfFile = NULL; + } + } + + if (m_eMode != MODE_PREVIEW) + { + D("exit encoder test"); + VencTest_Exit(); + } + + pthread_mutex_destroy(&m_mutex); + pthread_cond_destroy(&m_signal); + + /* Time Statistics Logging */ + if(0 != m_sProfile.nFramerate) + { + enc_time_usec = m_nTimeStamp - (1000000 / m_sProfile.nFramerate); + enc_time_sec =enc_time_usec/1000000; + if(0 != enc_time_sec) + { + printf("Total Frame Rate: %f",ebd_cnt/enc_time_sec); + printf("\nEncoder Bitrate :%lf Kbps",(tot_bufsize*8)/(enc_time_sec*1000)); + } + } + else + { + printf("\n\n Encode Time is zero"); + } + printf("\nTotal Number of Frames :%d",ebd_cnt); + printf("\nNumber of dropped frames during encoding:%d\n",ebd_cnt-fbd_cnt); + /* End of Time Statistics Logging */ + + D("main has exited"); + return 0; +} diff --git a/mm-video/vidc/venc/test/venc_util.c b/mm-video/vidc/venc/test/venc_util.c new file mode 100755 index 0000000..1f03810 --- /dev/null +++ b/mm-video/vidc/venc/test/venc_util.c @@ -0,0 +1,51 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +/*============================================================================ + V E N C _ U T I L. C + +DESCRIPTION + + +REFERENCES + +============================================================================*/ + +#include "venc_util.h" +#include +#include + +long long GetTimeStamp() +{ + struct timeval tv; + long long microsec; + gettimeofday(&tv, NULL); + microsec = (tv.tv_sec * 1000000) + (tv.tv_usec); + return microsec; + +} + diff --git a/mm-video/vidc/venc/test/video_encoder_test.c b/mm-video/vidc/venc/test/video_encoder_test.c new file mode 100755 index 0000000..0eb5f3c --- /dev/null +++ b/mm-video/vidc/venc/test/video_encoder_test.c @@ -0,0 +1,1064 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Code Aurora nor + the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include "video_encoder_test.h" + +#define DEBUG_PRINT printf +/************************************************************************/ +/* #DEFINES */ +/************************************************************************/ + +#define VOP_START_CODE 0x000001B6 +#define SHORT_HEADER_START_CODE 0x00008000 +#define H264_START_CODE 0x00000001 + +/************************************************************************/ +/* STATIC VARIABLES */ +/************************************************************************/ + +static int Code_type; +static int total_frames = 0; +static unsigned int header_code = 0; +static pthread_mutex_t read_lock; + +static unsigned int read_frame ( unsigned char *dataptr,unsigned int length, + FILE * inputBufferFile + ); +static unsigned clp2(unsigned x) +{ + x = x - 1; + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >>16); + return x + 1; +} + + +static void* video_thread (void *); +static void* async_thread (void *); + + + +int main (int argc, char **argv) +{ + struct video_encoder_context *encoder_context = NULL; + char *file_name = NULL; + FILE *file_ptr = NULL; + int temp1 =0,temp2 =0; + int error = 1; + unsigned int i = 0; + + file_name = argv [1]; + file_ptr = fopen (file_name,"rb"); + + if (file_ptr == NULL) + { + DEBUG_PRINT("\n File is not located "); + return -1; + } + + + encoder_context = (struct video_encoder_context *) \ + calloc (sizeof (struct video_encoder_context),1); + if (encoder_context == NULL) + { + return -1; + } + encoder_context->outputBufferFile = NULL; + encoder_context->inputBufferFile = NULL; + encoder_context->video_driver_fd = -1; + encoder_context->inputBufferFile = file_ptr; + encoder_context->input_width = 176; + encoder_context->input_height = 144; + encoder_context->codectype = VEN_CODEC_MPEG4; + encoder_context->fps_num = 60; + encoder_context->fps_den = 2; + encoder_context->inputformat = VEN_INPUTFMT_NV12; + encoder_context->targetbitrate = 128000; + + file_ptr = fopen ("/data/output.m4v","wb"); + if (file_ptr == NULL) + { + DEBUG_PRINT("\n File can't be created"); + free (encoder_context); + return -1; + } + encoder_context->outputBufferFile = file_ptr; + + switch (atoi(argv[2])) + { + case 0: + DEBUG_PRINT("\n MPEG4 codec selected"); + encoder_context->codectype = VEN_CODEC_MPEG4; + Code_type = 0; + break; + case 1: + DEBUG_PRINT("\n H.263"); + encoder_context->codectype = VEN_CODEC_H263; + Code_type = 0; + break; + case 2: + DEBUG_PRINT("\n H.264"); + encoder_context->codectype = VEN_CODEC_H264; + Code_type = 1; + break; + default: + DEBUG_PRINT("\n Wrong codec type"); + error = -1; + break; + } + + if (error != -1) + { + temp1 = atoi(argv[3]); + temp2 = atoi(argv[4]); + + if (((temp1%16) != 0) || ((temp2%16) != 0)) + { + error = -1; + } + else + { + encoder_context->input_width = temp1; + encoder_context->input_height = temp2; + } + } + + switch (atoi(argv[5])) + { + case 0: + DEBUG_PRINT("\n No Sink"); + encoder_context->outputBufferFile = NULL; + break; + } + + if (error != -1) + { + encoder_context->targetbitrate = atoi (argv[6]); + } + + if ( error != -1 && (init_encoder (encoder_context) == -1 )) + { + DEBUG_PRINT("\n Init decoder fails "); + error = -1; + } + DEBUG_PRINT("\n Decoder open successfull"); + + + /*Allocate input and output buffers*/ + if (error != -1 && (allocate_buffer (0,encoder_context)== -1)) + { + DEBUG_PRINT("\n Error in input Buffer allocation"); + error = -1; + } + + if (error != -1 && (allocate_buffer (1,encoder_context)== -1)) + { + DEBUG_PRINT("\n Error in output Buffer allocation"); + error = -1; + } + + + if (error != -1 && (start_encoding (encoder_context) == -1)) + { + DEBUG_PRINT("\n Error in start decoding call"); + error = -1; + } + + if (error != -1 && (stop_encoding (encoder_context) == -1)) + { + DEBUG_PRINT("\n Error in stop decoding call"); + error = -1; + } + + DEBUG_PRINT("\n De-init the decoder"); + if ((deinit_encoder (encoder_context) == -1)) + { + error = -1; + } + + + (void)free_buffer (INPUT_BUFFER,encoder_context); + (void)free_buffer (OUTPUT_BUFFER,encoder_context); + + if (encoder_context->inputBufferFile != NULL) + { + fclose (encoder_context->inputBufferFile); + } + if (encoder_context->outputBufferFile != NULL) + { + fclose (encoder_context->outputBufferFile); + } + DEBUG_PRINT ("\n Total Number of frames decoded %d",total_frames); + DEBUG_PRINT("\n closing the driver"); + free (encoder_context); + + return error; +} + +int init_encoder ( struct video_encoder_context *init_decode ) +{ + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_basecfg basecfg; + struct video_queue_context *queue_ptr = NULL; + struct venc_ratectrlcfg ratecrl; + pthread_mutexattr_t init_values; + struct venc_profile profile; + struct ven_profilelevel profilelevel; + + DEBUG_PRINT("\n Before calling the open"); + + init_decode->video_driver_fd = open ("/dev/msm_vidc_enc", \ + O_RDWR | O_NONBLOCK); + + + + if (init_decode->video_driver_fd < 0) + { + DEBUG_PRINT("\n Open failed"); + return -1; + } + + basecfg.codectype = init_decode->codectype; + basecfg.dvs_height = 0; + basecfg.dvs_width = 0; + basecfg.fps_den = init_decode->fps_den; + basecfg.fps_num = init_decode->fps_num; + basecfg.input_height = init_decode->input_height; + basecfg.input_width = init_decode->input_width; + basecfg.inputformat = init_decode->inputformat; + basecfg.targetbitrate = init_decode->targetbitrate; + + /*Initialize Decoder with codec type and resolution*/ + ioctl_msg.in = &basecfg; + ioctl_msg.out = NULL; + + if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_BASE_CFG, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Set base config type failed"); + return -1; + } + + /*Initialize Decoder with codec type and resolution*/ + DEBUG_PRINT ("\n Switch off rate control"); + ioctl_msg.in = &ratecrl; + ioctl_msg.out = NULL; + ratecrl.rcmode = VEN_RC_OFF; + if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_RATE_CTRL_CFG, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Set rate control failed"); + return -1; + } + + if (basecfg.codectype == VEN_CODEC_H264) + { + DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High"); + ioctl_msg.in = &profile; + ioctl_msg.out = NULL; + profile.profile = VEN_PROFILE_H264_BASELINE; + if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_CODEC_PROFILE, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed"); + return -1; + } + + DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High"); + ioctl_msg.in = &profilelevel; + ioctl_msg.out = NULL; + profilelevel.level = VEN_LEVEL_H264_1p1; + if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_PROFILE_LEVEL, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed"); + return -1; + } + + if (basecfg.input_width > 720) + { + DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High"); + ioctl_msg.in = &profile; + ioctl_msg.out = NULL; + profile.profile = VEN_PROFILE_H264_HIGH; + if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_CODEC_PROFILE, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed"); + return -1; + } + + DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High"); + ioctl_msg.in = &profilelevel; + ioctl_msg.out = NULL; + profilelevel.level = VEN_LEVEL_H264_3p1; + if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_PROFILE_LEVEL, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed"); + return -1; + } + } + } + + DEBUG_PRINT("\n Query Input bufffer requirements"); + /*Get the Buffer requirements for input and output ports*/ + + + + ioctl_msg.in = NULL; + ioctl_msg.out = &init_decode->input_buffer; + + if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Requesting for input buffer requirements failed"); + return -1; + } + + DEBUG_PRINT("\n input Size=%d min count =%d actual count = %d", \ + (int)init_decode->input_buffer.datasize,\ + (int)init_decode->input_buffer.mincount,\ + (int)init_decode->input_buffer.actualcount); + + + ioctl_msg.in = &init_decode->input_buffer; + ioctl_msg.out = NULL; + init_decode->input_buffer.actualcount = init_decode->input_buffer.mincount + 2; + + if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Set Buffer Requirements Failed"); + return -1; + } + + + DEBUG_PRINT("\n Query output bufffer requirements"); + ioctl_msg.in = NULL; + ioctl_msg.out = &init_decode->output_buffer; + + if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Requesting for output buffer requirements failed"); + return -1; + } + + DEBUG_PRINT("\n output Size=%d min count =%d actual count = %d", \ + (int)init_decode->output_buffer.datasize,\ + (int)init_decode->output_buffer.mincount,\ + (int)init_decode->output_buffer.actualcount); + + /*Create Queue related data structures*/ + queue_ptr = &init_decode->queue_context; + queue_ptr->commandq_size = 50; + queue_ptr->dataq_size = 50; + + sem_init(&queue_ptr->sem_message,0, 0); + sem_init(&init_decode->sem_synchronize,0, 0); + + pthread_mutexattr_init (&init_values); + pthread_mutex_init (&queue_ptr->mutex,&init_values); + pthread_mutex_init (&read_lock,&init_values); + DEBUG_PRINT("\n create Queues"); + queue_ptr->ptr_cmdq = (struct video_msgq*) \ + calloc (sizeof (struct video_msgq), + queue_ptr->commandq_size); + queue_ptr->ptr_dataq = (struct video_msgq*) \ + calloc (sizeof (struct video_msgq), + queue_ptr->dataq_size + ); + + if ( queue_ptr->ptr_cmdq == NULL || + queue_ptr->ptr_dataq == NULL + ) + { + return -1; + } + DEBUG_PRINT("\n create Threads"); + /*Create two threads*/ + if ( (pthread_create (&init_decode->videothread_id,NULL,video_thread, + init_decode) < 0) || + (pthread_create (&init_decode->asyncthread_id,NULL,async_thread, + init_decode) < 0) + ) + { + return -1; + } + + return 1; +} + + + +int free_buffer ( unsigned int buffer_dir, + struct video_encoder_context *encoder_context + ) +{ + unsigned int buffercount = 0,i=0; + struct venc_bufferpayload **ptemp = NULL; + + if (encoder_context == NULL) + { + return -1; + } + + if (buffer_dir == INPUT_BUFFER && encoder_context->ptr_inputbuffer) + { + buffercount = encoder_context->input_buffer.actualcount; + ptemp = encoder_context->ptr_inputbuffer; + + for (i=0;ifd != -1) + { + munmap ( ptemp [i]->pbuffer,ptemp [i]->maped_size); + ptemp [i]->pbuffer = NULL; + close (ptemp [i]->fd); + } + free (ptemp [i]); + ptemp [i] = NULL; + } + } + free (encoder_context->ptr_inputbuffer); + encoder_context->ptr_inputbuffer = NULL; + } + else if ( buffer_dir == OUTPUT_BUFFER && encoder_context->ptr_outputbuffer ) + { + buffercount = encoder_context->output_buffer.actualcount; + ptemp = encoder_context->ptr_outputbuffer; + + if (ptemp) + { + for (i=0;ifd != -1) + { + munmap ( ptemp [i]->pbuffer,ptemp [i]->maped_size); + ptemp [i]->pbuffer = NULL; + close (ptemp [i]->fd); + } + free (ptemp [i]); + ptemp [i] = NULL; + } + } + free (ptemp); + encoder_context->ptr_outputbuffer = NULL; + } + } + + return 1; +} + +int allocate_buffer ( unsigned int buffer_dir, + struct video_encoder_context *encoder_context + ) +{ + struct venc_bufferpayload **ptemp = NULL; + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + unsigned int buffercount = 0,i=0,alignedsize=0; + unsigned int buffersize = 0; + + if ( encoder_context == NULL) + { + DEBUG_PRINT ("\nallocate_buffer: context is NULL"); + return -1; + } + + if ( buffer_dir == INPUT_BUFFER ) + { + /*Check if buffers are allocated*/ + if (encoder_context->ptr_inputbuffer != NULL) + { + DEBUG_PRINT ("\nallocate_buffer: encoder_context->ptr_inputbuffer is set"); + return -1; + } + + buffercount = encoder_context->input_buffer.actualcount; + alignedsize = encoder_context->input_buffer.alignment; + buffersize = encoder_context->input_buffer.datasize; + buffersize = (buffersize + alignedsize) & (~alignedsize); + } + else if (buffer_dir == OUTPUT_BUFFER) + { + /*Check if buffers are allocated*/ + if (encoder_context->ptr_outputbuffer != NULL) + { + DEBUG_PRINT ("\nallocate_buffer: Double allcoate output"); + return -1; + } + + buffercount = encoder_context->output_buffer.actualcount; + alignedsize = encoder_context->output_buffer.alignment; + buffersize = encoder_context->output_buffer.datasize; + buffersize = (buffersize + alignedsize) & (~alignedsize); + + } + else + { + DEBUG_PRINT ("\nallocate_buffer: Wrong buffer directions"); + return -1; + } + + ptemp = (struct venc_bufferpayload **)\ + calloc (sizeof (struct venc_bufferpayload *),buffercount); + + if (ptemp == NULL) + { + DEBUG_PRINT ("\nallocate_buffer: venc_bufferpayload failure"); + return -1; + } + + + if (buffer_dir == OUTPUT_BUFFER) + { + DEBUG_PRINT ("\nallocate_buffer: OUT"); + encoder_context->ptr_outputbuffer = ptemp; + } + else + { + DEBUG_PRINT ("\nallocate_buffer: IN"); + encoder_context->ptr_inputbuffer = ptemp; + } + + /*Allocate buffer headers*/ + for (i=0; i< buffercount; i++) + { + ptemp [i] = (struct venc_bufferpayload*)\ + calloc (sizeof (struct venc_bufferpayload),1); + + if (ptemp [i] == NULL) + { + DEBUG_PRINT ("\nallocate_buffer: ptemp [i] calloc failure"); + return -1; + } + ptemp [i]->fd = -1; + } + + for (i=0; i< buffercount; i++) + { + ptemp [i]->fd = open ("/dev/pmem_adsp",O_RDWR); + + if (ptemp [i]->fd < 0) + { + DEBUG_PRINT ("\nallocate_buffer: open pmem_adsp failed"); + return -1; + } + + ptemp [i]->pbuffer = mmap(NULL,clp2(buffersize),PROT_READ|PROT_WRITE, + MAP_SHARED,ptemp [i]->fd,0); + DEBUG_PRINT ("\n pmem fd = %d virt addr = %p",ptemp [i]->fd,\ + ptemp [i]->pbuffer); + if (ptemp [i]->pbuffer == MAP_FAILED) + { + ptemp [i]->pbuffer = NULL; + DEBUG_PRINT ("\nallocate_buffer: MMAP failed"); + return -1; + } + ptemp [i]->sz = buffersize; + ptemp [i]->maped_size = clp2 (buffersize); + + ioctl_msg.in = ptemp [i]; + ioctl_msg.out = NULL; + + if (buffer_dir == OUTPUT_BUFFER) + { + if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER, + &ioctl_msg) < 0) + { + DEBUG_PRINT ("\nallocate_buffer: Set Output Buffer IOCTL failed"); + return -1; + } + } + else + { + if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_SET_INPUT_BUFFER, + &ioctl_msg) < 0) + { + DEBUG_PRINT ("\nallocate_buffer: Set input Buffer IOCTL failed"); + return -1; + } + } + + } + DEBUG_PRINT ("\nallocate_buffer: Success"); + return 1; +} + + + +int start_encoding (struct video_encoder_context *encoder_context) +{ + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_buffer enc_buffer; + unsigned int i = 0; + unsigned int data_len =0; + + + if (encoder_context == NULL) + { + return -1; + } + + if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_CMD_START, + NULL) < 0) + { + DEBUG_PRINT("\n Start failed"); + return -1; + } + + DEBUG_PRINT("\n Start Issued successfully waiting for Start Done"); + /*Wait for Start command response*/ + sem_wait (&encoder_context->sem_synchronize); + + /*Push output Buffers*/ + i = 0; + while (i < encoder_context->output_buffer.actualcount) + { + enc_buffer.clientdata = (void *)encoder_context->ptr_outputbuffer [i]; + enc_buffer.flags = 0; + enc_buffer.sz = encoder_context->ptr_outputbuffer [i]->sz; + enc_buffer.len = 0; + enc_buffer.ptrbuffer = encoder_context->ptr_outputbuffer [i]->pbuffer; + enc_buffer.offset = 0; + enc_buffer.timestamp = 0; + + DEBUG_PRINT ("\n Client Data on output = %p",(void *)enc_buffer.clientdata); + ioctl_msg.in = &enc_buffer; + ioctl_msg.out = NULL; + + if (ioctl (encoder_context->video_driver_fd, + VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) + { + DEBUG_PRINT("\n fill output frame failed"); + return -1; + } + i++; + } + + + /*push input buffers*/ + i = 0; + while (i < encoder_context->input_buffer.actualcount) + { + DEBUG_PRINT("\n Read Frame from File"); + + enc_buffer.clientdata = (void *)encoder_context->ptr_inputbuffer [i]; + enc_buffer.flags = 0; + enc_buffer.sz = encoder_context->ptr_inputbuffer [i]->sz; + enc_buffer.len = 0; + enc_buffer.ptrbuffer = encoder_context->ptr_inputbuffer [i]->pbuffer; + enc_buffer.offset = 0; + enc_buffer.timestamp = total_frames * + ((encoder_context->fps_den * 1000000)/encoder_context->fps_num); + enc_buffer.len = (encoder_context->input_height * + encoder_context->input_width *3)/2; + data_len = read_frame ( enc_buffer.ptrbuffer, + enc_buffer.len, + encoder_context->inputBufferFile); + if (data_len == 0) + { + DEBUG_PRINT("\n Length is zero error"); + return -1; + } + enc_buffer.len = data_len; + DEBUG_PRINT("\n Read Frame from File szie = %d",(int)data_len); + + DEBUG_PRINT ("\n Client Data on output = %p",(void *)enc_buffer.clientdata); + ioctl_msg.in = &enc_buffer; + ioctl_msg.out = NULL; + + if (ioctl (encoder_context->video_driver_fd, + VEN_IOCTL_CMD_ENCODE_FRAME,&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Encode input frame failed"); + return -1; + } + total_frames++; + i++; + } + DEBUG_PRINT ("\n Wait for EOS"); + /*Wait for EOS or Error condition*/ + sem_wait (&encoder_context->sem_synchronize); + DEBUG_PRINT ("\n Reached EOS"); + + return 1; +} + +int stop_encoding (struct video_encoder_context *encoder_context) +{ + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_bufferflush buffer_flush; + + if (encoder_context == NULL) + { + return -1; + } + buffer_flush.flush_mode = VEN_FLUSH_INPUT; + ioctl_msg.in = &buffer_flush; + ioctl_msg.out = NULL; + + if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_FLUSH, + &ioctl_msg) < 0) + { + DEBUG_PRINT("\n Flush input failed"); + } + else + { + sem_wait (&encoder_context->sem_synchronize); + } + + buffer_flush.flush_mode = VEN_FLUSH_OUTPUT; + ioctl_msg.in = &buffer_flush; + ioctl_msg.out = NULL; + + if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_FLUSH, + &ioctl_msg) < 0) + { + DEBUG_PRINT("\n Flush output failed"); + } + else + { + sem_wait (&encoder_context->sem_synchronize); + } + + DEBUG_PRINT("\n Stop VEN_IOCTL_CMD_STOP"); + if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_STOP,NULL) < 0) + { + DEBUG_PRINT("\n Stop failed"); + } + else + { + sem_wait (&encoder_context->sem_synchronize); + } + return 1; +} + +int deinit_encoder (struct video_encoder_context *init_decode) +{ + if (init_decode == NULL) + { + return -1; + } + + /*Close the driver*/ + if (init_decode->video_driver_fd != -1) + { + close (init_decode->video_driver_fd); + } + + if (init_decode->queue_context.ptr_cmdq) + { + free (init_decode->queue_context.ptr_cmdq); + init_decode->queue_context.ptr_cmdq = NULL; + } + + if (init_decode->queue_context.ptr_dataq) + { + free (init_decode->queue_context.ptr_dataq); + init_decode->queue_context.ptr_dataq = NULL; + } + + sem_destroy (&init_decode->queue_context.sem_message); + sem_destroy (&init_decode->sem_synchronize); + + pthread_mutex_destroy(&init_decode->queue_context.mutex); + pthread_mutex_destroy (&read_lock); + + return 1; +} + +static void* video_thread (void *context) +{ + struct video_encoder_context *encoder_context = NULL; + struct video_msgq *queueitem = NULL; + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_bufferpayload *tempbuffer = NULL; + struct venc_buffer enc_buffer; + unsigned int data_len =0; + + + if (context == NULL) + { + DEBUG_PRINT("\n video thread recieved NULL context"); + return NULL; + } + encoder_context = (struct video_encoder_context *) context; + + /* Thread function which will accept commands from async thread + * or main thread + */ + while (1) + { + queueitem = queue_get_cmd (&encoder_context ->queue_context); + if (queueitem != NULL) + { + switch (queueitem->cmd) + { + case VEN_MSG_START: + DEBUG_PRINT("\n recived start done command"); + sem_post (&encoder_context->sem_synchronize); + break; + + case VEN_MSG_STOP: + DEBUG_PRINT("\n recieved stop done"); + sem_post (&encoder_context->sem_synchronize); + break; + + case VEN_MSG_INPUT_BUFFER_DONE: + + tempbuffer = (struct venc_bufferpayload *)queueitem->clientdata; + if (tempbuffer == NULL) + { + DEBUG_PRINT("\n FATAL ERROR input buffer address is bad"); + sem_post (&encoder_context->sem_synchronize); + break; + } + tempbuffer->filled_len = (encoder_context->input_height * + encoder_context->input_width *3)/2; + + data_len = read_frame ( tempbuffer->pbuffer, + tempbuffer->filled_len, + encoder_context->inputBufferFile); + + if (data_len == 0) + { + DEBUG_PRINT ("\n End of stream reached"); + sem_post (&encoder_context->sem_synchronize); + break; + } + enc_buffer.clientdata = (void *)tempbuffer; + enc_buffer.flags = 0; + enc_buffer.ptrbuffer = tempbuffer->pbuffer; + enc_buffer.sz = tempbuffer->sz; + enc_buffer.len = tempbuffer->filled_len; + enc_buffer.offset = 0; + enc_buffer.timestamp = total_frames * + ((encoder_context->fps_den * 1000000)/encoder_context->fps_num); + + /*TODO: Time stamp needs to be updated*/ + ioctl_msg.in = &enc_buffer; + ioctl_msg.out = NULL; + total_frames++; + if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_ENCODE_FRAME, + &ioctl_msg) < 0) + { + DEBUG_PRINT("\n Decoder frame failed"); + sem_post (&encoder_context->sem_synchronize); + } + DEBUG_PRINT("\n Input buffer done send next buffer current value = %d",\ + total_frames); + break; + + case VEN_MSG_OUTPUT_BUFFER_DONE: + + tempbuffer = (struct venc_bufferpayload *)queueitem->clientdata; + if (tempbuffer == NULL) + { + DEBUG_PRINT("\n FATAL ERROR input buffer address is bad"); + sem_post (&encoder_context->sem_synchronize); + break; + } + + if (encoder_context->outputBufferFile != NULL) + { + fwrite (tempbuffer->pbuffer,1,tempbuffer->filled_len, + encoder_context->outputBufferFile); + } + + + DEBUG_PRINT("\n recieved output buffer consume outbuffer"); + DEBUG_PRINT("\nValues outputbuffer->bufferaddr = %p",\ + tempbuffer->pbuffer); + enc_buffer.clientdata = (void *)tempbuffer; + enc_buffer.flags = 0; + enc_buffer.sz = tempbuffer->sz; + enc_buffer.len = 0; + enc_buffer.ptrbuffer = tempbuffer->pbuffer; + enc_buffer.offset = 0; + enc_buffer.timestamp = 0; + + ioctl_msg.in = &enc_buffer; + ioctl_msg.out = NULL; + + if (ioctl (encoder_context->video_driver_fd, + VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Decoder frame failed"); + return NULL; + } + + break; + + case VEN_MSG_FLUSH_INPUT_DONE: + DEBUG_PRINT("\n Flush input complete"); + sem_post (&encoder_context->sem_synchronize); + break; + + case VEN_MSG_FLUSH_OUPUT_DONE: + DEBUG_PRINT("\n Flush output complete"); + sem_post (&encoder_context->sem_synchronize); + break; + } + + if (queueitem->cmd == VEN_MSG_STOP) + { + DEBUG_PRINT("\n Playback has ended thread will exit"); + return NULL; + } + } + else + { + DEBUG_PRINT("\n Error condition recieved NULL from Queue"); + } + + } +} + +static void* async_thread (void *context) +{ + struct video_encoder_context *encoder_context = NULL; + struct video_msgq queueitem ; + struct venc_msg venc_msg; + struct venc_bufferpayload *tempbuffer = NULL; + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + int result = -1; + + if (context == NULL) + { + DEBUG_PRINT("\n aynsc thread recieved NULL context"); + return NULL; + } + encoder_context = (struct video_encoder_context *) context; + DEBUG_PRINT("\n Entering the async thread"); + + while (1) + { + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&venc_msg; + DEBUG_PRINT ("\n Sizeof venc_msginfo = %d ",sizeof (venc_msg)); + DEBUG_PRINT("\n Address of Venc msg in async thread %p",\ + ioctl_msg.out); + if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_CMD_READ_NEXT_MSG,\ + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Error in ioctl read next msg"); + } + else + { + switch (venc_msg.msgcode) + { + case VEN_MSG_START: + case VEN_MSG_STOP: + case VEN_MSG_INDICATION: + DEBUG_PRINT("\nSTOP/START Indiacation"); + queueitem.cmd = venc_msg.msgcode; + queueitem.status = venc_msg.statuscode; + queueitem.clientdata = NULL; + break; + + case VEN_MSG_INPUT_BUFFER_DONE: + DEBUG_PRINT("\nINPUT buffer done Indiacation"); + queueitem.cmd = venc_msg.msgcode; + queueitem.status = venc_msg.statuscode; + queueitem.clientdata = (void *)venc_msg.buf.clientdata; + DEBUG_PRINT("\nInput Client data pointer is %p",queueitem.clientdata); + tempbuffer = (struct venc_bufferpayload *) queueitem.clientdata; + DEBUG_PRINT ("\n Input Address of tempbuffer %p",tempbuffer); + tempbuffer->filled_len = venc_msg.buf.len; + DEBUG_PRINT ("\n Input value of tempbuffer tempbuffer->filled_len %d",(int)tempbuffer->filled_len); + break; + case VEN_MSG_OUTPUT_BUFFER_DONE: + DEBUG_PRINT("\nOUPUT buffer done Indiacation"); + queueitem.cmd = venc_msg.msgcode; + queueitem.status = venc_msg.statuscode; + queueitem.clientdata = (void *)venc_msg.buf.clientdata; + DEBUG_PRINT("\nOutput Client data pointer is %p",queueitem.clientdata); + tempbuffer = (struct venc_bufferpayload *) queueitem.clientdata; + DEBUG_PRINT ("\n Output Address of tempbuffer %p",tempbuffer); + tempbuffer->filled_len = venc_msg.buf.len; + DEBUG_PRINT ("\n Output value of tempbuffer tempbuffer->filled_len %d",(int)tempbuffer->filled_len); + break; + + default: + DEBUG_PRINT("\nIn Default of get next message %d",(int)venc_msg.msgcode); + queueitem.cmd = venc_msg.msgcode; + queueitem.status = venc_msg.statuscode; + queueitem.clientdata = NULL; + break; + } + result = queue_post_cmdq (&encoder_context->queue_context,&queueitem); + while (result == 0) + { + result = queue_post_cmdq (&encoder_context->queue_context,&queueitem); + } + + if (result == -1) + { + DEBUG_PRINT("\n FATAL ERROR WITH Queue"); + } + } + if (venc_msg.msgcode == VEN_MSG_STOP) + { + /*Thread can exit at this point*/ + return NULL; + } + } +} + + +static unsigned int read_frame (unsigned char *dataptr, unsigned int length, + FILE * inputBufferFile) +{ + + unsigned int readOffset = 0; + int bytes_read = 0; + unsigned int code = 0; + int found = 0; + + DEBUG_PRINT ("\n Inside the readframe"); + + if (dataptr == NULL && length == 0) + { + DEBUG_PRINT ("\n dataptr = %p length = %d",dataptr,(int)length); + return 0; + } + + pthread_mutex_lock(&read_lock); + bytes_read = fread(&dataptr[readOffset],1,length,inputBufferFile); + pthread_mutex_unlock(&read_lock); + + return bytes_read; +}