diff --git a/Android.mk b/Android.mk index 6e1bdc55cf297962eef0f43567f409cf9b80b36d..5c95d204568e85e9a908e257197ba3e23c2f2f56 100644 --- a/Android.mk +++ b/Android.mk @@ -198,6 +198,9 @@ LOCAL_JAVA_LIBRARIES := core ext LOCAL_MODULE := framework LOCAL_MODULE_CLASS := JAVA_LIBRARIES +LOCAL_NO_EMMA_INSTRUMENT := true +LOCAL_NO_EMMA_COMPILE := true + # List of classes and interfaces which should be loaded by the Zygote. LOCAL_JAVA_RESOURCE_FILES += $(LOCAL_PATH)/preloaded-classes @@ -294,7 +297,7 @@ fwbase_dirs_to_document := \ # as "final" in the official SDK APIs. fwbase_dirs_to_document += core/config/sdk -# These are relative to dalvik/libcore +# These are relative to libcore # Intentionally not included from libcore: # icu openssl suncompat support libcore_to_document := \ @@ -334,7 +337,7 @@ non_base_dirs := \ dirs_to_document := \ $(fwbase_dirs_to_document) \ $(non_base_dirs) \ - $(addprefix ../../dalvik/libcore/, $(libcore_to_document)) + $(addprefix ../../libcore/, $(libcore_to_document)) html_dirs := \ $(FRAMEWORKS_BASE_SUBDIRS) \ @@ -345,6 +348,10 @@ framework_docs_LOCAL_SRC_FILES := \ $(call find-other-java-files, $(dirs_to_document)) \ $(call find-other-html-files, $(html_dirs)) +# This is used by ide.mk as the list of source files that are +# always included. +INTERNAL_SDK_SOURCE_DIRS := $(addprefix $(LOCAL_PATH)/,$(dirs_to_document)) + framework_docs_LOCAL_DROIDDOC_SOURCE_PATH := \ $(FRAMEWORKS_BASE_JAVA_SRC_DIRS) @@ -592,6 +599,9 @@ LOCAL_JAVA_LIBRARIES := core LOCAL_MODULE := ext +LOCAL_NO_EMMA_INSTRUMENT := true +LOCAL_NO_EMMA_COMPILE := true + include $(BUILD_JAVA_LIBRARY) diff --git a/CleanSpec.mk b/CleanSpec.mk index 707404ba398114ed181054ccc89659011511a4ee..6455103a91632b1afaa375330355e78238d68219 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -51,6 +51,8 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/app) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/content) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/FrameworkTest_intermediates/) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android.policy*) +$(call add-clean-step, rm -rf $(TARGET_OUT_JAVA_LIBRARIES)/android.policy.jar) # ************************************************ diff --git a/api/9.xml b/api/9.xml new file mode 100644 index 0000000000000000000000000000000000000000..b7596bd22eb3c1fa17dd7d255ee90946a75803e2 --- /dev/null +++ b/api/9.xml @@ -0,0 +1,395736 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/api/current.xml b/api/current.xml index 9d259f3a3090c3f574df39f30e466670134133ef..e6780be60871c678c97893720aef64cf6c3bf899 100644 --- a/api/current.xml +++ b/api/current.xml @@ -1559,6 +1559,226 @@ visibility="public" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -79377,6 +83408,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CameraHardwareStub::getPreviewHeap() const @@ -175,7 +174,7 @@ int CameraHardwareStub::previewThread() // Fill the current frame with the fake camera. uint8_t *frame = ((uint8_t *)base) + offset; - fakeCamera->getNextFrameAsYuv422(frame); + fakeCamera->getNextFrameAsYuv420(frame); //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame); @@ -288,9 +287,9 @@ int CameraHardwareStub::pictureThread() // In the meantime just make another fake camera picture. int w, h; mParameters.getPictureSize(&w, &h); - sp mem = new MemoryBase(mRawHeap, 0, w * 2 * h); + sp mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2); FakeCamera cam(w, h); - cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base()); + cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base()); mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie); } @@ -307,7 +306,7 @@ status_t CameraHardwareStub::takePicture() { stopPreview(); if (createThread(beginPictureThread, this) == false) - return -1; + return UNKNOWN_ERROR; return NO_ERROR; } @@ -339,12 +338,14 @@ status_t CameraHardwareStub::setParameters(const CameraParameters& params) Mutex::Autolock lock(mLock); // XXX verify params - if (strcmp(params.getPreviewFormat(), "yuv422sp") != 0) { - LOGE("Only yuv422sp preview is supported"); + if (strcmp(params.getPreviewFormat(), + CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) { + LOGE("Only yuv420sp preview is supported"); return -1; } - if (strcmp(params.getPictureFormat(), "jpeg") != 0) { + if (strcmp(params.getPictureFormat(), + CameraParameters::PIXEL_FORMAT_JPEG) != 0) { LOGE("Only jpeg still pictures are supported"); return -1; } @@ -379,22 +380,12 @@ void CameraHardwareStub::release() { } -wp CameraHardwareStub::singleton; - sp CameraHardwareStub::createInstance() { - if (singleton != 0) { - sp hardware = singleton.promote(); - if (hardware != 0) { - return hardware; - } - } - sp hardware(new CameraHardwareStub()); - singleton = hardware; - return hardware; + return new CameraHardwareStub(); } -extern "C" sp openCameraHardware() +extern "C" sp openCameraHardwareStub() { return CameraHardwareStub::createInstance(); } diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h index 957813a4a47ab5f98bf5726375e64134cdacb1ca..d194f3c4ed1d00b3d6a3992d3d7c0e61156b3ca0 100644 --- a/camera/libcameraservice/CameraHardwareStub.h +++ b/camera/libcameraservice/CameraHardwareStub.h @@ -67,8 +67,6 @@ private: CameraHardwareStub(); virtual ~CameraHardwareStub(); - static wp singleton; - static const int kBufferCount = 4; class PreviewThread : public Thread { @@ -130,6 +128,8 @@ private: int mCurrentPreviewFrame; }; +extern "C" sp openCameraHardwareStub(); + }; // namespace android #endif diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp index 00bd54eb597586867e76a057765c7947f86d40da..4f684b7ba3d3ada990e16b800bb2618dc3f2eb64 100644 --- a/camera/libcameraservice/CameraService.cpp +++ b/camera/libcameraservice/CameraService.cpp @@ -17,383 +17,448 @@ */ #define LOG_TAG "CameraService" -#include -#include +#include +#include +#include + #include -#include -#include +#include #include #include -#include +#include +#include +#include +#include #include #include +#include +#include +#include -#include - -#include -#include #include "CameraService.h" - -#include +#ifdef INCLUDE_CAMERA_STUB +#include "CameraHardwareStub.h" +#endif namespace android { -extern "C" { -#include -#include -#include -#include -#include -#include -} +/* This determines the number of cameras available */ +#if defined(INCLUDE_CAMERA_HARDWARE) && defined(INCLUDE_CAMERA_STUB) + #define NUM_CAMERAS 2 +#elif defined(INCLUDE_CAMERA_HARDWARE) || defined(INCLUDE_CAMERA_STUB) + #define NUM_CAMERAS 1 +#else + #error "Should have at least one camera" +#endif -// When you enable this, as well as DEBUG_REFS=1 and -// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp, this will track all -// references to the CameraService::Client in order to catch the case where the -// client is being destroyed while a callback from the CameraHardwareInterface -// is outstanding. This is a serious bug because if we make another call into -// CameraHardwreInterface that itself triggers a callback, we will deadlock. +/* Make sure we have enough array space allocated */ +#if NUM_CAMERAS > MAX_CAMERAS + #error "Need to increase MAX_CAMERAS" +#endif -#define DEBUG_CLIENT_REFERENCES 0 +/* This defines the "open" function for each camera */ +extern "C" typedef sp (*OpenCameraHardwareFunction)(); +static OpenCameraHardwareFunction sOpenCameraTable[] = { +#ifdef INCLUDE_CAMERA_HARDWARE + &openCameraHardware, +#endif +#ifdef INCLUDE_CAMERA_STUB + &openCameraHardwareStub, +#endif +}; -#define PICTURE_TIMEOUT seconds(5) +// ---------------------------------------------------------------------------- +// Logging support -- this is for debugging only +// Use "adb shell dumpsys media.camera -v 1" to change it. +static volatile int32_t gLogLevel = 0; -#define DEBUG_DUMP_PREVIEW_FRAME_TO_FILE 0 /* n-th frame to write */ -#define DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE 0 -#define DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE 0 -#define DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE 0 +#define LOG1(...) LOGD_IF(gLogLevel >= 1, __VA_ARGS__); +#define LOG2(...) LOGD_IF(gLogLevel >= 2, __VA_ARGS__); -#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE -static int debug_frame_cnt; -#endif +static void setLogLevel(int level) { + android_atomic_write(level, &gLogLevel); +} + +// ---------------------------------------------------------------------------- static int getCallingPid() { return IPCThreadState::self()->getCallingPid(); } -// ---------------------------------------------------------------------------- - -void CameraService::instantiate() { - defaultServiceManager()->addService( - String16("media.camera"), new CameraService()); +static int getCallingUid() { + return IPCThreadState::self()->getCallingUid(); } // ---------------------------------------------------------------------------- -CameraService::CameraService() : - BnCameraService() +// This is ugly and only safe if we never re-create the CameraService, but +// should be ok for now. +static CameraService *gCameraService; + +CameraService::CameraService() +:mSoundRef(0) { - LOGI("CameraService started: pid=%d", getpid()); - mUsers = 0; + LOGI("CameraService started (pid=%d)", getpid()); + + for (int i = 0; i < NUM_CAMERAS; i++) { + setCameraFree(i); + } + + gCameraService = this; } -CameraService::~CameraService() -{ - if (mClient != 0) { - LOGE("mClient was still connected in destructor!"); +CameraService::~CameraService() { + for (int i = 0; i < NUM_CAMERAS; i++) { + if (mBusy[i]) { + LOGE("camera %d is still in use in destructor!", i); + } } + + gCameraService = NULL; } -sp CameraService::connect(const sp& cameraClient) -{ +int32_t CameraService::getNumberOfCameras() { + return NUM_CAMERAS; +} + +sp CameraService::connect( + const sp& cameraClient, int cameraId) { int callingPid = getCallingPid(); - LOGV("CameraService::connect E (pid %d, client %p)", callingPid, - cameraClient->asBinder().get()); + LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId); - Mutex::Autolock lock(mServiceLock); sp client; - if (mClient != 0) { - sp currentClient = mClient.promote(); - if (currentClient != 0) { - sp currentCameraClient(currentClient->getCameraClient()); - if (cameraClient->asBinder() == currentCameraClient->asBinder()) { - // This is the same client reconnecting... - LOGV("CameraService::connect X (pid %d, same client %p) is reconnecting...", - callingPid, cameraClient->asBinder().get()); - return currentClient; - } else { - // It's another client... reject it - LOGV("CameraService::connect X (pid %d, new client %p) rejected. " - "(old pid %d, old client %p)", - callingPid, cameraClient->asBinder().get(), - currentClient->mClientPid, currentCameraClient->asBinder().get()); - if (kill(currentClient->mClientPid, 0) == -1 && errno == ESRCH) { - LOGV("The old client is dead!"); - } + if (cameraId < 0 || cameraId >= NUM_CAMERAS) { + LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).", + callingPid, cameraId); + return NULL; + } + + Mutex::Autolock lock(mServiceLock); + if (mClient[cameraId] != 0) { + client = mClient[cameraId].promote(); + if (client != 0) { + if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) { + LOG1("CameraService::connect X (pid %d) (the same client)", + callingPid); return client; - } - } else { - // can't promote, the previous client has died... - LOGV("New client (pid %d) connecting, old reference was dangling...", + } else { + LOGW("CameraService::connect X (pid %d) rejected (existing client).", callingPid); - mClient.clear(); + return NULL; + } } + mClient[cameraId].clear(); } - if (mUsers > 0) { - LOGV("Still have client, rejected"); - return client; + if (mBusy[cameraId]) { + LOGW("CameraService::connect X (pid %d) rejected" + " (camera %d is still busy).", callingPid, cameraId); + return NULL; } - // create a new Client object - client = new Client(this, cameraClient, callingPid); - mClient = client; -#if DEBUG_CLIENT_REFERENCES - // Enable tracking for this object, and track increments and decrements of - // the refcount. - client->trackMe(true, true); -#endif - LOGV("CameraService::connect X"); + client = new Client(this, cameraClient, cameraId, callingPid); + mClient[cameraId] = client; + LOG1("CameraService::connect X"); return client; } -void CameraService::removeClient(const sp& cameraClient) -{ +void CameraService::removeClient(const sp& cameraClient) { int callingPid = getCallingPid(); + LOG1("CameraService::removeClient E (pid %d)", callingPid); - // Declare this outside the lock to make absolutely sure the - // destructor won't be called with the lock held. - sp client; + for (int i = 0; i < NUM_CAMERAS; i++) { + // Declare this before the lock to make absolutely sure the + // destructor won't be called with the lock held. + sp client; - Mutex::Autolock lock(mServiceLock); + Mutex::Autolock lock(mServiceLock); - if (mClient == 0) { - // This happens when we have already disconnected. - LOGV("removeClient (pid %d): already disconnected", callingPid); - return; - } + // This happens when we have already disconnected (or this is + // just another unused camera). + if (mClient[i] == 0) continue; - // Promote mClient. It can fail if we are called from this path: - // Client::~Client() -> disconnect() -> removeClient(). - client = mClient.promote(); - if (client == 0) { - LOGV("removeClient (pid %d): no more strong reference", callingPid); - mClient.clear(); - return; + // Promote mClient. It can fail if we are called from this path: + // Client::~Client() -> disconnect() -> removeClient(). + client = mClient[i].promote(); + + if (client == 0) { + mClient[i].clear(); + continue; + } + + if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) { + // Found our camera, clear and leave. + LOG1("removeClient: clear camera %d", i); + mClient[i].clear(); + break; + } } - if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) { - // ugh! that's not our client!! - LOGW("removeClient (pid %d): mClient doesn't match!", callingPid); - } else { - // okay, good, forget about mClient - mClient.clear(); + LOG1("CameraService::removeClient X (pid %d)", callingPid); +} + +sp CameraService::getClientById(int cameraId) { + if (cameraId < 0 || cameraId >= NUM_CAMERAS) return NULL; + return mClient[cameraId].promote(); +} + +void CameraService::instantiate() { + defaultServiceManager()->addService(String16("media.camera"), + new CameraService()); +} + +status_t CameraService::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { + // Permission checks + switch (code) { + case BnCameraService::CONNECT: + const int pid = getCallingPid(); + const int self_pid = getpid(); + if (pid != self_pid) { + // we're called from a different process, do the real check + if (!checkCallingPermission( + String16("android.permission.CAMERA"))) { + const int uid = getCallingUid(); + LOGE("Permission Denial: " + "can't use the camera pid=%d, uid=%d", pid, uid); + return PERMISSION_DENIED; + } + } + break; } - LOGV("removeClient (pid %d) done", callingPid); + return BnCameraService::onTransact(code, data, reply, flags); } -// The reason we need this count is a new CameraService::connect() request may -// come in while the previous Client's destructor has not been run or is still -// running. If the last strong reference of the previous Client is gone but -// destructor has not been run, we should not allow the new Client to be created -// because we need to wait for the previous Client to tear down the hardware -// first. -void CameraService::incUsers() { - android_atomic_inc(&mUsers); +// The reason we need this busy bit is a new CameraService::connect() request +// may come in while the previous Client's destructor has not been run or is +// still running. If the last strong reference of the previous Client is gone +// but the destructor has not been finished, we should not allow the new Client +// to be created because we need to wait for the previous Client to tear down +// the hardware first. +void CameraService::setCameraBusy(int cameraId) { + android_atomic_write(1, &mBusy[cameraId]); } -void CameraService::decUsers() { - android_atomic_dec(&mUsers); +void CameraService::setCameraFree(int cameraId) { + android_atomic_write(0, &mBusy[cameraId]); } -static sp newMediaPlayer(const char *file) -{ - sp mp = new MediaPlayer(); - if (mp->setDataSource(file, NULL /* headers */) == NO_ERROR) { +// We share the media players for shutter and recording sound for all clients. +// A reference count is kept to determine when we will actually release the +// media players. + +static MediaPlayer* newMediaPlayer(const char *file) { + MediaPlayer* mp = new MediaPlayer(); + if (mp->setDataSource(file, NULL) == NO_ERROR) { mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE); mp->prepare(); } else { - mp.clear(); - LOGE("Failed to load CameraService sounds."); + LOGE("Failed to load CameraService sounds: %s", file); + return NULL; } return mp; } +void CameraService::loadSound() { + Mutex::Autolock lock(mSoundLock); + LOG1("CameraService::loadSound ref=%d", mSoundRef); + if (mSoundRef++) return; + + mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg"); + mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg"); +} + +void CameraService::releaseSound() { + Mutex::Autolock lock(mSoundLock); + LOG1("CameraService::releaseSound ref=%d", mSoundRef); + if (--mSoundRef) return; + + for (int i = 0; i < NUM_SOUNDS; i++) { + if (mSoundPlayer[i] != 0) { + mSoundPlayer[i]->disconnect(); + mSoundPlayer[i].clear(); + } + } +} + +void CameraService::playSound(sound_kind kind) { + LOG1("playSound(%d)", kind); + Mutex::Autolock lock(mSoundLock); + sp player = mSoundPlayer[kind]; + if (player != 0) { + // do not play the sound if stream volume is 0 + // (typically because ringer mode is silent). + int index; + AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index); + if (index != 0) { + player->seekTo(0); + player->start(); + } + } +} + +// ---------------------------------------------------------------------------- + CameraService::Client::Client(const sp& cameraService, - const sp& cameraClient, pid_t clientPid) -{ + const sp& cameraClient, int cameraId, int clientPid) { int callingPid = getCallingPid(); - LOGV("Client::Client E (pid %d)", callingPid); + LOG1("Client::Client E (pid %d)", callingPid); + mCameraService = cameraService; mCameraClient = cameraClient; + mCameraId = cameraId; mClientPid = clientPid; - mHardware = openCameraHardware(); + + mHardware = sOpenCameraTable[cameraId](); mUseOverlay = mHardware->useOverlay(); + mMsgEnabled = 0; mHardware->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, - mCameraService.get()); + (void *)cameraId); // Enable zoom, error, and focus messages by default - mHardware->enableMsgType(CAMERA_MSG_ERROR | - CAMERA_MSG_ZOOM | - CAMERA_MSG_FOCUS); - - mMediaPlayerClick = newMediaPlayer("/system/media/audio/ui/camera_click.ogg"); - mMediaPlayerBeep = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg"); + enableMsgType(CAMERA_MSG_ERROR | + CAMERA_MSG_ZOOM | + CAMERA_MSG_FOCUS); mOverlayW = 0; mOverlayH = 0; // Callback is disabled by default mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; mOrientation = 0; - cameraService->incUsers(); - LOGV("Client::Client X (pid %d)", callingPid); + cameraService->setCameraBusy(cameraId); + cameraService->loadSound(); + LOG1("Client::Client X (pid %d)", callingPid); } -status_t CameraService::Client::checkPid() -{ +static void *unregister_surface(void *arg) { + ISurface *surface = (ISurface *)arg; + surface->unregisterBuffers(); + IPCThreadState::self()->flushCommands(); + return NULL; +} + +// tear down the client +CameraService::Client::~Client() { int callingPid = getCallingPid(); - if (mClientPid == callingPid) return NO_ERROR; - LOGW("Attempt to use locked camera (client %p) from different process " - " (old pid %d, new pid %d)", - getCameraClient()->asBinder().get(), mClientPid, callingPid); - return -EBUSY; + LOG1("Client::~Client E (pid %d, this %p)", callingPid, this); + + if (mSurface != 0 && !mUseOverlay) { + pthread_t thr; + // We unregister the buffers in a different thread because binder does + // not let us make sychronous transactions in a binder destructor (that + // is, upon our reaching a refcount of zero.) + pthread_create(&thr, + NULL, // attr + unregister_surface, + mSurface.get()); + pthread_join(thr, NULL); + } + + // set mClientPid to let disconnet() tear down the hardware + mClientPid = callingPid; + disconnect(); + mCameraService->releaseSound(); + LOG1("Client::~Client X (pid %d, this %p)", callingPid, this); } -status_t CameraService::Client::lock() -{ +// ---------------------------------------------------------------------------- + +status_t CameraService::Client::checkPid() const { int callingPid = getCallingPid(); - LOGV("lock from pid %d (mClientPid %d)", callingPid, mClientPid); - Mutex::Autolock _l(mLock); + if (callingPid == mClientPid) return NO_ERROR; + if (callingPid == getpid()) { + LOGW("FIXME: use camera from mediaserver without permission."); + return NO_ERROR; + } + LOGW("attempt to use a locked camera from a different process" + " (old pid %d, new pid %d)", mClientPid, callingPid); + return EBUSY; +} + +status_t CameraService::Client::checkPidAndHardware() const { + status_t result = checkPid(); + if (result != NO_ERROR) return result; + if (mHardware == 0) { + LOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid()); + return INVALID_OPERATION; + } + return NO_ERROR; +} + +status_t CameraService::Client::lock() { + int callingPid = getCallingPid(); + LOG1("lock (pid %d)", callingPid); + Mutex::Autolock lock(mLock); + // lock camera to this client if the the camera is unlocked if (mClientPid == 0) { mClientPid = callingPid; return NO_ERROR; } - // returns NO_ERROR if the client already owns the camera, -EBUSY otherwise + + // returns NO_ERROR if the client already owns the camera, EBUSY otherwise return checkPid(); } -status_t CameraService::Client::unlock() -{ +status_t CameraService::Client::unlock() { int callingPid = getCallingPid(); - LOGV("unlock from pid %d (mClientPid %d)", callingPid, mClientPid); - Mutex::Autolock _l(mLock); - // allow anyone to use camera + LOG1("unlock (pid %d)", callingPid); + Mutex::Autolock lock(mLock); + + // allow anyone to use camera (after they lock the camera) status_t result = checkPid(); if (result == NO_ERROR) { mClientPid = 0; - LOGV("clear mCameraClient (pid %d)", callingPid); - // we need to remove the reference so that when app goes - // away, the reference count goes to 0. + LOG1("clear mCameraClient (pid %d)", callingPid); + // we need to remove the reference to ICameraClient so that when the app + // goes away, the reference count goes to 0. mCameraClient.clear(); } return result; } -status_t CameraService::Client::connect(const sp& client) -{ +// connect a new client to the camera +status_t CameraService::Client::connect(const sp& client) { int callingPid = getCallingPid(); + LOG1("connect E (pid %d)", callingPid); + Mutex::Autolock lock(mLock); - // connect a new process to the camera - LOGV("Client::connect E (pid %d, client %p)", callingPid, client->asBinder().get()); - - // I hate this hack, but things get really ugly when the media recorder - // service is handing back the camera to the app. The ICameraClient - // destructor will be called during the same IPC, making it look like - // the remote client is trying to disconnect. This hack temporarily - // sets the mClientPid to an invalid pid to prevent the hardware from - // being torn down. - { - - // hold a reference to the old client or we will deadlock if the client is - // in the same process and we hold the lock when we remove the reference - sp oldClient; - { - Mutex::Autolock _l(mLock); - if (mClientPid != 0 && checkPid() != NO_ERROR) { - LOGW("Tried to connect to locked camera (old pid %d, new pid %d)", - mClientPid, callingPid); - return -EBUSY; - } - oldClient = mCameraClient; - - // did the client actually change? - if ((mCameraClient != NULL) && (client->asBinder() == mCameraClient->asBinder())) { - LOGV("Connect to the same client"); - return NO_ERROR; - } - - mCameraClient = client; - mClientPid = -1; - mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; - LOGV("Connect to the new client (pid %d, client %p)", - callingPid, mCameraClient->asBinder().get()); - } + if (mClientPid != 0 && checkPid() != NO_ERROR) { + LOGW("Tried to connect to a locked camera (old pid %d, new pid %d)", + mClientPid, callingPid); + return EBUSY; + } + if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) { + LOG1("Connect to the same client"); + return NO_ERROR; } - // the old client destructor is called when oldClient goes out of scope - // now we set the new PID to lock the interface again + + mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; mClientPid = callingPid; + mCameraClient = client; + LOG1("connect X (pid %d)", callingPid); return NO_ERROR; } -#if HAVE_ANDROID_OS -static void *unregister_surface(void *arg) -{ - ISurface *surface = (ISurface *)arg; - surface->unregisterBuffers(); - IPCThreadState::self()->flushCommands(); - return NULL; -} -#endif - -CameraService::Client::~Client() -{ +void CameraService::Client::disconnect() { int callingPid = getCallingPid(); + LOG1("disconnect E (pid %d)", callingPid); + Mutex::Autolock lock(mLock); - // tear down client - LOGV("Client::~Client E (pid %d, client %p)", - callingPid, getCameraClient()->asBinder().get()); - if (mSurface != 0 && !mUseOverlay) { -#if HAVE_ANDROID_OS - pthread_t thr; - // We unregister the buffers in a different thread because binder does - // not let us make sychronous transactions in a binder destructor (that - // is, upon our reaching a refcount of zero.) - pthread_create(&thr, NULL, - unregister_surface, - mSurface.get()); - pthread_join(thr, NULL); -#else - mSurface->unregisterBuffers(); -#endif - } - - if (mMediaPlayerBeep.get() != NULL) { - mMediaPlayerBeep->disconnect(); - mMediaPlayerBeep.clear(); - } - if (mMediaPlayerClick.get() != NULL) { - mMediaPlayerClick->disconnect(); - mMediaPlayerClick.clear(); + if (checkPid() != NO_ERROR) { + LOGW("different client - don't disconnect"); + return; } - // make sure we tear down the hardware - mClientPid = callingPid; - disconnect(); - LOGV("Client::~Client X (pid %d)", mClientPid); -} - -void CameraService::Client::disconnect() -{ - int callingPid = getCallingPid(); - - LOGV("Client::disconnect() E (pid %d client %p)", - callingPid, getCameraClient()->asBinder().get()); - - Mutex::Autolock lock(mLock); if (mClientPid <= 0) { - LOGV("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid); - return; - } - if (checkPid() != NO_ERROR) { - LOGV("Different client - don't disconnect"); + LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid); return; } @@ -401,508 +466,551 @@ void CameraService::Client::disconnect() // from the user directly, or called by the destructor. if (mHardware == 0) return; - LOGV("hardware teardown"); + LOG1("hardware teardown"); // Before destroying mHardware, we must make sure it's in the // idle state. + // Turn off all messages. + disableMsgType(CAMERA_MSG_ALL_MSGS); mHardware->stopPreview(); - // Cancel all picture callbacks. - mHardware->disableMsgType(CAMERA_MSG_SHUTTER | - CAMERA_MSG_POSTVIEW_FRAME | - CAMERA_MSG_RAW_IMAGE | - CAMERA_MSG_COMPRESSED_IMAGE); mHardware->cancelPicture(); - // Turn off remaining messages. - mHardware->disableMsgType(CAMERA_MSG_ALL_MSGS); // Release the hardware resources. mHardware->release(); // Release the held overlay resources. - if (mUseOverlay) - { + if (mUseOverlay) { mOverlayRef = 0; } mHardware.clear(); mCameraService->removeClient(mCameraClient); - mCameraService->decUsers(); + mCameraService->setCameraFree(mCameraId); - LOGV("Client::disconnect() X (pid %d)", callingPid); + LOG1("disconnect X (pid %d)", callingPid); } -// pass the buffered ISurface to the camera service -status_t CameraService::Client::setPreviewDisplay(const sp& surface) -{ - LOGV("setPreviewDisplay(%p) (pid %d)", - ((surface == NULL) ? NULL : surface.get()), getCallingPid()); +// ---------------------------------------------------------------------------- + +// set the ISurface that the preview will use +status_t CameraService::Client::setPreviewDisplay(const sp& surface) { + LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid()); Mutex::Autolock lock(mLock); - status_t result = checkPid(); + status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; - Mutex::Autolock surfaceLock(mSurfaceLock); result = NO_ERROR; - // asBinder() is safe on NULL (returns NULL) - if (surface->asBinder() != mSurface->asBinder()) { - if (mSurface != 0) { - LOGV("clearing old preview surface %p", mSurface.get()); - if ( !mUseOverlay) - { - mSurface->unregisterBuffers(); - } - else - { - // Force the destruction of any previous overlay - sp dummy; - mHardware->setOverlay( dummy ); - } - } - mSurface = surface; - mOverlayRef = 0; - // If preview has been already started, set overlay or register preview - // buffers now. - if (mHardware->previewEnabled()) { - if (mUseOverlay) { - result = setOverlay(); - } else if (mSurface != 0) { - result = registerPreviewBuffers(); - } - } - } - return result; -} - -// set the preview callback flag to affect how the received frames from -// preview are handled. -void CameraService::Client::setPreviewCallbackFlag(int callback_flag) -{ - LOGV("setPreviewCallbackFlag (pid %d)", getCallingPid()); - Mutex::Autolock lock(mLock); - if (checkPid() != NO_ERROR) return; - mPreviewCallbackFlag = callback_flag; - if(mUseOverlay) { - if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) - mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME); - else - mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME); - } -} - -// start preview mode -status_t CameraService::Client::startCameraMode(camera_mode mode) -{ - int callingPid = getCallingPid(); - - LOGV("startCameraMode(%d) (pid %d)", mode, callingPid); - - /* we cannot call into mHardware with mLock held because - * mHardware has callbacks onto us which acquire this lock - */ - - Mutex::Autolock lock(mLock); - status_t result = checkPid(); - if (result != NO_ERROR) return result; - - if (mHardware == 0) { - LOGE("mHardware is NULL, returning."); - return INVALID_OPERATION; + // return if no change in surface. + // asBinder() is safe on NULL (returns NULL) + if (surface->asBinder() == mSurface->asBinder()) { + return result; } - switch(mode) { - case CAMERA_RECORDING_MODE: - if (mSurface == 0) { - LOGE("setPreviewDisplay must be called before startRecordingMode."); - return INVALID_OPERATION; + if (mSurface != 0) { + LOG1("clearing old preview surface %p", mSurface.get()); + if (mUseOverlay) { + // Force the destruction of any previous overlay + sp dummy; + mHardware->setOverlay(dummy); + } else { + mSurface->unregisterBuffers(); } - return startRecordingMode(); - - default: // CAMERA_PREVIEW_MODE - if (mSurface == 0) { - LOGV("mSurface is not set yet."); + } + mSurface = surface; + mOverlayRef = 0; + // If preview has been already started, set overlay or register preview + // buffers now. + if (mHardware->previewEnabled()) { + if (mUseOverlay) { + result = setOverlay(); + } else if (mSurface != 0) { + result = registerPreviewBuffers(); } - return startPreviewMode(); } -} -status_t CameraService::Client::startRecordingMode() -{ - LOGV("startRecordingMode (pid %d)", getCallingPid()); - - status_t ret = UNKNOWN_ERROR; + return result; +} - // if preview has not been started, start preview first - if (!mHardware->previewEnabled()) { - ret = startPreviewMode(); - if (ret != NO_ERROR) { - return ret; - } - } +status_t CameraService::Client::registerPreviewBuffers() { + int w, h; + CameraParameters params(mHardware->getParameters()); + params.getPreviewSize(&w, &h); - // if recording has been enabled, nothing needs to be done - if (mHardware->recordingEnabled()) { - return NO_ERROR; - } + // FIXME: don't use a hardcoded format here. + ISurface::BufferHeap buffers(w, h, w, h, + HAL_PIXEL_FORMAT_YCrCb_420_SP, + mOrientation, + 0, + mHardware->getPreviewHeap()); - // start recording mode - ret = mHardware->startRecording(); - if (ret != NO_ERROR) { - LOGE("mHardware->startRecording() failed with status %d", ret); + status_t result = mSurface->registerBuffers(buffers); + if (result != NO_ERROR) { + LOGE("registerBuffers failed with status %d", result); } - return ret; + return result; } -status_t CameraService::Client::setOverlay() -{ - LOGV("setOverlay"); +status_t CameraService::Client::setOverlay() { int w, h; CameraParameters params(mHardware->getParameters()); params.getPreviewSize(&w, &h); - if ( w != mOverlayW || h != mOverlayH ) - { + if (w != mOverlayW || h != mOverlayH) { // Force the destruction of any previous overlay sp dummy; - mHardware->setOverlay( dummy ); + mHardware->setOverlay(dummy); mOverlayRef = 0; } - status_t ret = NO_ERROR; - if (mSurface != 0) { - if (mOverlayRef.get() == NULL) { - + status_t result = NO_ERROR; + if (mSurface == 0) { + result = mHardware->setOverlay(NULL); + } else { + if (mOverlayRef == 0) { // FIXME: // Surfaceflinger may hold onto the previous overlay reference for some // time after we try to destroy it. retry a few times. In the future, we // should make the destroy call block, or possibly specify that we can - // wait in the createOverlay call if the previous overlay is in the + // wait in the createOverlay call if the previous overlay is in the // process of being destroyed. for (int retry = 0; retry < 50; ++retry) { mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT, mOrientation); - if (mOverlayRef != NULL) break; + if (mOverlayRef != 0) break; LOGW("Overlay create failed - retrying"); usleep(20000); } - if ( mOverlayRef.get() == NULL ) - { + if (mOverlayRef == 0) { LOGE("Overlay Creation Failed!"); return -EINVAL; } - ret = mHardware->setOverlay(new Overlay(mOverlayRef)); + result = mHardware->setOverlay(new Overlay(mOverlayRef)); } - } else { - ret = mHardware->setOverlay(NULL); } - if (ret != NO_ERROR) { - LOGE("mHardware->setOverlay() failed with status %d\n", ret); + if (result != NO_ERROR) { + LOGE("mHardware->setOverlay() failed with status %d\n", result); + return result; } mOverlayW = w; mOverlayH = h; - return ret; + return result; +} + +// set the preview callback flag to affect how the received frames from +// preview are handled. +void CameraService::Client::setPreviewCallbackFlag(int callback_flag) { + LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid()); + Mutex::Autolock lock(mLock); + if (checkPidAndHardware() != NO_ERROR) return; + + mPreviewCallbackFlag = callback_flag; + + // If we don't use overlay, we always need the preview frame for display. + // If we do use overlay, we only need the preview frame if the user + // wants the data. + if (mUseOverlay) { + if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) { + enableMsgType(CAMERA_MSG_PREVIEW_FRAME); + } else { + disableMsgType(CAMERA_MSG_PREVIEW_FRAME); + } + } } -status_t CameraService::Client::registerPreviewBuffers() -{ - int w, h; - CameraParameters params(mHardware->getParameters()); - params.getPreviewSize(&w, &h); +// start preview mode +status_t CameraService::Client::startPreview() { + LOG1("startPreview (pid %d)", getCallingPid()); + return startCameraMode(CAMERA_PREVIEW_MODE); +} - // don't use a hardcoded format here - ISurface::BufferHeap buffers(w, h, w, h, - HAL_PIXEL_FORMAT_YCrCb_420_SP, - mOrientation, - 0, - mHardware->getPreviewHeap()); +// start recording mode +status_t CameraService::Client::startRecording() { + LOG1("startRecording (pid %d)", getCallingPid()); + return startCameraMode(CAMERA_RECORDING_MODE); +} + +// start preview or recording +status_t CameraService::Client::startCameraMode(camera_mode mode) { + LOG1("startCameraMode(%d)", mode); + Mutex::Autolock lock(mLock); + status_t result = checkPidAndHardware(); + if (result != NO_ERROR) return result; - status_t ret = mSurface->registerBuffers(buffers); - if (ret != NO_ERROR) { - LOGE("registerBuffers failed with status %d", ret); + switch(mode) { + case CAMERA_PREVIEW_MODE: + if (mSurface == 0) { + LOG1("mSurface is not set yet."); + // still able to start preview in this case. + } + return startPreviewMode(); + case CAMERA_RECORDING_MODE: + if (mSurface == 0) { + LOGE("mSurface must be set before startRecordingMode."); + return INVALID_OPERATION; + } + return startRecordingMode(); + default: + return UNKNOWN_ERROR; } - return ret; } -status_t CameraService::Client::startPreviewMode() -{ - LOGV("startPreviewMode (pid %d)", getCallingPid()); +status_t CameraService::Client::startPreviewMode() { + LOG1("startPreviewMode"); + status_t result = NO_ERROR; // if preview has been enabled, nothing needs to be done if (mHardware->previewEnabled()) { return NO_ERROR; } - // start preview mode -#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE - debug_frame_cnt = 0; -#endif - status_t ret = NO_ERROR; - if (mUseOverlay) { // If preview display has been set, set overlay now. if (mSurface != 0) { - ret = setOverlay(); + result = setOverlay(); } - if (ret != NO_ERROR) return ret; - ret = mHardware->startPreview(); + if (result != NO_ERROR) return result; + result = mHardware->startPreview(); } else { - mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME); - ret = mHardware->startPreview(); - if (ret != NO_ERROR) return ret; + enableMsgType(CAMERA_MSG_PREVIEW_FRAME); + result = mHardware->startPreview(); + if (result != NO_ERROR) return result; // If preview display has been set, register preview buffers now. if (mSurface != 0) { - // Unregister here because the surface registered with raw heap. + // Unregister here because the surface may be previously registered + // with the raw (snapshot) heap. mSurface->unregisterBuffers(); - ret = registerPreviewBuffers(); + result = registerPreviewBuffers(); } } - return ret; + return result; } -status_t CameraService::Client::startPreview() -{ - LOGV("startPreview (pid %d)", getCallingPid()); +status_t CameraService::Client::startRecordingMode() { + LOG1("startRecordingMode"); + status_t result = NO_ERROR; - return startCameraMode(CAMERA_PREVIEW_MODE); -} - -status_t CameraService::Client::startRecording() -{ - LOGV("startRecording (pid %d)", getCallingPid()); + // if recording has been enabled, nothing needs to be done + if (mHardware->recordingEnabled()) { + return NO_ERROR; + } - if (mMediaPlayerBeep.get() != NULL) { - // do not play record jingle if stream volume is 0 - // (typically because ringer mode is silent). - int index; - AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index); - if (index != 0) { - mMediaPlayerBeep->seekTo(0); - mMediaPlayerBeep->start(); + // if preview has not been started, start preview first + if (!mHardware->previewEnabled()) { + result = startPreviewMode(); + if (result != NO_ERROR) { + return result; } } - mHardware->enableMsgType(CAMERA_MSG_VIDEO_FRAME); - - return startCameraMode(CAMERA_RECORDING_MODE); + // start recording mode + enableMsgType(CAMERA_MSG_VIDEO_FRAME); + mCameraService->playSound(SOUND_RECORDING); + result = mHardware->startRecording(); + if (result != NO_ERROR) { + LOGE("mHardware->startRecording() failed with status %d", result); + } + return result; } // stop preview mode -void CameraService::Client::stopPreview() -{ - LOGV("stopPreview (pid %d)", getCallingPid()); - - // hold main lock during state transition - { - Mutex::Autolock lock(mLock); - if (checkPid() != NO_ERROR) return; - - if (mHardware == 0) { - LOGE("mHardware is NULL, returning."); - return; - } +void CameraService::Client::stopPreview() { + LOG1("stopPreview (pid %d)", getCallingPid()); + Mutex::Autolock lock(mLock); + if (checkPidAndHardware() != NO_ERROR) return; - mHardware->stopPreview(); - mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME); - LOGV("stopPreview(), hardware stopped OK"); + disableMsgType(CAMERA_MSG_PREVIEW_FRAME); + mHardware->stopPreview(); - if (mSurface != 0 && !mUseOverlay) { - mSurface->unregisterBuffers(); - } + if (mSurface != 0 && !mUseOverlay) { + mSurface->unregisterBuffers(); } - // hold preview buffer lock - { - Mutex::Autolock lock(mPreviewLock); - mPreviewBuffer.clear(); - } + mPreviewBuffer.clear(); } // stop recording mode -void CameraService::Client::stopRecording() -{ - LOGV("stopRecording (pid %d)", getCallingPid()); +void CameraService::Client::stopRecording() { + LOG1("stopRecording (pid %d)", getCallingPid()); + Mutex::Autolock lock(mLock); + if (checkPidAndHardware() != NO_ERROR) return; - // hold main lock during state transition - { - Mutex::Autolock lock(mLock); - if (checkPid() != NO_ERROR) return; + mCameraService->playSound(SOUND_RECORDING); + disableMsgType(CAMERA_MSG_VIDEO_FRAME); + mHardware->stopRecording(); - if (mHardware == 0) { - LOGE("mHardware is NULL, returning."); - return; - } + mPreviewBuffer.clear(); +} - if (mMediaPlayerBeep.get() != NULL) { - mMediaPlayerBeep->seekTo(0); - mMediaPlayerBeep->start(); - } +// release a recording frame +void CameraService::Client::releaseRecordingFrame(const sp& mem) { + Mutex::Autolock lock(mLock); + if (checkPidAndHardware() != NO_ERROR) return; + mHardware->releaseRecordingFrame(mem); +} - mHardware->stopRecording(); - mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME); - LOGV("stopRecording(), hardware stopped OK"); - } +bool CameraService::Client::previewEnabled() { + LOG1("previewEnabled (pid %d)", getCallingPid()); - // hold preview buffer lock - { - Mutex::Autolock lock(mPreviewLock); - mPreviewBuffer.clear(); - } + Mutex::Autolock lock(mLock); + if (checkPidAndHardware() != NO_ERROR) return false; + return mHardware->previewEnabled(); } -// release a recording frame -void CameraService::Client::releaseRecordingFrame(const sp& mem) -{ +bool CameraService::Client::recordingEnabled() { + LOG1("recordingEnabled (pid %d)", getCallingPid()); + Mutex::Autolock lock(mLock); - if (checkPid() != NO_ERROR) return; + if (checkPidAndHardware() != NO_ERROR) return false; + return mHardware->recordingEnabled(); +} - if (mHardware == 0) { - LOGE("mHardware is NULL, returning."); - return; - } +status_t CameraService::Client::autoFocus() { + LOG1("autoFocus (pid %d)", getCallingPid()); - mHardware->releaseRecordingFrame(mem); + Mutex::Autolock lock(mLock); + status_t result = checkPidAndHardware(); + if (result != NO_ERROR) return result; + + return mHardware->autoFocus(); } -bool CameraService::Client::previewEnabled() -{ +status_t CameraService::Client::cancelAutoFocus() { + LOG1("cancelAutoFocus (pid %d)", getCallingPid()); + Mutex::Autolock lock(mLock); - if (mHardware == 0) return false; - return mHardware->previewEnabled(); + status_t result = checkPidAndHardware(); + if (result != NO_ERROR) return result; + + return mHardware->cancelAutoFocus(); } -bool CameraService::Client::recordingEnabled() -{ +// take a picture - image is returned in callback +status_t CameraService::Client::takePicture() { + LOG1("takePicture (pid %d)", getCallingPid()); + Mutex::Autolock lock(mLock); - if (mHardware == 0) return false; - return mHardware->recordingEnabled(); + status_t result = checkPidAndHardware(); + if (result != NO_ERROR) return result; + + enableMsgType(CAMERA_MSG_SHUTTER | + CAMERA_MSG_POSTVIEW_FRAME | + CAMERA_MSG_RAW_IMAGE | + CAMERA_MSG_COMPRESSED_IMAGE); + + return mHardware->takePicture(); } -// Safely retrieves a strong pointer to the client during a hardware callback. -sp CameraService::Client::getClientFromCookie(void* user) -{ - sp client = 0; - CameraService *service = static_cast(user); - if (service != NULL) { - Mutex::Autolock ourLock(service->mServiceLock); - if (service->mClient != 0) { - client = service->mClient.promote(); - if (client == 0) { - LOGE("getClientFromCookie: client appears to have died"); - service->mClient.clear(); +// set preview/capture parameters - key/value pairs +status_t CameraService::Client::setParameters(const String8& params) { + LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string()); + + Mutex::Autolock lock(mLock); + status_t result = checkPidAndHardware(); + if (result != NO_ERROR) return result; + + CameraParameters p(params); + return mHardware->setParameters(p); +} + +// get preview/capture parameters - key/value pairs +String8 CameraService::Client::getParameters() const { + Mutex::Autolock lock(mLock); + if (checkPidAndHardware() != NO_ERROR) return String8(); + + String8 params(mHardware->getParameters().flatten()); + LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string()); + return params; +} + +status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) { + LOG1("sendCommand (pid %d)", getCallingPid()); + Mutex::Autolock lock(mLock); + status_t result = checkPidAndHardware(); + if (result != NO_ERROR) return result; + + if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) { + // The orientation cannot be set during preview. + if (mHardware->previewEnabled()) { + return INVALID_OPERATION; + } + switch (arg1) { + case 0: + mOrientation = ISurface::BufferHeap::ROT_0; + break; + case 90: + mOrientation = ISurface::BufferHeap::ROT_90; + break; + case 180: + mOrientation = ISurface::BufferHeap::ROT_180; + break; + case 270: + mOrientation = ISurface::BufferHeap::ROT_270; + break; + default: + return BAD_VALUE; + } + return OK; + } + + return mHardware->sendCommand(cmd, arg1, arg2); +} + +// ---------------------------------------------------------------------------- + +void CameraService::Client::enableMsgType(int32_t msgType) { + android_atomic_or(msgType, &mMsgEnabled); + mHardware->enableMsgType(msgType); +} + +void CameraService::Client::disableMsgType(int32_t msgType) { + android_atomic_and(~msgType, &mMsgEnabled); + mHardware->disableMsgType(msgType); +} + +#define CHECK_MESSAGE_INTERVAL 10 // 10ms +bool CameraService::Client::lockIfMessageWanted(int32_t msgType) { + int sleepCount = 0; + while (mMsgEnabled & msgType) { + if (mLock.tryLock() == NO_ERROR) { + if (sleepCount > 0) { + LOG1("lockIfMessageWanted(%d): waited for %d ms", + msgType, sleepCount * CHECK_MESSAGE_INTERVAL); } - } else { - LOGE("getClientFromCookie: got callback but client was NULL"); + return true; + } + if (sleepCount++ == 0) { + LOG1("lockIfMessageWanted(%d): enter sleep", msgType); } + usleep(CHECK_MESSAGE_INTERVAL * 1000); } - return client; + LOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType); + return false; } +// ---------------------------------------------------------------------------- -#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \ - DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \ - DEBUG_DUMP_PREVIEW_FRAME_TO_FILE -static void dump_to_file(const char *fname, - uint8_t *buf, uint32_t size) -{ - int nw, cnt = 0; - uint32_t written = 0; +// Converts from a raw pointer to the client to a strong pointer during a +// hardware callback. This requires the callbacks only happen when the client +// is still alive. +sp CameraService::Client::getClientFromCookie(void* user) { + sp client = gCameraService->getClientById((int) user); - LOGV("opening file [%s]\n", fname); - int fd = open(fname, O_RDWR | O_CREAT); - if (fd < 0) { - LOGE("failed to create file [%s]: %s", fname, strerror(errno)); - return; + // This could happen if the Client is in the process of shutting down (the + // last strong reference is gone, but the destructor hasn't finished + // stopping the hardware). + if (client == 0) return NULL; + + // The checks below are not necessary and are for debugging only. + if (client->mCameraService.get() != gCameraService) { + LOGE("mismatch service!"); + return NULL; } - LOGV("writing %d bytes to file [%s]\n", size, fname); - while (written < size) { - nw = ::write(fd, - buf + written, - size - written); - if (nw < 0) { - LOGE("failed to write to file [%s]: %s", - fname, strerror(errno)); - break; - } - written += nw; - cnt++; + if (client->mHardware == 0) { + LOGE("mHardware == 0: callback after disconnect()?"); + return NULL; } - LOGV("done writing %d bytes to file [%s] in %d passes\n", - size, fname, cnt); - ::close(fd); + + return client; } -#endif -status_t CameraService::Client::autoFocus() -{ - LOGV("autoFocus (pid %d)", getCallingPid()); +// Callback messages can be dispatched to internal handlers or pass to our +// client's callback functions, depending on the message type. +// +// notifyCallback: +// CAMERA_MSG_SHUTTER handleShutter +// (others) c->notifyCallback +// dataCallback: +// CAMERA_MSG_PREVIEW_FRAME handlePreviewData +// CAMERA_MSG_POSTVIEW_FRAME handlePostview +// CAMERA_MSG_RAW_IMAGE handleRawPicture +// CAMERA_MSG_COMPRESSED_IMAGE handleCompressedPicture +// (others) c->dataCallback +// dataCallbackTimestamp +// (others) c->dataCallbackTimestamp +// +// NOTE: the *Callback functions grab mLock of the client before passing +// control to handle* functions. So the handle* functions must release the +// lock before calling the ICameraClient's callbacks, so those callbacks can +// invoke methods in the Client class again (For example, the preview frame +// callback may want to releaseRecordingFrame). The handle* functions must +// release the lock after all accesses to member variables, so it must be +// handled very carefully. + +void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1, + int32_t ext2, void* user) { + LOG2("notifyCallback(%d)", msgType); - Mutex::Autolock lock(mLock); - status_t result = checkPid(); - if (result != NO_ERROR) return result; + sp client = getClientFromCookie(user); + if (client == 0) return; + if (!client->lockIfMessageWanted(msgType)) return; - if (mHardware == 0) { - LOGE("mHardware is NULL, returning."); - return INVALID_OPERATION; + switch (msgType) { + case CAMERA_MSG_SHUTTER: + // ext1 is the dimension of the yuv picture. + client->handleShutter((image_rect_type *)ext1); + break; + default: + client->handleGenericNotify(msgType, ext1, ext2); + break; } - - return mHardware->autoFocus(); } -status_t CameraService::Client::cancelAutoFocus() -{ - LOGV("cancelAutoFocus (pid %d)", getCallingPid()); +void CameraService::Client::dataCallback(int32_t msgType, + const sp& dataPtr, void* user) { + LOG2("dataCallback(%d)", msgType); - Mutex::Autolock lock(mLock); - status_t result = checkPid(); - if (result != NO_ERROR) return result; + sp client = getClientFromCookie(user); + if (client == 0) return; + if (!client->lockIfMessageWanted(msgType)) return; - if (mHardware == 0) { - LOGE("mHardware is NULL, returning."); - return INVALID_OPERATION; + if (dataPtr == 0) { + LOGE("Null data returned in data callback"); + client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); + return; } - return mHardware->cancelAutoFocus(); + switch (msgType) { + case CAMERA_MSG_PREVIEW_FRAME: + client->handlePreviewData(dataPtr); + break; + case CAMERA_MSG_POSTVIEW_FRAME: + client->handlePostview(dataPtr); + break; + case CAMERA_MSG_RAW_IMAGE: + client->handleRawPicture(dataPtr); + break; + case CAMERA_MSG_COMPRESSED_IMAGE: + client->handleCompressedPicture(dataPtr); + break; + default: + client->handleGenericData(msgType, dataPtr); + break; + } } -// take a picture - image is returned in callback -status_t CameraService::Client::takePicture() -{ - LOGV("takePicture (pid %d)", getCallingPid()); +void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp, + int32_t msgType, const sp& dataPtr, void* user) { + LOG2("dataCallbackTimestamp(%d)", msgType); - Mutex::Autolock lock(mLock); - status_t result = checkPid(); - if (result != NO_ERROR) return result; + sp client = getClientFromCookie(user); + if (client == 0) return; + if (!client->lockIfMessageWanted(msgType)) return; - if (mHardware == 0) { - LOGE("mHardware is NULL, returning."); - return INVALID_OPERATION; + if (dataPtr == 0) { + LOGE("Null data returned in data with timestamp callback"); + client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); + return; } - mHardware->enableMsgType(CAMERA_MSG_SHUTTER | - CAMERA_MSG_POSTVIEW_FRAME | - CAMERA_MSG_RAW_IMAGE | - CAMERA_MSG_COMPRESSED_IMAGE); - - return mHardware->takePicture(); + client->handleGenericDataTimestamp(timestamp, msgType, dataPtr); } -// snapshot taken -void CameraService::Client::handleShutter( - image_rect_type *size // The width and height of yuv picture for - // registerBuffer. If this is NULL, use the picture - // size from parameters. -) -{ - // Play shutter sound. - if (mMediaPlayerClick.get() != NULL) { - // do not play shutter sound if stream volume is 0 - // (typically because ringer mode is silent). - int index; - AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index); - if (index != 0) { - mMediaPlayerClick->seekTo(0); - mMediaPlayerClick->start(); - } - } +// snapshot taken callback +// "size" is the width and height of yuv picture for registerBuffer. +// If it is NULL, use the picture size from parameters. +void CameraService::Client::handleShutter(image_rect_type *size) { + mCameraService->playSound(SOUND_SHUTTER); // Screen goes black after the buffer is unregistered. if (mSurface != 0 && !mUseOverlay) { @@ -910,10 +1018,12 @@ void CameraService::Client::handleShutter( } sp c = mCameraClient; - if (c != NULL) { + if (c != 0) { + mLock.unlock(); c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0); + if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return; } - mHardware->disableMsgType(CAMERA_MSG_SHUTTER); + disableMsgType(CAMERA_MSG_SHUTTER); // It takes some time before yuvPicture callback to be called. // Register the buffer for raw image here to reduce latency. @@ -927,7 +1037,7 @@ void CameraService::Client::handleShutter( h = size->height; w &= ~1; h &= ~1; - LOGV("Snapshot image width=%d, height=%d", w, h); + LOG1("Snapshot image width=%d, height=%d", w, h); } // FIXME: don't use hardcoded format constants here ISurface::BufferHeap buffers(w, h, w, h, @@ -936,37 +1046,18 @@ void CameraService::Client::handleShutter( mSurface->registerBuffers(buffers); } + + mLock.unlock(); } // preview callback - frame buffer update -void CameraService::Client::handlePreviewData(const sp& mem) -{ +void CameraService::Client::handlePreviewData(const sp& mem) { ssize_t offset; size_t size; sp heap = mem->getMemory(&offset, &size); -#if DEBUG_HEAP_LEAKS && 0 // debugging - if (gWeakHeap == NULL) { - if (gWeakHeap != heap) { - LOGV("SETTING PREVIEW HEAP"); - heap->trackMe(true, true); - gWeakHeap = heap; - } - } -#endif -#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE - { - if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) { - dump_to_file("/data/preview.yuv", - (uint8_t *)heap->base() + offset, size); - } - } -#endif - - if (!mUseOverlay) - { - Mutex::Autolock surfaceLock(mSurfaceLock); - if (mSurface != NULL) { + if (!mUseOverlay) { + if (mSurface != 0) { mSurface->postBuffer(offset); } } @@ -977,7 +1068,8 @@ void CameraService::Client::handlePreviewData(const sp& mem) // is callback enabled? if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) { // If the enable bit is off, the copy-out and one-shot bits are ignored - LOGV("frame callback is diabled"); + LOG2("frame callback is disabled"); + mLock.unlock(); return; } @@ -985,61 +1077,49 @@ void CameraService::Client::handlePreviewData(const sp& mem) sp c = mCameraClient; // clear callback flags if no client or one-shot mode - if ((c == NULL) || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) { - LOGV("Disable preview callback"); + if (c == 0 || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) { + LOG2("Disable preview callback"); mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK | - FRAME_CALLBACK_FLAG_COPY_OUT_MASK | - FRAME_CALLBACK_FLAG_ENABLE_MASK); - // TODO: Shouldn't we use this API for non-overlay hardware as well? - if (mUseOverlay) - mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME); + FRAME_CALLBACK_FLAG_COPY_OUT_MASK | + FRAME_CALLBACK_FLAG_ENABLE_MASK); + if (mUseOverlay) { + disableMsgType(CAMERA_MSG_PREVIEW_FRAME); + } } - // Is the received frame copied out or not? - if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) { - LOGV("frame is copied"); - copyFrameAndPostCopiedFrame(c, heap, offset, size); + if (c != 0) { + // Is the received frame copied out or not? + if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) { + LOG2("frame is copied"); + copyFrameAndPostCopiedFrame(c, heap, offset, size); + } else { + LOG2("frame is forwarded"); + mLock.unlock(); + c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem); + } } else { - LOGV("frame is forwarded"); - c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem); + mLock.unlock(); } } // picture callback - postview image ready -void CameraService::Client::handlePostview(const sp& mem) -{ -#if DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE // for testing pursposes only - { - ssize_t offset; - size_t size; - sp heap = mem->getMemory(&offset, &size); - dump_to_file("/data/postview.yuv", - (uint8_t *)heap->base() + offset, size); - } -#endif +void CameraService::Client::handlePostview(const sp& mem) { + disableMsgType(CAMERA_MSG_POSTVIEW_FRAME); sp c = mCameraClient; - if (c != NULL) { + mLock.unlock(); + if (c != 0) { c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem); } - mHardware->disableMsgType(CAMERA_MSG_POSTVIEW_FRAME); } // picture callback - raw image ready -void CameraService::Client::handleRawPicture(const sp& mem) -{ +void CameraService::Client::handleRawPicture(const sp& mem) { + disableMsgType(CAMERA_MSG_RAW_IMAGE); + ssize_t offset; size_t size; sp heap = mem->getMemory(&offset, &size); -#if DEBUG_HEAP_LEAKS && 0 // debugging - gWeakHeap = heap; // debugging -#endif - - //LOGV("handleRawPicture(%d, %d)", offset, size); -#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only - dump_to_file("/data/photo.yuv", - (uint8_t *)heap->base() + offset, size); -#endif // Put the YUV version of the snapshot in the preview display. if (mSurface != 0 && !mUseOverlay) { @@ -1047,250 +1127,90 @@ void CameraService::Client::handleRawPicture(const sp& mem) } sp c = mCameraClient; - if (c != NULL) { + mLock.unlock(); + if (c != 0) { c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem); } - mHardware->disableMsgType(CAMERA_MSG_RAW_IMAGE); } // picture callback - compressed picture ready -void CameraService::Client::handleCompressedPicture(const sp& mem) -{ -#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only - { - ssize_t offset; - size_t size; - sp heap = mem->getMemory(&offset, &size); - dump_to_file("/data/photo.jpg", - (uint8_t *)heap->base() + offset, size); - } -#endif +void CameraService::Client::handleCompressedPicture(const sp& mem) { + disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); sp c = mCameraClient; - if (c != NULL) { + mLock.unlock(); + if (c != 0) { c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem); } - mHardware->disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); } -void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user) -{ - LOGV("notifyCallback(%d)", msgType); - - sp client = getClientFromCookie(user); - if (client == 0) { - return; - } - - switch (msgType) { - case CAMERA_MSG_SHUTTER: - // ext1 is the dimension of the yuv picture. - client->handleShutter((image_rect_type *)ext1); - break; - default: - sp c = client->mCameraClient; - if (c != NULL) { - c->notifyCallback(msgType, ext1, ext2); - } - break; - } -#if DEBUG_CLIENT_REFERENCES - if (client->getStrongCount() == 1) { - LOGE("++++++++++++++++ (NOTIFY CALLBACK) THIS WILL CAUSE A LOCKUP!"); - client->printRefs(); +void CameraService::Client::handleGenericNotify(int32_t msgType, + int32_t ext1, int32_t ext2) { + sp c = mCameraClient; + mLock.unlock(); + if (c != 0) { + c->notifyCallback(msgType, ext1, ext2); } -#endif } -void CameraService::Client::dataCallback(int32_t msgType, const sp& dataPtr, void* user) -{ - LOGV("dataCallback(%d)", msgType); - - sp client = getClientFromCookie(user); - if (client == 0) { - return; - } - - sp c = client->mCameraClient; - if (dataPtr == NULL) { - LOGE("Null data returned in data callback"); - if (c != NULL) { - c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); - c->dataCallback(msgType, NULL); - } - return; - } - - switch (msgType) { - case CAMERA_MSG_PREVIEW_FRAME: - client->handlePreviewData(dataPtr); - break; - case CAMERA_MSG_POSTVIEW_FRAME: - client->handlePostview(dataPtr); - break; - case CAMERA_MSG_RAW_IMAGE: - client->handleRawPicture(dataPtr); - break; - case CAMERA_MSG_COMPRESSED_IMAGE: - client->handleCompressedPicture(dataPtr); - break; - default: - if (c != NULL) { - c->dataCallback(msgType, dataPtr); - } - break; - } - -#if DEBUG_CLIENT_REFERENCES - if (client->getStrongCount() == 1) { - LOGE("++++++++++++++++ (DATA CALLBACK) THIS WILL CAUSE A LOCKUP!"); - client->printRefs(); +void CameraService::Client::handleGenericData(int32_t msgType, + const sp& dataPtr) { + sp c = mCameraClient; + mLock.unlock(); + if (c != 0) { + c->dataCallback(msgType, dataPtr); } -#endif } -void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, - const sp& dataPtr, void* user) -{ - LOGV("dataCallbackTimestamp(%d)", msgType); - - sp client = getClientFromCookie(user); - if (client == 0) { - return; - } - sp c = client->mCameraClient; - - if (dataPtr == NULL) { - LOGE("Null data returned in data with timestamp callback"); - if (c != NULL) { - c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); - c->dataCallbackTimestamp(0, msgType, NULL); - } - return; - } - - if (c != NULL) { +void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp, + int32_t msgType, const sp& dataPtr) { + sp c = mCameraClient; + mLock.unlock(); + if (c != 0) { c->dataCallbackTimestamp(timestamp, msgType, dataPtr); } - -#if DEBUG_CLIENT_REFERENCES - if (client->getStrongCount() == 1) { - LOGE("++++++++++++++++ (DATA CALLBACK TIMESTAMP) THIS WILL CAUSE A LOCKUP!"); - client->printRefs(); - } -#endif -} - -// set preview/capture parameters - key/value pairs -status_t CameraService::Client::setParameters(const String8& params) -{ - LOGV("setParameters(%s)", params.string()); - - Mutex::Autolock lock(mLock); - status_t result = checkPid(); - if (result != NO_ERROR) return result; - - if (mHardware == 0) { - LOGE("mHardware is NULL, returning."); - return INVALID_OPERATION; - } - - CameraParameters p(params); - - return mHardware->setParameters(p); -} - -// get preview/capture parameters - key/value pairs -String8 CameraService::Client::getParameters() const -{ - Mutex::Autolock lock(mLock); - - if (mHardware == 0) { - LOGE("mHardware is NULL, returning."); - return String8(); - } - - String8 params(mHardware->getParameters().flatten()); - LOGV("getParameters(%s)", params.string()); - return params; -} - -status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) -{ - LOGV("sendCommand (pid %d)", getCallingPid()); - Mutex::Autolock lock(mLock); - status_t result = checkPid(); - if (result != NO_ERROR) return result; - - if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) { - // The orientation cannot be set during preview. - if (mHardware->previewEnabled()) { - return INVALID_OPERATION; - } - switch (arg1) { - case 0: - mOrientation = ISurface::BufferHeap::ROT_0; - break; - case 90: - mOrientation = ISurface::BufferHeap::ROT_90; - break; - case 180: - mOrientation = ISurface::BufferHeap::ROT_180; - break; - case 270: - mOrientation = ISurface::BufferHeap::ROT_270; - break; - default: - return BAD_VALUE; - } - return OK; - } - - if (mHardware == 0) { - LOGE("mHardware is NULL, returning."); - return INVALID_OPERATION; - } - - return mHardware->sendCommand(cmd, arg1, arg2); } -void CameraService::Client::copyFrameAndPostCopiedFrame(const sp& client, - const sp& heap, size_t offset, size_t size) -{ - LOGV("copyFrameAndPostCopiedFrame"); +void CameraService::Client::copyFrameAndPostCopiedFrame( + const sp& client, const sp& heap, + size_t offset, size_t size) { + LOG2("copyFrameAndPostCopiedFrame"); // It is necessary to copy out of pmem before sending this to // the callback. For efficiency, reuse the same MemoryHeapBase // provided it's big enough. Don't allocate the memory or // perform the copy if there's no callback. - // hold the preview lock while we grab a reference to the preview buffer sp previewBuffer; - { - Mutex::Autolock lock(mPreviewLock); - if (mPreviewBuffer == 0) { - mPreviewBuffer = new MemoryHeapBase(size, 0, NULL); - } else if (size > mPreviewBuffer->virtualSize()) { - mPreviewBuffer.clear(); - mPreviewBuffer = new MemoryHeapBase(size, 0, NULL); - } - if (mPreviewBuffer == 0) { - LOGE("failed to allocate space for preview buffer"); - return; - } - previewBuffer = mPreviewBuffer; + + if (mPreviewBuffer == 0) { + mPreviewBuffer = new MemoryHeapBase(size, 0, NULL); + } else if (size > mPreviewBuffer->virtualSize()) { + mPreviewBuffer.clear(); + mPreviewBuffer = new MemoryHeapBase(size, 0, NULL); + } + if (mPreviewBuffer == 0) { + LOGE("failed to allocate space for preview buffer"); + mLock.unlock(); + return; } - memcpy(previewBuffer->base(), - (uint8_t *)heap->base() + offset, size); + previewBuffer = mPreviewBuffer; + + memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size); sp frame = new MemoryBase(previewBuffer, 0, size); if (frame == 0) { LOGE("failed to allocate space for frame callback"); + mLock.unlock(); return; } + + mLock.unlock(); client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame); } +// ---------------------------------------------------------------------------- + static const int kDumpLockRetries = 50; static const int kDumpLockSleep = 60000; @@ -1307,8 +1227,7 @@ static bool tryLock(Mutex& mutex) return locked; } -status_t CameraService::dump(int fd, const Vector& args) -{ +status_t CameraService::dump(int fd, const Vector& args) { static const char* kDeadlockedString = "CameraService may be deadlocked\n"; const size_t SIZE = 256; @@ -1318,7 +1237,7 @@ status_t CameraService::dump(int fd, const Vector& args) snprintf(buffer, SIZE, "Permission Denial: " "can't dump CameraService from pid=%d, uid=%d\n", getCallingPid(), - IPCThreadState::self()->getCallingUid()); + getCallingUid()); result.append(buffer); write(fd, result.string(), result.size()); } else { @@ -1329,89 +1248,39 @@ status_t CameraService::dump(int fd, const Vector& args) write(fd, result.string(), result.size()); } - if (mClient != 0) { - sp currentClient = mClient.promote(); - sprintf(buffer, "Client (%p) PID: %d\n", - currentClient->getCameraClient()->asBinder().get(), - currentClient->mClientPid); + bool hasClient = false; + for (int i = 0; i < NUM_CAMERAS; i++) { + sp client = mClient[i].promote(); + if (client == 0) continue; + hasClient = true; + sprintf(buffer, "Client[%d] (%p) PID: %d\n", + i, + client->getCameraClient()->asBinder().get(), + client->mClientPid); result.append(buffer); write(fd, result.string(), result.size()); - currentClient->mHardware->dump(fd, args); - } else { + client->mHardware->dump(fd, args); + } + if (!hasClient) { result.append("No camera client yet.\n"); write(fd, result.string(), result.size()); } if (locked) mServiceLock.unlock(); - } - return NO_ERROR; -} - - -status_t CameraService::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - // permission checks... - switch (code) { - case BnCameraService::CONNECT: - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int self_pid = getpid(); - if (pid != self_pid) { - // we're called from a different process, do the real check - if (!checkCallingPermission( - String16("android.permission.CAMERA"))) - { - const int uid = ipc->getCallingUid(); - LOGE("Permission Denial: " - "can't use the camera pid=%d, uid=%d", pid, uid); - return PERMISSION_DENIED; - } - } - break; - } - status_t err = BnCameraService::onTransact(code, data, reply, flags); - -#if DEBUG_HEAP_LEAKS - LOGV("+++ onTransact err %d code %d", err, code); - - if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) { - // the 'service' command interrogates this binder for its name, and then supplies it - // even for the debugging commands. that means we need to check for it here, using - // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to - // BnSurfaceComposer before falling through to this code). - - LOGV("+++ onTransact code %d", code); - - CHECK_INTERFACE(ICameraService, data, reply); - - switch(code) { - case 1000: - { - if (gWeakHeap != 0) { - sp h = gWeakHeap.promote(); - IMemoryHeap *p = gWeakHeap.unsafe_get(); - LOGV("CHECKING WEAK REFERENCE %p (%p)", h.get(), p); - if (h != 0) - h->printRefs(); - bool attempt_to_delete = data.readInt32() == 1; - if (attempt_to_delete) { - // NOT SAFE! - LOGV("DELETING WEAK REFERENCE %p (%p)", h.get(), p); - if (p) delete p; - } - return NO_ERROR; + // change logging level + int n = args.size(); + for (int i = 0; i + 1 < n; i++) { + if (args[i] == String16("-v")) { + String8 levelStr(args[i+1]); + int level = atoi(levelStr.string()); + sprintf(buffer, "Set Log Level to %d", level); + result.append(buffer); + setLogLevel(level); } } - break; - default: - break; - } } -#endif // DEBUG_HEAP_LEAKS - - return err; + return NO_ERROR; } }; // namespace android diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h index bc49b1dbd555b7ddb31c7620e30447a682de02d4..86986cab82e3daa8d0ca972d6852c7f1dd7c44a5 100644 --- a/camera/libcameraservice/CameraService.h +++ b/camera/libcameraservice/CameraService.h @@ -21,207 +21,171 @@ #include #include -#include + +/* This needs to be increased if we can have more cameras */ +#define MAX_CAMERAS 2 namespace android { class MemoryHeapBase; class MediaPlayer; -// ---------------------------------------------------------------------------- - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -// When enabled, this feature allows you to send an event to the CameraService -// so that you can cause all references to the heap object gWeakHeap, defined -// below, to be printed. You will also need to set DEBUG_REFS=1 and -// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp. You just have to -// set gWeakHeap to the appropriate heap you want to track. - -#define DEBUG_HEAP_LEAKS 0 - -// ---------------------------------------------------------------------------- - -class CameraService : public BnCameraService +class CameraService: public BnCameraService { class Client; - public: - static void instantiate(); + static void instantiate(); + + CameraService(); + virtual ~CameraService(); - // ICameraService interface - virtual sp connect(const sp& cameraClient); + virtual int32_t getNumberOfCameras(); + virtual sp connect(const sp& cameraClient, int cameraId); + virtual void removeClient(const sp& cameraClient); + virtual sp getClientById(int cameraId); - virtual status_t dump(int fd, const Vector& args); + virtual status_t dump(int fd, const Vector& args); + virtual status_t onTransact(uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags); - void removeClient(const sp& cameraClient); + enum sound_kind { + SOUND_SHUTTER = 0, + SOUND_RECORDING = 1, + NUM_SOUNDS + }; - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); + void loadSound(); + void playSound(sound_kind kind); + void releaseSound(); private: + Mutex mServiceLock; + wp mClient[MAX_CAMERAS]; // protected by mServiceLock -// ---------------------------------------------------------------------------- + // atomics to record whether the hardware is allocated to some client. + volatile int32_t mBusy[MAX_CAMERAS]; + void setCameraBusy(int cameraId); + void setCameraFree(int cameraId); - class Client : public BnCamera { + // sounds + Mutex mSoundLock; + sp mSoundPlayer[NUM_SOUNDS]; + int mSoundRef; // reference count (release all MediaPlayer when 0) + class Client : public BnCamera + { public: + // ICamera interface (see ICamera for details) virtual void disconnect(); - - // connect new client with existing camera remote virtual status_t connect(const sp& client); - - // prevent other processes from using this ICamera interface virtual status_t lock(); - - // allow other processes to use this ICamera interface virtual status_t unlock(); - - // pass the buffered ISurface to the camera service virtual status_t setPreviewDisplay(const sp& surface); - - // set the preview callback flag to affect how the received frames from - // preview are handled. - virtual void setPreviewCallbackFlag(int callback_flag); - - // start preview mode, must call setPreviewDisplay first + virtual void setPreviewCallbackFlag(int flag); virtual status_t startPreview(); - - // stop preview mode virtual void stopPreview(); - - // get preview state virtual bool previewEnabled(); - - // start recording mode virtual status_t startRecording(); - - // stop recording mode virtual void stopRecording(); - - // get recording state virtual bool recordingEnabled(); - - // release a recording frame virtual void releaseRecordingFrame(const sp& mem); - - // auto focus virtual status_t autoFocus(); - - // cancel auto focus virtual status_t cancelAutoFocus(); - - // take a picture - returns an IMemory (ref-counted mmap) virtual status_t takePicture(); - - // set preview/capture parameters - key/value pairs virtual status_t setParameters(const String8& params); - - // get preview/capture parameters - key/value pairs virtual String8 getParameters() const; - - // send command to camera driver virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2); - - // our client... - const sp& getCameraClient() const { return mCameraClient; } - private: friend class CameraService; Client(const sp& cameraService, - const sp& cameraClient, - pid_t clientPid); - Client(); - virtual ~Client(); - - status_t checkPid(); - - static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user); - static void dataCallback(int32_t msgType, const sp& dataPtr, void* user); - static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, - const sp& dataPtr, void* user); + const sp& cameraClient, + int cameraId, + int clientPid); + ~Client(); - static sp getClientFromCookie(void* user); + // return our camera client + const sp& getCameraClient() { return mCameraClient; } - void handlePreviewData(const sp&); - void handleShutter(image_rect_type *image); - void handlePostview(const sp&); - void handleRawPicture(const sp&); - void handleCompressedPicture(const sp&); + // check whether the calling process matches mClientPid. + status_t checkPid() const; + status_t checkPidAndHardware() const; // also check mHardware != 0 - void copyFrameAndPostCopiedFrame(const sp& client, - const sp& heap, size_t offset, size_t size); + // these are internal functions used to set up preview buffers + status_t registerPreviewBuffers(); + status_t setOverlay(); // camera operation mode enum camera_mode { CAMERA_PREVIEW_MODE = 0, // frame automatically released CAMERA_RECORDING_MODE = 1, // frame has to be explicitly released by releaseRecordingFrame() }; + // these are internal functions used for preview/recording status_t startCameraMode(camera_mode mode); status_t startPreviewMode(); status_t startRecordingMode(); - status_t setOverlay(); - status_t registerPreviewBuffers(); + + // these are static callback functions + static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user); + static void dataCallback(int32_t msgType, const sp& dataPtr, void* user); + static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr, void* user); + // convert client from cookie + static sp getClientFromCookie(void* user); + // handlers for messages + void handleShutter(image_rect_type *size); + void handlePreviewData(const sp& mem); + void handlePostview(const sp& mem); + void handleRawPicture(const sp& mem); + void handleCompressedPicture(const sp& mem); + void handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2); + void handleGenericData(int32_t msgType, const sp& dataPtr); + void handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr); + + void copyFrameAndPostCopiedFrame( + const sp& client, + const sp& heap, + size_t offset, size_t size); + + // these are initialized in the constructor. + sp mCameraService; // immutable after constructor + sp mCameraClient; + int mCameraId; // immutable after constructor + pid_t mClientPid; + sp mHardware; // cleared after disconnect() + bool mUseOverlay; // immutable after constructor + sp mOverlayRef; + int mOverlayW; + int mOverlayH; + int mPreviewCallbackFlag; + int mOrientation; // Ensures atomicity among the public methods - mutable Mutex mLock; - - // mSurfaceLock synchronizes access to mSurface between - // setPreviewSurface() and postPreviewFrame(). Note that among - // the public methods, all accesses to mSurface are - // syncrhonized by mLock. However, postPreviewFrame() is called - // by the CameraHardwareInterface callback, and needs to - // access mSurface. It cannot hold mLock, however, because - // stopPreview() may be holding that lock while attempting - // to stop preview, and stopPreview itself will block waiting - // for a callback from CameraHardwareInterface. If this - // happens, it will cause a deadlock. - mutable Mutex mSurfaceLock; - mutable Condition mReady; - sp mCameraService; - sp mSurface; - int mPreviewCallbackFlag; - int mOrientation; - - sp mMediaPlayerClick; - sp mMediaPlayerBeep; - - // these are immutable once the object is created, - // they don't need to be protected by a lock - sp mCameraClient; - sp mHardware; - pid_t mClientPid; - bool mUseOverlay; - - sp mOverlayRef; - int mOverlayW; - int mOverlayH; - - mutable Mutex mPreviewLock; - sp mPreviewBuffer; + mutable Mutex mLock; + sp mSurface; + + // If the user want us to return a copy of the preview frame (instead + // of the original one), we allocate mPreviewBuffer and reuse it if possible. + sp mPreviewBuffer; + + // We need to avoid the deadlock when the incoming command thread and + // the CameraHardwareInterface callback thread both want to grab mLock. + // An extra flag is used to tell the callback thread that it should stop + // trying to deliver the callback messages if the client is not + // interested in it anymore. For example, if the client is calling + // stopPreview(), the preview frame messages do not need to be delivered + // anymore. + + // This function takes the same parameter as the enableMsgType() and + // disableMsgType() functions in CameraHardwareInterface. + void enableMsgType(int32_t msgType); + void disableMsgType(int32_t msgType); + volatile int32_t mMsgEnabled; + + // This function keeps trying to grab mLock, or give up if the message + // is found to be disabled. It returns true if mLock is grabbed. + bool lockIfMessageWanted(int32_t msgType); }; - -// ---------------------------------------------------------------------------- - - CameraService(); - virtual ~CameraService(); - - // We use a count for number of clients (shoule only be 0 or 1). - volatile int32_t mUsers; - virtual void incUsers(); - virtual void decUsers(); - - mutable Mutex mServiceLock; - wp mClient; - -#if DEBUG_HEAP_LEAKS - wp gWeakHeap; -#endif }; -// ---------------------------------------------------------------------------- - -}; // namespace android +} // namespace android #endif diff --git a/camera/libcameraservice/FakeCamera.cpp b/camera/libcameraservice/FakeCamera.cpp index 67498998272884c48bf9f81ada49d8168d89692f..f3a6a67ee84a4a5db31b4f6022843af8c5ac3cea 100644 --- a/camera/libcameraservice/FakeCamera.cpp +++ b/camera/libcameraservice/FakeCamera.cpp @@ -198,10 +198,11 @@ static const int SHIFT2 = 16; static const int DELTA = kYb*(1 << SHIFT2); static const int GAMMA = kYr*(1 << SHIFT2); -int32_t ccrgb16toyuv_wo_colorkey(uint8_t *rgb16,uint8_t *yuv422,uint32_t *param,uint8_t *table[]) +int32_t ccrgb16toyuv_wo_colorkey(uint8_t *rgb16, uint8_t *yuv420, + uint32_t *param, uint8_t *table[]) { uint16_t *inputRGB = (uint16_t*)rgb16; - uint8_t *outYUV = yuv422; + uint8_t *outYUV = yuv420; int32_t width_dst = param[0]; int32_t height_dst = param[1]; int32_t pitch_dst = param[2]; @@ -260,12 +261,14 @@ uint32_t temp; tempY[0] = y0; tempY[1] = y1; - tempU[0] = u; - tempV[0] = v; - tempY += 2; - tempU += 2; - tempV += 2; + + if ((j&1) == 0) { + tempU[0] = u; + tempV[0] = v; + tempU += 2; + tempV += 2; + } } inputRGB += pitch_src; @@ -277,7 +280,7 @@ uint32_t temp; #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) -static void convert_rgb16_to_yuv422(uint8_t *rgb, uint8_t *yuv, int width, int height) +static void convert_rgb16_to_yuv420(uint8_t *rgb, uint8_t *yuv, int width, int height) { if (!tables_initialized) { initYtab(); @@ -326,7 +329,7 @@ void FakeCamera::setSize(int width, int height) mCheckY = 0; // This will cause it to be reallocated on the next call - // to getNextFrameAsYuv422(). + // to getNextFrameAsYuv420(). delete[] mTmpRgb16Buffer; mTmpRgb16Buffer = 0; } @@ -347,13 +350,13 @@ void FakeCamera::getNextFrameAsRgb565(uint16_t *buffer) mCounter++; } -void FakeCamera::getNextFrameAsYuv422(uint8_t *buffer) +void FakeCamera::getNextFrameAsYuv420(uint8_t *buffer) { if (mTmpRgb16Buffer == 0) mTmpRgb16Buffer = new uint16_t[mWidth * mHeight]; getNextFrameAsRgb565(mTmpRgb16Buffer); - convert_rgb16_to_yuv422((uint8_t*)mTmpRgb16Buffer, buffer, mWidth, mHeight); + convert_rgb16_to_yuv420((uint8_t*)mTmpRgb16Buffer, buffer, mWidth, mHeight); } void FakeCamera::drawSquare(uint16_t *dst, int x, int y, int size, int color, int shadow) diff --git a/camera/libcameraservice/FakeCamera.h b/camera/libcameraservice/FakeCamera.h index f7f880328a4c416a2b52ff86e1098c6fe4e9a53d..724de207f82ea96c682d47bfc29a1454605a3dfe 100644 --- a/camera/libcameraservice/FakeCamera.h +++ b/camera/libcameraservice/FakeCamera.h @@ -40,7 +40,7 @@ public: ~FakeCamera(); void setSize(int width, int height); - void getNextFrameAsYuv422(uint8_t *buffer); + void getNextFrameAsYuv420(uint8_t *buffer); // Write to the fd a string representing the current state. void dump(int fd) const; diff --git a/camera/tests/CameraServiceTest/Android.mk b/camera/tests/CameraServiceTest/Android.mk index 9bb190abcd4f34159fbb8180f5519fd9c9125721..cf4e42ff8742a992d1568b47ad16e7d19b544a99 100644 --- a/camera/tests/CameraServiceTest/Android.mk +++ b/camera/tests/CameraServiceTest/Android.mk @@ -21,4 +21,6 @@ LOCAL_SHARED_LIBRARIES += \ libcamera_client \ libsurfaceflinger_client -include $(BUILD_EXECUTABLE) +# Disable it because the ISurface interface may change, and before we have a +# chance to fix this test, we don't want to break normal builds. +#include $(BUILD_EXECUTABLE) diff --git a/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/camera/tests/CameraServiceTest/CameraServiceTest.cpp index 9fc795b3e11e9098d6fa0ab7ab3ec7632372728c..3c8d55397a95fd15ced044f4e720fa32bd0abb22 100644 --- a/camera/tests/CameraServiceTest/CameraServiceTest.cpp +++ b/camera/tests/CameraServiceTest/CameraServiceTest.cpp @@ -38,7 +38,7 @@ void assert_fail(const char *file, int line, const char *func, const char *expr) INFO("assertion failed at file %s, line %d, function %s:", file, line, func); INFO("%s", expr); - exit(1); + abort(); } void assert_eq_fail(const char *file, int line, const char *func, @@ -46,7 +46,7 @@ void assert_eq_fail(const char *file, int line, const char *func, INFO("assertion failed at file %s, line %d, function %s:", file, line, func); INFO("(expected) %s != (actual) %d", expr, actual); - exit(1); + abort(); } #define ASSERT(e) \ @@ -155,7 +155,7 @@ public: virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2); virtual void dataCallback(int32_t msgType, const sp& data); virtual void dataCallbackTimestamp(nsecs_t timestamp, - int32_t msgType, const sp& data) {} + int32_t msgType, const sp& data); // new functions void clearStat(); @@ -176,6 +176,7 @@ private: DefaultKeyedVector mDataCount; DefaultKeyedVector mDataSize; bool test(OP op, int v1, int v2); + void assertTest(OP op, int v1, int v2); ICamera *mReleaser; }; @@ -199,26 +200,33 @@ bool MCameraClient::test(OP op, int v1, int v2) { return false; } +void MCameraClient::assertTest(OP op, int v1, int v2) { + if (!test(op, v1, v2)) { + LOGE("assertTest failed: op=%d, v1=%d, v2=%d", op, v1, v2); + ASSERT(0); + } +} + void MCameraClient::assertNotify(int32_t msgType, OP op, int count) { Mutex::Autolock _l(mLock); int v = mNotifyCount.valueFor(msgType); - ASSERT(test(op, v, count)); + assertTest(op, v, count); } void MCameraClient::assertData(int32_t msgType, OP op, int count) { Mutex::Autolock _l(mLock); int v = mDataCount.valueFor(msgType); - ASSERT(test(op, v, count)); + assertTest(op, v, count); } void MCameraClient::assertDataSize(int32_t msgType, OP op, int dataSize) { Mutex::Autolock _l(mLock); int v = mDataSize.valueFor(msgType); - ASSERT(test(op, v, dataSize)); + assertTest(op, v, dataSize); } void MCameraClient::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) { - INFO(__func__); + INFO("%s", __func__); Mutex::Autolock _l(mLock); ssize_t i = mNotifyCount.indexOfKey(msgType); if (i < 0) { @@ -230,7 +238,7 @@ void MCameraClient::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) } void MCameraClient::dataCallback(int32_t msgType, const sp& data) { - INFO(__func__); + INFO("%s", __func__); int dataSize = data->size(); INFO("data type = %d, size = %d", msgType, dataSize); Mutex::Autolock _l(mLock); @@ -250,6 +258,11 @@ void MCameraClient::dataCallback(int32_t msgType, const sp& data) { } } +void MCameraClient::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, + const sp& data) { + dataCallback(msgType, data); +} + void MCameraClient::waitNotify(int32_t msgType, OP op, int count) { INFO("waitNotify: %d, %d, %d", msgType, op, count); Mutex::Autolock _l(mLock); @@ -285,6 +298,7 @@ public: virtual sp createOverlay( uint32_t w, uint32_t h, int32_t format, int32_t orientation); virtual sp requestBuffer(int bufferIdx, int usage); + virtual status_t setBufferCount(int bufferCount); // new functions void clearStat(); @@ -300,7 +314,7 @@ private: }; status_t MSurface::registerBuffers(const BufferHeap& buffers) { - INFO(__func__); + INFO("%s", __func__); Mutex::Autolock _l(mLock); ++registerBuffersCount; mCond.signal(); @@ -308,21 +322,26 @@ status_t MSurface::registerBuffers(const BufferHeap& buffers) { } void MSurface::postBuffer(ssize_t offset) { - // INFO(__func__); + // INFO("%s", __func__); Mutex::Autolock _l(mLock); ++postBufferCount; mCond.signal(); } void MSurface::unregisterBuffers() { - INFO(__func__); + INFO("%s", __func__); Mutex::Autolock _l(mLock); ++unregisterBuffersCount; mCond.signal(); } sp MSurface::requestBuffer(int bufferIdx, int usage) { - INFO(__func__); + INFO("%s", __func__); + return NULL; +} + +status_t MSurface::setBufferCount(int bufferCount) { + INFO("%s", __func__); return NULL; } @@ -348,10 +367,9 @@ void MSurface::waitUntil(int c0, int c1, int c2) { sp MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format, int32_t orientation) { - // We don't expect this to be called in current hardware. + // Not implemented. ASSERT(0); - sp dummy; - return dummy; + return NULL; } // @@ -368,17 +386,17 @@ sp getHolder() { } void putTempObject(sp obj) { - INFO(__func__); + INFO("%s", __func__); getHolder()->put(obj); } sp getTempObject() { - INFO(__func__); + INFO("%s", __func__); return getHolder()->get(); } void clearTempObject() { - INFO(__func__); + INFO("%s", __func__); getHolder()->clear(); } @@ -395,64 +413,71 @@ sp getCameraService() { return cs; } +int getNumberOfCameras() { + sp cs = getCameraService(); + return cs->getNumberOfCameras(); +} + // // Various Connect Tests // -void testConnect() { - INFO(__func__); +void testConnect(int cameraId) { + INFO("%s", __func__); sp cs = getCameraService(); sp cc = new MCameraClient(); - sp c = cs->connect(cc); + sp c = cs->connect(cc, cameraId); ASSERT(c != 0); c->disconnect(); } -void testAllowConnectOnceOnly() { - INFO(__func__); +void testAllowConnectOnceOnly(int cameraId) { + INFO("%s", __func__); sp cs = getCameraService(); // Connect the first client. sp cc = new MCameraClient(); - sp c = cs->connect(cc); + sp c = cs->connect(cc, cameraId); ASSERT(c != 0); // Same client -- ok. - ASSERT(cs->connect(cc) != 0); + ASSERT(cs->connect(cc, cameraId) != 0); // Different client -- not ok. sp cc2 = new MCameraClient(); - ASSERT(cs->connect(cc2) == 0); + ASSERT(cs->connect(cc2, cameraId) == 0); c->disconnect(); } void testReconnectFailed() { - INFO(__func__); + INFO("%s", __func__); sp c = interface_cast(getTempObject()); - sp cc2 = new MCameraClient(); - ASSERT(c->connect(cc2) != NO_ERROR); + sp cc = new MCameraClient(); + ASSERT(c->connect(cc) != NO_ERROR); } void testReconnectSuccess() { - INFO(__func__); + INFO("%s", __func__); sp c = interface_cast(getTempObject()); sp cc = new MCameraClient(); ASSERT(c->connect(cc) == NO_ERROR); + c->disconnect(); } void testLockFailed() { - INFO(__func__); + INFO("%s", __func__); sp c = interface_cast(getTempObject()); ASSERT(c->lock() != NO_ERROR); } void testLockUnlockSuccess() { - INFO(__func__); + INFO("%s", __func__); sp c = interface_cast(getTempObject()); ASSERT(c->lock() == NO_ERROR); ASSERT(c->unlock() == NO_ERROR); } void testLockSuccess() { - INFO(__func__); + INFO("%s", __func__); sp c = interface_cast(getTempObject()); ASSERT(c->lock() == NO_ERROR); + c->disconnect(); } // @@ -499,11 +524,11 @@ void runInAnotherProcess(const char *tag) { } } -void testReconnect() { - INFO(__func__); +void testReconnect(int cameraId) { + INFO("%s", __func__); sp cs = getCameraService(); sp cc = new MCameraClient(); - sp c = cs->connect(cc); + sp c = cs->connect(cc, cameraId); ASSERT(c != 0); // Reconnect to the same client -- ok. ASSERT(c->connect(cc) == NO_ERROR); @@ -514,10 +539,10 @@ void testReconnect() { cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0); } -void testLockUnlock() { +void testLockUnlock(int cameraId) { sp cs = getCameraService(); sp cc = new MCameraClient(); - sp c = cs->connect(cc); + sp c = cs->connect(cc, cameraId); ASSERT(c != 0); // We can lock as many times as we want. ASSERT(c->lock() == NO_ERROR); @@ -530,16 +555,15 @@ void testLockUnlock() { runInAnotherProcess("testLockUnlockSuccess"); // Unlock then lock from a different process -- ok. runInAnotherProcess("testLockSuccess"); - c->disconnect(); clearTempObject(); } -void testReconnectFromAnotherProcess() { - INFO(__func__); +void testReconnectFromAnotherProcess(int cameraId) { + INFO("%s", __func__); sp cs = getCameraService(); sp cc = new MCameraClient(); - sp c = cs->connect(cc); + sp c = cs->connect(cc, cameraId); ASSERT(c != 0); // Reconnect from a different process -- not ok. putTempObject(c->asBinder()); @@ -547,7 +571,6 @@ void testReconnectFromAnotherProcess() { // Unlock then reconnect from a different process -- ok. ASSERT(c->unlock() == NO_ERROR); runInAnotherProcess("testReconnectSuccess"); - c->disconnect(); clearTempObject(); } @@ -560,10 +583,11 @@ static void flushCommands() { } // Run a test case -#define RUN(class_name) do { \ +#define RUN(class_name, cameraId) do { \ { \ INFO(#class_name); \ class_name instance; \ + instance.init(cameraId); \ instance.run(); \ } \ flushCommands(); \ @@ -571,19 +595,21 @@ static void flushCommands() { // Base test case after the the camera is connected. class AfterConnect { -protected: - sp cs; - sp cc; - sp c; - - AfterConnect() { +public: + void init(int cameraId) { cs = getCameraService(); cc = new MCameraClient(); - c = cs->connect(cc); + c = cs->connect(cc, cameraId); ASSERT(c != 0); } +protected: + sp cs; + sp cc; + sp c; + ~AfterConnect() { + c->disconnect(); c.clear(); cc.clear(); cs.clear(); @@ -612,19 +638,16 @@ public: surface->waitUntil(1, 10, 0); // needs 1 registerBuffers and 10 postBuffer surface->clearStat(); - c->disconnect(); - // TODO: CameraService crashes for this. Fix it. -#if 0 sp another_surface = new MSurface(); c->setPreviewDisplay(another_surface); // just to make sure unregisterBuffers // is called. surface->waitUntil(0, 0, 1); // needs unregisterBuffers -#endif + cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0); } }; -class TestStartPreviewWithoutDisplay : AfterConnect { +class TestStartPreviewWithoutDisplay : public AfterConnect { public: void run() { ASSERT(c->startPreview() == NO_ERROR); @@ -636,15 +659,17 @@ public: // Base test case after the the camera is connected and the preview is started. class AfterStartPreview : public AfterConnect { -protected: - sp surface; - - AfterStartPreview() { +public: + void init(int cameraId) { + AfterConnect::init(cameraId); surface = new MSurface(); ASSERT(c->setPreviewDisplay(surface) == NO_ERROR); ASSERT(c->startPreview() == NO_ERROR); } +protected: + sp surface; + ~AfterStartPreview() { surface.clear(); } @@ -680,9 +705,6 @@ public: cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1); cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1); c->stopPreview(); -#if 1 // TODO: It crashes if we don't have this. Fix it. - usleep(100000); -#endif c->disconnect(); cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0); } @@ -697,7 +719,6 @@ public: cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1); cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1); cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1); - usleep(100000); // 100ms } c->disconnect(); cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0); @@ -708,36 +729,71 @@ class TestGetParameters: public AfterStartPreview { public: void run() { String8 param_str = c->getParameters(); - INFO(param_str); + INFO("%s", static_cast(param_str)); } }; +static bool getNextSize(const char **ptrS, int *w, int *h) { + const char *s = *ptrS; + + // skip over ',' + if (*s == ',') s++; + + // remember start position in p + const char *p = s; + while (*s != '\0' && *s != 'x') { + s++; + } + if (*s == '\0') return false; + + // get the width + *w = atoi(p); + + // skip over 'x' + ASSERT(*s == 'x'); + p = s + 1; + while (*s != '\0' && *s != ',') { + s++; + } + + // get the height + *h = atoi(p); + *ptrS = s; + return true; +} + class TestPictureSize : public AfterStartPreview { public: void checkOnePicture(int w, int h) { - const float rate = 0.5; // byte per pixel limit + const float rate = 0.9; // byte per pixel limit int pixels = w * h; CameraParameters param(c->getParameters()); param.setPictureSize(w, h); + // disable thumbnail to get more accurate size. + param.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, 0); + param.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, 0); c->setParameters(param.flatten()); cc->clearStat(); ASSERT(c->takePicture() == NO_ERROR); cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1); - cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2); + //cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2); cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1); cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::LT, int(pixels * rate)); cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::GT, 0); cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0); - usleep(100000); // 100ms } void run() { - checkOnePicture(2048, 1536); - checkOnePicture(1600, 1200); - checkOnePicture(1024, 768); + CameraParameters param(c->getParameters()); + int w, h; + const char *s = param.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES); + while (getNextSize(&s, &w, &h)) { + LOGD("checking picture size %dx%d", w, h); + checkOnePicture(w, h); + } } }; @@ -749,6 +805,8 @@ public: // Try all flag combinations. for (int v = 0; v < 8; v++) { + LOGD("TestPreviewCallbackFlag: flag=%d", v); + usleep(100000); // sleep a while to clear the in-flight callbacks. cc->clearStat(); c->setPreviewCallbackFlag(v); ASSERT(c->previewEnabled() == false); @@ -781,6 +839,7 @@ public: ASSERT(c->recordingEnabled() == true); sleep(2); c->stopRecording(); + usleep(100000); // sleep a while to clear the in-flight callbacks. cc->setReleaser(NULL); cc->assertData(CAMERA_MSG_VIDEO_FRAME, MCameraClient::GE, 10); } @@ -806,9 +865,13 @@ public: } void run() { - checkOnePicture(480, 320); - checkOnePicture(352, 288); - checkOnePicture(176, 144); + CameraParameters param(c->getParameters()); + int w, h; + const char *s = param.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES); + while (getNextSize(&s, &w, &h)) { + LOGD("checking preview size %dx%d", w, h); + checkOnePicture(w, h); + } } }; @@ -827,23 +890,30 @@ int main(int argc, char **argv) INFO("CameraServiceTest start"); gExecutable = argv[0]; runHolderService(); - - testConnect(); flushCommands(); - testAllowConnectOnceOnly(); flushCommands(); - testReconnect(); flushCommands(); - testLockUnlock(); flushCommands(); - testReconnectFromAnotherProcess(); flushCommands(); - - RUN(TestSetPreviewDisplay); - RUN(TestStartPreview); - RUN(TestStartPreviewWithoutDisplay); - RUN(TestAutoFocus); - RUN(TestStopPreview); - RUN(TestTakePicture); - RUN(TestTakeMultiplePictures); - RUN(TestGetParameters); - RUN(TestPictureSize); - RUN(TestPreviewCallbackFlag); - RUN(TestRecording); - RUN(TestPreviewSize); + int n = getNumberOfCameras(); + INFO("%d Cameras available", n); + + for (int id = 0; id < n; id++) { + INFO("Testing camera %d", id); + testConnect(id); flushCommands(); + testAllowConnectOnceOnly(id); flushCommands(); + testReconnect(id); flushCommands(); + testLockUnlock(id); flushCommands(); + testReconnectFromAnotherProcess(id); flushCommands(); + + RUN(TestSetPreviewDisplay, id); + RUN(TestStartPreview, id); + RUN(TestStartPreviewWithoutDisplay, id); + RUN(TestAutoFocus, id); + RUN(TestStopPreview, id); + RUN(TestTakePicture, id); + RUN(TestTakeMultiplePictures, id); + RUN(TestGetParameters, id); + RUN(TestPictureSize, id); + RUN(TestPreviewCallbackFlag, id); + RUN(TestRecording, id); + RUN(TestPreviewSize, id); + } + + INFO("CameraServiceTest finished"); } diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 736ac08f058601565f039cfc5632c4f6800ab55c..301883f43c1f61a666088c1c6e435a9048a17a78 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -205,7 +205,7 @@ public class Am { String uri = nextArg(); if (uri != null) { Intent oldIntent = intent; - intent = Intent.getIntent(uri); + intent = Intent.parseUri(uri, 0); if (oldIntent.getAction() != null) { intent.setAction(oldIntent.getAction()); } diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index ac2eb0d1d8aee31527a9807bc8fb7a0a96bba9d9..7a7f8ed352152b6541f078fceafc962b97457981 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include diff --git a/cmds/input/input b/cmds/input/input old mode 100644 new mode 100755 diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index 41f070ca27758ee98cfecf7ca4b4b4b3c2475f8c..b8ba3f6db55809975c0ae3752fd688f85ef59e8c 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -16,7 +16,7 @@ #include "installd.h" -int install(const char *pkgname, uid_t uid, gid_t gid) +int install(const char *pkgname, int encrypted_fs_flag, uid_t uid, gid_t gid) { char pkgdir[PKG_PATH_MAX]; char libdir[PKG_PATH_MAX]; @@ -27,11 +27,17 @@ int install(const char *pkgname, uid_t uid, gid_t gid) } - if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) - return -1; - if (create_pkg_path(libdir, PKG_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX)) - return -1; - + if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { + if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + if (create_pkg_path(libdir, PKG_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX)) + return -1; + } else { + if (create_pkg_path(pkgdir, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + if (create_pkg_path(libdir, PKG_SEC_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX)) + return -1; + } if (mkdir(pkgdir, 0751) < 0) { LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); @@ -56,27 +62,38 @@ int install(const char *pkgname, uid_t uid, gid_t gid) return 0; } -int uninstall(const char *pkgname) +int uninstall(const char *pkgname, int encrypted_fs_flag) { char pkgdir[PKG_PATH_MAX]; - if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) - return -1; + if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { + if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + } else { + if (create_pkg_path(pkgdir, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + } /* delete contents AND directory, no exceptions */ return delete_dir_contents(pkgdir, 1, 0); } -int renamepkg(const char *oldpkgname, const char *newpkgname) +int renamepkg(const char *oldpkgname, const char *newpkgname, int encrypted_fs_flag) { char oldpkgdir[PKG_PATH_MAX]; char newpkgdir[PKG_PATH_MAX]; - if (create_pkg_path(oldpkgdir, PKG_DIR_PREFIX, oldpkgname, PKG_DIR_POSTFIX)) - return -1; - if (create_pkg_path(newpkgdir, PKG_DIR_PREFIX, newpkgname, PKG_DIR_POSTFIX)) - return -1; - + if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { + if (create_pkg_path(oldpkgdir, PKG_DIR_PREFIX, oldpkgname, PKG_DIR_POSTFIX)) + return -1; + if (create_pkg_path(newpkgdir, PKG_DIR_PREFIX, newpkgname, PKG_DIR_POSTFIX)) + return -1; + } else { + if (create_pkg_path(oldpkgdir, PKG_SEC_DIR_PREFIX, oldpkgname, PKG_DIR_POSTFIX)) + return -1; + if (create_pkg_path(newpkgdir, PKG_SEC_DIR_PREFIX, newpkgname, PKG_DIR_POSTFIX)) + return -1; + } if (rename(oldpkgdir, newpkgdir) < 0) { LOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno)); @@ -85,29 +102,41 @@ int renamepkg(const char *oldpkgname, const char *newpkgname) return 0; } -int delete_user_data(const char *pkgname) +int delete_user_data(const char *pkgname, int encrypted_fs_flag) { char pkgdir[PKG_PATH_MAX]; - if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) - return -1; + if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { + if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + } else { + if (create_pkg_path(pkgdir, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) + return -1; + } /* delete contents, excluding "lib", but not the directory itself */ return delete_dir_contents(pkgdir, 0, "lib"); } -int delete_cache(const char *pkgname) +int delete_cache(const char *pkgname, int encrypted_fs_flag) { char cachedir[PKG_PATH_MAX]; - if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX)) - return -1; - + if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { + if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX)) + return -1; + } else { + if (create_pkg_path(cachedir, CACHE_SEC_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX)) + return -1; + } /* delete contents, not the directory, no exceptions */ return delete_dir_contents(cachedir, 0, 0); } +/* TODO(oam): depending on use case (ecryptfs or dmcrypt) + * change implementation + */ static int disk_free() { struct statfs sfs; @@ -139,6 +168,39 @@ int free_cache(int free_size) LOGI("free_cache(%d) avail %d\n", free_size, avail); if (avail >= free_size) return 0; + /* First try encrypted dir */ + d = opendir(PKG_SEC_DIR_PREFIX); + if (d == NULL) { + LOGE("cannot open %s\n", PKG_SEC_DIR_PREFIX); + } else { + dfd = dirfd(d); + + while ((de = readdir(d))) { + if (de->d_type != DT_DIR) continue; + name = de->d_name; + + /* always skip "." and ".." */ + if (name[0] == '.') { + if (name[1] == 0) continue; + if ((name[1] == '.') && (name[2] == 0)) continue; + } + + subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); + if (subfd < 0) continue; + + delete_dir_contents_fd(subfd, "cache"); + close(subfd); + + avail = disk_free(); + if (avail >= free_size) { + closedir(d); + return 0; + } + } + closedir(d); + } + + /* Next try unencrypted dir... */ d = opendir(PKG_DIR_PREFIX); if (d == NULL) { LOGE("cannot open %s\n", PKG_DIR_PREFIX); @@ -314,7 +376,7 @@ static int calculate_dir_size(int dfd) int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath, - int *_codesize, int *_datasize, int *_cachesize) + int *_codesize, int *_datasize, int *_cachesize, int encrypted_fs_flag) { DIR *d; int dfd; @@ -349,8 +411,14 @@ int get_size(const char *pkgname, const char *apkpath, } } - if (create_pkg_path(path, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) { - goto done; + if (encrypted_fs_flag == 0) { + if (create_pkg_path(path, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) { + goto done; + } + } else { + if (create_pkg_path(path, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) { + goto done; + } } d = opendir(path); diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index f6ca9980a0fd67e5497db026bc403ac7a00dcac7..882c493b59719fd4fc405dbb0a04952a56356733 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -29,7 +29,7 @@ static int do_ping(char **arg, char reply[REPLY_MAX]) static int do_install(char **arg, char reply[REPLY_MAX]) { - return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */ + return install(arg[0], atoi(arg[1]), atoi(arg[2]), atoi(arg[3])); /* pkgname, uid, gid */ } static int do_dexopt(char **arg, char reply[REPLY_MAX]) @@ -50,12 +50,12 @@ static int do_rm_dex(char **arg, char reply[REPLY_MAX]) static int do_remove(char **arg, char reply[REPLY_MAX]) { - return uninstall(arg[0]); /* pkgname */ + return uninstall(arg[0], atoi(arg[1])); /* pkgname */ } static int do_rename(char **arg, char reply[REPLY_MAX]) { - return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */ + return renamepkg(arg[0], arg[1], atoi(arg[2])); /* oldpkgname, newpkgname */ } static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */ @@ -65,7 +65,7 @@ static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_siz static int do_rm_cache(char **arg, char reply[REPLY_MAX]) { - return delete_cache(arg[0]); /* pkgname */ + return delete_cache(arg[0], atoi(arg[1])); /* pkgname */ } static int do_protect(char **arg, char reply[REPLY_MAX]) @@ -81,7 +81,7 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) int res = 0; /* pkgdir, apkpath */ - res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize); + res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize, atoi(arg[3])); sprintf(reply,"%d %d %d", codesize, datasize, cachesize); return res; @@ -89,7 +89,7 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) static int do_rm_user_data(char **arg, char reply[REPLY_MAX]) { - return delete_user_data(arg[0]); /* pkgname */ + return delete_user_data(arg[0], atoi(arg[1])); /* pkgname */ } static int do_movefiles(char **arg, char reply[REPLY_MAX]) @@ -105,17 +105,17 @@ struct cmdinfo { struct cmdinfo cmds[] = { { "ping", 0, do_ping }, - { "install", 3, do_install }, + { "install", 4, do_install }, { "dexopt", 3, do_dexopt }, { "movedex", 2, do_move_dex }, { "rmdex", 1, do_rm_dex }, - { "remove", 1, do_remove }, - { "rename", 2, do_rename }, + { "remove", 2, do_remove }, + { "rename", 3, do_rename }, { "freecache", 1, do_free_cache }, - { "rmcache", 1, do_rm_cache }, + { "rmcache", 2, do_rm_cache }, { "protect", 2, do_protect }, - { "getsize", 3, do_get_size }, - { "rmuserdata", 1, do_rm_user_data }, + { "getsize", 4, do_get_size }, + { "rmuserdata", 2, do_rm_user_data }, { "movefiles", 0, do_movefiles }, }; diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index cfcdb98f7e65297941f9401205ae562eabdeed5a..8e4adb10ff2ba27b6356e69f1fb6808ce69da89e 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -48,16 +48,23 @@ /* elements combined with a valid package name to form paths */ #define PKG_DIR_PREFIX "/data/data/" +#define PKG_SEC_DIR_PREFIX "/data/secure/data/" #define PKG_DIR_POSTFIX "" #define PKG_LIB_PREFIX "/data/data/" +#define PKG_SEC_LIB_PREFIX "/data/secure/data/" #define PKG_LIB_POSTFIX "/lib" #define CACHE_DIR_PREFIX "/data/data/" +#define CACHE_SEC_DIR_PREFIX "/data/secure/data/" #define CACHE_DIR_POSTFIX "/cache" #define APK_DIR_PREFIX "/data/app/" +/* Encrypted File SYstems constants */ +#define USE_ENCRYPTED_FS 1 +#define USE_UNENCRYPTED_FS 0 + /* other handy constants */ #define PROTECTED_DIR_PREFIX "/data/app-private/" @@ -89,16 +96,16 @@ int delete_dir_contents_fd(int dfd, const char *name); /* commands.c */ -int install(const char *pkgname, uid_t uid, gid_t gid); -int uninstall(const char *pkgname); -int renamepkg(const char *oldpkgname, const char *newpkgname); -int delete_user_data(const char *pkgname); -int delete_cache(const char *pkgname); +int install(const char *pkgname, int encrypted_fs_flag, uid_t uid, gid_t gid); +int uninstall(const char *pkgname, int encrypted_fs_flag); +int renamepkg(const char *oldpkgname, const char *newpkgname, int encrypted_fs_flag); +int delete_user_data(const char *pkgname, int encrypted_fs_flag); +int delete_cache(const char *pkgname, int encrypted_fs_flag); int move_dex(const char *src, const char *dst); int rm_dex(const char *path); int protect(char *pkgname, gid_t gid); int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath, - int *codesize, int *datasize, int *cachesize); + int *codesize, int *datasize, int *cachesize, int encrypted_fs_flag); int free_cache(int free_size); int dexopt(const char *apk_path, uid_t uid, int is_public); int movefiles(); diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp index 845c85471f9204ef2a1ba97ed55acdc74a143db3..5a87f4ca2a6e38b221c1fcefcd1d398025c25a25 100644 --- a/cmds/stagefright/record.cpp +++ b/cmds/stagefright/record.cpp @@ -147,7 +147,7 @@ int main(int argc, char **argv) { OMXClient client; CHECK_EQ(client.connect(), OK); -#if 1 +#if 0 sp source = createSource(argv[1]); if (source == NULL) { @@ -165,14 +165,15 @@ int main(int argc, char **argv) { success = success && meta->findInt32(kKeyHeight, &height); CHECK(success); #else - int width = 800; + int width = 720; int height = 480; sp decoder = new DummySource(width, height); #endif sp enc_meta = new MetaData; // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); - enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); + // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); + enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); enc_meta->setInt32(kKeyWidth, width); enc_meta->setInt32(kKeyHeight, height); @@ -213,6 +214,8 @@ int main(int argc, char **argv) { #if 0 CameraSource *source = CameraSource::Create(); + source->start(); + printf("source = %p\n", source); for (int i = 0; i < 100; ++i) { @@ -227,6 +230,8 @@ int main(int argc, char **argv) { buffer = NULL; } + source->stop(); + delete source; source = NULL; #endif diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index b838f320776feee43f63df3fa5144306e75fae8e..94086fa0ce70c2452d75f73026386eeaddd4e5f2 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -85,6 +85,7 @@ static void playSource(OMXClient *client, const sp &source) { if (gPlaybackAudio) { AudioPlayer *player = new AudioPlayer(NULL); player->setSource(rawSource); + rawSource.clear(); player->start(true /* sourceAlreadyStarted */); @@ -95,6 +96,8 @@ static void playSource(OMXClient *client, const sp &source) { delete player; player = NULL; + + return; } else if (gReproduceBug >= 3 && gReproduceBug <= 5) { int64_t durationUs; CHECK(meta->findInt64(kKeyDuration, &durationUs)); diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 1cd7aa77e2719184beba3aed3147a4385f24f785..1d9e0f166c5b5b2b43fdd16acf678b5040239e96 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -1483,7 +1483,13 @@ public class AccountManagerService } private static String getDatabaseName() { - return DATABASE_NAME; + if(Environment.isEncryptedFilesystemEnabled()) { + // Hard-coded path in case of encrypted file system + return Environment.getSystemSecureDirectory().getPath() + File.separator + DATABASE_NAME; + } else { + // Regular path in case of non-encrypted file system + return DATABASE_NAME; + } } private class DatabaseHelper extends SQLiteOpenHelper { diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index f471f579e482136c3ae595fab2b90889b6f52bec..11b7b0227934d8644734c09ef7bd188ef925429b 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2173,6 +2173,39 @@ class ContextImpl extends Context { throws NameNotFoundException { return getApplicationIcon(getApplicationInfo(packageName, 0)); } + + @Override + public Drawable getActivityLogo(ComponentName activityName) + throws NameNotFoundException { + return getActivityInfo(activityName, 0).loadLogo(this); + } + + @Override + public Drawable getActivityLogo(Intent intent) + throws NameNotFoundException { + if (intent.getComponent() != null) { + return getActivityLogo(intent.getComponent()); + } + + ResolveInfo info = resolveActivity( + intent, PackageManager.MATCH_DEFAULT_ONLY); + if (info != null) { + return info.activityInfo.loadLogo(this); + } + + throw new NameNotFoundException(intent.toUri(0)); + } + + @Override + public Drawable getApplicationLogo(ApplicationInfo info) { + return info.loadLogo(this); + } + + @Override + public Drawable getApplicationLogo(String packageName) + throws NameNotFoundException { + return getApplicationLogo(getApplicationInfo(packageName, 0)); + } @Override public Resources getResourcesForActivity( ComponentName activityName) throws NameNotFoundException { diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..fd20b71c18b6d3d53def33d3088d3a664c1b1e43 --- /dev/null +++ b/core/java/android/app/NativeActivity.java @@ -0,0 +1,141 @@ +package android.app; + +import dalvik.system.PathClassLoader; + +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.view.SurfaceHolder; + +import java.io.File; + +/** + * Convenience for implementing an activity that will be implemented + * purely in native code. That is, a game (or game-like thing). + */ +public class NativeActivity extends Activity implements SurfaceHolder.Callback { + public static final String META_DATA_LIB_NAME = "android.app.lib_name"; + + private int mNativeHandle; + + private native int loadNativeCode(String path); + private native void unloadNativeCode(int handle); + + private native void onStartNative(int handle); + private native void onResumeNative(int handle); + private native void onSaveInstanceStateNative(int handle); + private native void onPauseNative(int handle); + private native void onStopNative(int handle); + private native void onLowMemoryNative(int handle); + private native void onWindowFocusChangedNative(int handle, boolean focused); + private native void onSurfaceCreatedNative(int handle, SurfaceHolder holder); + private native void onSurfaceChangedNative(int handle, SurfaceHolder holder, + int format, int width, int height); + private native void onSurfaceDestroyedNative(int handle, SurfaceHolder holder); + + @Override + protected void onCreate(Bundle savedInstanceState) { + String libname = "main"; + ActivityInfo ai; + + getWindow().takeSurface(this); + + try { + ai = getPackageManager().getActivityInfo( + getIntent().getComponent(), PackageManager.GET_META_DATA); + if (ai.metaData != null) { + String ln = ai.metaData.getString(META_DATA_LIB_NAME); + if (ln != null) libname = ln; + } + } catch (PackageManager.NameNotFoundException e) { + throw new RuntimeException("Error getting activity info", e); + } + + String path = null; + + if ((ai.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) == 0) { + // If the application does not have (Java) code, then no ClassLoader + // has been set up for it. We will need to do our own search for + // the native code. + path = ai.applicationInfo.dataDir + "/lib/" + System.mapLibraryName(libname); + if (!(new File(path)).exists()) { + path = null; + } + } + + if (path == null) { + path = ((PathClassLoader)getClassLoader()).findLibrary(libname); + } + + if (path == null) { + throw new IllegalArgumentException("Unable to find native library: " + libname); + } + + mNativeHandle = loadNativeCode(path); + if (mNativeHandle == 0) { + throw new IllegalArgumentException("Unable to load native library: " + path); + } + super.onCreate(savedInstanceState); + } + + @Override + protected void onDestroy() { + unloadNativeCode(mNativeHandle); + super.onDestroy(); + } + + @Override + protected void onPause() { + super.onPause(); + onPauseNative(mNativeHandle); + } + + @Override + protected void onResume() { + super.onResume(); + onResumeNative(mNativeHandle); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + onSaveInstanceStateNative(mNativeHandle); + } + + @Override + protected void onStart() { + super.onStart(); + onStartNative(mNativeHandle); + } + + @Override + protected void onStop() { + super.onStop(); + onStopNative(mNativeHandle); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + onLowMemoryNative(mNativeHandle); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + onWindowFocusChangedNative(mNativeHandle, hasFocus); + } + + public void surfaceCreated(SurfaceHolder holder) { + onSurfaceCreatedNative(mNativeHandle, holder); + } + + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + onSurfaceChangedNative(mNativeHandle, holder, format, width, height); + } + + public void surfaceDestroyed(SurfaceHolder holder) { + onSurfaceDestroyedNative(mNativeHandle, holder); + } +} diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java index 377e38373cb6eb2d65ca5ea23fa050f911189ef8..fc2dfc07b0e17a50e2652727d2ec82f082e7e124 100644 --- a/core/java/android/content/ContentService.java +++ b/core/java/android/content/ContentService.java @@ -537,6 +537,9 @@ public final class ContentService extends IContentService.Stub { // Look to see if the proper child already exists String segment = getUriSegment(uri, index); + if (segment == null) { + throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer"); + } int N = mChildren.size(); for (int i = 0; i < N; i++) { ObserverNode node = mChildren.get(i); diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java index 98a499303e264284cad83a9fc32cc0ec9d8fc1e0..6413cec32459e7b722060cdaf73fb9adb7d4e755 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -317,7 +317,9 @@ public class SyncStorageEngine extends Handler { if (sSyncStorageEngine != null) { return; } - File dataDir = Environment.getDataDirectory(); + // This call will return the correct directory whether Encrypted File Systems is + // enabled or not. + File dataDir = Environment.getSecureDataDirectory(); sSyncStorageEngine = new SyncStorageEngine(context, dataDir); } diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 1577f9e3e28d93ec658041a6875d5500247428a1..70471139853e9b425f89029baf4f08a602336cf8 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -174,7 +174,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * Value for {@link #flags}: true when the application's window can be * increased in size for larger screens. Corresponds to * {@link android.R.styleable#AndroidManifestSupportsScreens_largeScreens - * android:smallScreens}. + * android:largeScreens}. */ public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<11; @@ -252,6 +252,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public static final int FLAG_RESTORE_ANY_VERSION = 1<<17; /** + * Value for {@link #flags}: Set to true if the application has been + * installed using the forward lock option. + * * Value for {@link #flags}: Set to true if the application is * currently installed on external/removable/unprotected storage. Such * applications may not be available if their storage is not currently @@ -261,13 +264,31 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ public static final int FLAG_EXTERNAL_STORAGE = 1<<18; + /** + * Value for {@link #flags}: true when the application's window can be + * increased in size for extra large screens. Corresponds to + * {@link android.R.styleable#AndroidManifestSupportsScreens_xlargeScreens + * android:xlargeScreens}. + */ + public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 1<<19; + + /** + * Value for {@link #flags}: this is true if the application has set + * its android:neverEncrypt to true, false otherwise. It is used to specify + * that this package specifically "opts-out" of a secured file system solution, + * and will always store its data in-the-clear. + * + * {@hide} + */ + public static final int FLAG_NEVER_ENCRYPT = 1<<30; + /** * Value for {@link #flags}: Set to true if the application has been * installed using the forward lock option. * * {@hide} */ - public static final int FLAG_FORWARD_LOCK = 1<<20; + public static final int FLAG_FORWARD_LOCK = 1<<29; /** * Value for {@link #flags}: Set to true if the application is @@ -275,7 +296,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * * {@hide} */ - public static final int FLAG_NATIVE_DEBUGGABLE = 1<<21; + public static final int FLAG_NATIVE_DEBUGGABLE = 1<<28; /** * Flags associated with the application. Any combination of @@ -285,7 +306,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP}, * {@link #FLAG_TEST_ONLY}, {@link #FLAG_SUPPORTS_SMALL_SCREENS}, * {@link #FLAG_SUPPORTS_NORMAL_SCREENS}, - * {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_RESIZEABLE_FOR_SCREENS}, + * {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_SUPPORTS_XLARGE_SCREENS}, + * {@link #FLAG_RESIZEABLE_FOR_SCREENS}, * {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}, {@link #FLAG_VM_SAFE_MODE} */ public int flags = 0; @@ -517,7 +539,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public void disableCompatibilityMode() { flags |= (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS | FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS | - FLAG_SUPPORTS_SCREEN_DENSITIES); + FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS); } /** diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java index cafe3725ec0a28e7af03e792dcd7af0b9e26f22a..f16c4efdfaf44aa5b32f74e53272fb30f4d4f2dc 100644 --- a/core/java/android/content/pm/ComponentInfo.java +++ b/core/java/android/content/pm/ComponentInfo.java @@ -154,6 +154,14 @@ public class ComponentInfo extends PackageItemInfo { return applicationInfo.loadIcon(pm); } + /** + * @hide + */ + @Override + protected Drawable loadDefaultLogo(PackageManager pm) { + return applicationInfo.loadLogo(pm); + } + /** * @hide */ diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java index 14c068006c11f6406b06857da2ba187340981a04..d73aaf6a2e989f64cd53cdfa732ef70e6b8b842a 100644 --- a/core/java/android/content/pm/PackageItemInfo.java +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -66,6 +66,14 @@ public class PackageItemInfo { */ public int icon; + /** + * A drawable resource identifier (in the package's resources) of this + * component's logo. Logos may be larger/wider than icons and are + * displayed by certain UI elements in place of a name or name/icon + * combination. From the "logo" attribute or, if not set, 0. + */ + public int logo; + /** * Additional meta-data associated with this component. This field * will only be filled in if you set the @@ -84,6 +92,7 @@ public class PackageItemInfo { nonLocalizedLabel = orig.nonLocalizedLabel; if (nonLocalizedLabel != null) nonLocalizedLabel = nonLocalizedLabel.toString().trim(); icon = orig.icon; + logo = orig.logo; metaData = orig.metaData; } @@ -151,6 +160,42 @@ public class PackageItemInfo { return pm.getDefaultActivityIcon(); } + /** + * Retrieve the current graphical logo associated with this item. This + * will call back on the given PackageManager to load the logo from + * the application. + * + * @param pm A PackageManager from which the logo can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a Drawable containing the item's logo. If the item + * does not have a logo, this method will return null. + */ + public Drawable loadLogo(PackageManager pm) { + if (logo != 0) { + Drawable d = pm.getDrawable(packageName, logo, getApplicationInfo()); + if (d != null) { + return d; + } + } + return loadDefaultLogo(pm); + } + + /** + * Retrieve the default graphical logo associated with this item. + * + * @param pm A PackageManager from which the logo can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a Drawable containing the item's default logo + * or null if no default logo is available. + * + * @hide + */ + protected Drawable loadDefaultLogo(PackageManager pm) { + return null; + } + /** * Load an XML resource attached to the meta-data of this item. This will * retrieved the name meta-data entry, and if defined call back on the @@ -196,6 +241,7 @@ public class PackageItemInfo { dest.writeInt(labelRes); TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags); dest.writeInt(icon); + dest.writeInt(logo); dest.writeBundle(metaData); } @@ -206,6 +252,7 @@ public class PackageItemInfo { nonLocalizedLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); icon = source.readInt(); + logo = source.readInt(); metaData = source.readBundle(); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 68b44e705fce8a496d31ca02edcc41fb47389db1..196f5085bbe25611d2075afbd8940a2c5975d622 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1596,6 +1596,79 @@ public abstract class PackageManager { public abstract Drawable getApplicationIcon(String packageName) throws NameNotFoundException; + /** + * Retrieve the logo associated with an activity. Given the full name of + * an activity, retrieves the information about it and calls + * {@link ComponentInfo#loadLogo ComponentInfo.loadLogo()} to return its logo. + * If the activity can not be found, NameNotFoundException is thrown. + * + * @param activityName Name of the activity whose logo is to be retrieved. + * + * @return Returns the image of the logo or null if the activity has no + * logo specified. + * + * @throws NameNotFoundException Thrown if the resources for the given + * activity could not be loaded. + * + * @see #getActivityLogo(Intent) + */ + public abstract Drawable getActivityLogo(ComponentName activityName) + throws NameNotFoundException; + + /** + * Retrieve the logo associated with an Intent. If intent.getClassName() is + * set, this simply returns the result of + * getActivityLogo(intent.getClassName()). Otherwise it resolves the intent's + * component and returns the logo associated with the resolved component. + * If intent.getClassName() can not be found or the Intent can not be resolved + * to a component, NameNotFoundException is thrown. + * + * @param intent The intent for which you would like to retrieve a logo. + * + * @return Returns the image of the logo, or null if the activity has no + * logo specified. + * + * @throws NameNotFoundException Thrown if the resources for application + * matching the given intent could not be loaded. + * + * @see #getActivityLogo(ComponentName) + */ + public abstract Drawable getActivityLogo(Intent intent) + throws NameNotFoundException; + + /** + * Retrieve the logo associated with an application. If it has not specified + * a logo, this method returns null. + * + * @param info Information about application being queried. + * + * @return Returns the image of the logo, or null if no logo is specified + * by the application. + * + * @see #getApplicationLogo(String) + */ + public abstract Drawable getApplicationLogo(ApplicationInfo info); + + /** + * Retrieve the logo associated with an application. Given the name of the + * application's package, retrieves the information about it and calls + * getApplicationLogo() to return its logo. If the application can not be + * found, NameNotFoundException is thrown. + * + * @param packageName Name of the package whose application logo is to be + * retrieved. + * + * @return Returns the image of the logo, or null if no application logo + * has been specified. + * + * @throws NameNotFoundException Thrown if the resources for the given + * application could not be loaded. + * + * @see #getApplicationLogo(ApplicationInfo) + */ + public abstract Drawable getApplicationLogo(String packageName) + throws NameNotFoundException; + /** * Retrieve text from a package. This is a low-level API used by * the various package manager info structures (such as diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 2a20a2d0e363d2e6bee2cbe5adffbff547de3fd7..4ddc124430b435edde2563c52699ef749382aa5c 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -105,17 +105,19 @@ public class PackageParser { final int nameRes; final int labelRes; final int iconRes; + final int logoRes; String tag; TypedArray sa; ParsePackageItemArgs(Package _owner, String[] _outError, - int _nameRes, int _labelRes, int _iconRes) { + int _nameRes, int _labelRes, int _iconRes, int _logoRes) { owner = _owner; outError = _outError; nameRes = _nameRes; labelRes = _labelRes; iconRes = _iconRes; + logoRes = _logoRes; } } @@ -127,10 +129,10 @@ public class PackageParser { int flags; ParseComponentArgs(Package _owner, String[] _outError, - int _nameRes, int _labelRes, int _iconRes, + int _nameRes, int _labelRes, int _iconRes, int _logoRes, String[] _sepProcesses, int _processRes, int _descriptionRes, int _enabledRes) { - super(_owner, _outError, _nameRes, _labelRes, _iconRes); + super(_owner, _outError, _nameRes, _labelRes, _iconRes, _logoRes); sepProcesses = _sepProcesses; processRes = _processRes; descriptionRes = _descriptionRes; @@ -789,6 +791,7 @@ public class PackageParser { int supportsSmallScreens = 1; int supportsNormalScreens = 1; int supportsLargeScreens = 1; + int supportsXLargeScreens = 1; int resizeable = 1; int anyDensity = 1; @@ -996,9 +999,12 @@ public class PackageParser { supportsLargeScreens = sa.getInteger( com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens, supportsLargeScreens); + supportsXLargeScreens = sa.getInteger( + com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens, + supportsXLargeScreens); resizeable = sa.getInteger( com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable, - supportsLargeScreens); + resizeable); anyDensity = sa.getInteger( com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity, anyDensity); @@ -1132,6 +1138,11 @@ public class PackageParser { >= android.os.Build.VERSION_CODES.DONUT)) { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS; } + if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0 + && pkg.applicationInfo.targetSdkVersion + >= android.os.Build.VERSION_CODES.GINGERBREAD)) { + pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS; + } if (resizeable < 0 || (resizeable > 0 && pkg.applicationInfo.targetSdkVersion >= android.os.Build.VERSION_CODES.DONUT)) { @@ -1241,7 +1252,8 @@ public class PackageParser { "", sa, com.android.internal.R.styleable.AndroidManifestPermissionGroup_name, com.android.internal.R.styleable.AndroidManifestPermissionGroup_label, - com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon)) { + com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon, + com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo)) { sa.recycle(); mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return null; @@ -1276,7 +1288,8 @@ public class PackageParser { "", sa, com.android.internal.R.styleable.AndroidManifestPermission_name, com.android.internal.R.styleable.AndroidManifestPermission_label, - com.android.internal.R.styleable.AndroidManifestPermission_icon)) { + com.android.internal.R.styleable.AndroidManifestPermission_icon, + com.android.internal.R.styleable.AndroidManifestPermission_logo)) { sa.recycle(); mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return null; @@ -1329,7 +1342,8 @@ public class PackageParser { "", sa, com.android.internal.R.styleable.AndroidManifestPermissionTree_name, com.android.internal.R.styleable.AndroidManifestPermissionTree_label, - com.android.internal.R.styleable.AndroidManifestPermissionTree_icon)) { + com.android.internal.R.styleable.AndroidManifestPermissionTree_icon, + com.android.internal.R.styleable.AndroidManifestPermissionTree_logo)) { sa.recycle(); mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return null; @@ -1373,7 +1387,8 @@ public class PackageParser { mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError, com.android.internal.R.styleable.AndroidManifestInstrumentation_name, com.android.internal.R.styleable.AndroidManifestInstrumentation_label, - com.android.internal.R.styleable.AndroidManifestInstrumentation_icon); + com.android.internal.R.styleable.AndroidManifestInstrumentation_icon, + com.android.internal.R.styleable.AndroidManifestInstrumentation_logo); mParseInstrumentationArgs.tag = ""; } @@ -1485,6 +1500,8 @@ public class PackageParser { ai.icon = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestApplication_icon, 0); + ai.logo = sa.getResourceId( + com.android.internal.R.styleable.AndroidManifestApplication_logo, 0); ai.theme = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestApplication_theme, 0); ai.descriptionRes = sa.getResourceId( @@ -1542,6 +1559,12 @@ public class PackageParser { ai.flags |= ApplicationInfo.FLAG_TEST_ONLY; } + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_neverEncrypt, + false)) { + ai.flags |= ApplicationInfo.FLAG_NEVER_ENCRYPT; + } + String str; str = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifestApplication_permission, 0); @@ -1705,7 +1728,7 @@ public class PackageParser { private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo, String[] outError, String tag, TypedArray sa, - int nameRes, int labelRes, int iconRes) { + int nameRes, int labelRes, int iconRes, int logoRes) { String name = sa.getNonConfigurationString(nameRes, 0); if (name == null) { outError[0] = tag + " does not specify android:name"; @@ -1723,6 +1746,11 @@ public class PackageParser { outInfo.icon = iconVal; outInfo.nonLocalizedLabel = null; } + + int logoVal = sa.getResourceId(logoRes, 0); + if (logoVal != 0) { + outInfo.logo = logoVal; + } TypedValue v = sa.peekValue(labelRes); if (v != null && (outInfo.labelRes=v.resourceId) == 0) { @@ -1745,6 +1773,7 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestActivity_name, com.android.internal.R.styleable.AndroidManifestActivity_label, com.android.internal.R.styleable.AndroidManifestActivity_icon, + com.android.internal.R.styleable.AndroidManifestActivity_logo, mSeparateProcesses, com.android.internal.R.styleable.AndroidManifestActivity_process, com.android.internal.R.styleable.AndroidManifestActivity_description, @@ -1947,6 +1976,7 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestActivityAlias_name, com.android.internal.R.styleable.AndroidManifestActivityAlias_label, com.android.internal.R.styleable.AndroidManifestActivityAlias_icon, + com.android.internal.R.styleable.AndroidManifestActivityAlias_logo, mSeparateProcesses, 0, com.android.internal.R.styleable.AndroidManifestActivityAlias_description, @@ -1980,6 +2010,7 @@ public class PackageParser { info.configChanges = target.info.configChanges; info.flags = target.info.flags; info.icon = target.info.icon; + info.logo = target.info.logo; info.labelRes = target.info.labelRes; info.nonLocalizedLabel = target.info.nonLocalizedLabel; info.launchMode = target.info.launchMode; @@ -2074,6 +2105,7 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestProvider_name, com.android.internal.R.styleable.AndroidManifestProvider_label, com.android.internal.R.styleable.AndroidManifestProvider_icon, + com.android.internal.R.styleable.AndroidManifestProvider_logo, mSeparateProcesses, com.android.internal.R.styleable.AndroidManifestProvider_process, com.android.internal.R.styleable.AndroidManifestProvider_description, @@ -2337,6 +2369,7 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestService_name, com.android.internal.R.styleable.AndroidManifestService_label, com.android.internal.R.styleable.AndroidManifestService_icon, + com.android.internal.R.styleable.AndroidManifestService_logo, mSeparateProcesses, com.android.internal.R.styleable.AndroidManifestService_process, com.android.internal.R.styleable.AndroidManifestService_description, @@ -2540,6 +2573,9 @@ public class PackageParser { outInfo.icon = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0); + + outInfo.logo = sa.getResourceId( + com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0); sa.recycle(); @@ -2801,6 +2837,11 @@ public class PackageParser { outInfo.icon = iconVal; outInfo.nonLocalizedLabel = null; } + + int logoVal = args.sa.getResourceId(args.logoRes, 0); + if (logoVal != 0) { + outInfo.logo = logoVal; + } TypedValue v = args.sa.peekValue(args.labelRes); if (v != null && (outInfo.labelRes=v.resourceId) == 0) { @@ -3135,6 +3176,7 @@ public class PackageParser { public int labelRes; public CharSequence nonLocalizedLabel; public int icon; + public int logo; } public final static class ActivityIntentInfo extends IntentInfo { diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index 11c67cc18110727e2989b293a784e9518ebcecdb..d0ba590159f43948c7b489eddbc30f614681e93a 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -99,7 +99,22 @@ public class CompatibilityInfo { */ private static final int CONFIGURED_LARGE_SCREENS = 16; - private static final int SCALING_EXPANDABLE_MASK = SCALING_REQUIRED | EXPANDABLE | LARGE_SCREENS; + /** + * A flag mask to indicates that the application supports xlarge screens. + * The flag is set to true if + * 1) Application declares it supports xlarge screens in manifest file using or + * 2) The screen size is not xlarge + * {@see compatibilityFlag} + */ + private static final int XLARGE_SCREENS = 32; + + /** + * A flag mask to tell if the application supports xlarge screens. This differs + * from XLARGE_SCREENS in that the application that does not support xlarge + * screens will be marked as supporting them if the current screen is not + * xlarge. + */ + private static final int CONFIGURED_XLARGE_SCREENS = 64; /** * The effective screen density we have selected for this application. @@ -127,6 +142,9 @@ public class CompatibilityInfo { if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { mCompatibilityFlags |= LARGE_SCREENS | CONFIGURED_LARGE_SCREENS; } + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { + mCompatibilityFlags |= XLARGE_SCREENS | CONFIGURED_XLARGE_SCREENS; + } if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { mCompatibilityFlags |= EXPANDABLE | CONFIGURED_EXPANDABLE; } @@ -157,6 +175,7 @@ public class CompatibilityInfo { this(ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS + | ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS, EXPANDABLE | CONFIGURED_EXPANDABLE, DisplayMetrics.DENSITY_DEVICE, @@ -195,6 +214,17 @@ public class CompatibilityInfo { } } + /** + * Sets large screen bit in the compatibility flag. + */ + public void setXLargeScreens(boolean expandable) { + if (expandable) { + mCompatibilityFlags |= CompatibilityInfo.XLARGE_SCREENS; + } else { + mCompatibilityFlags &= ~CompatibilityInfo.XLARGE_SCREENS; + } + } + /** * @return true if the application is configured to be expandable. */ @@ -209,6 +239,13 @@ public class CompatibilityInfo { return (mCompatibilityFlags & CompatibilityInfo.CONFIGURED_LARGE_SCREENS) != 0; } + /** + * @return true if the application is configured to be expandable. + */ + public boolean isConfiguredXLargeScreens() { + return (mCompatibilityFlags & CompatibilityInfo.CONFIGURED_XLARGE_SCREENS) != 0; + } + /** * @return true if the scaling is required */ diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 1a0c867edf194dd970993c35fbaae99eefd5a0db..02956ba15dd651ee2f7abf4ad7ca65bac794adff 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -62,6 +62,7 @@ public final class Configuration implements Parcelable, ComparableThe {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size * of the screen. They may be one of * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL}, - * or {@link #SCREENLAYOUT_SIZE_LARGE}. + * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}. * *

The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen * is wider/taller than normal. They may be one of diff --git a/core/java/android/database/Cursor.java b/core/java/android/database/Cursor.java index 79178f421453758217ad9f9befefbd98501439f3..6539156ee41d1e69bcdc588cc5ee3362bbe3cc2e 100644 --- a/core/java/android/database/Cursor.java +++ b/core/java/android/database/Cursor.java @@ -25,6 +25,9 @@ import java.util.Map; /** * This interface provides random read-write access to the result set returned * by a database query. + * + * Cursor implementations are not required to be synchronized so code using a Cursor from multiple + * threads should perform its own synchronization when using the Cursor. */ public interface Cursor { /** diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java index 6e5b3e1685162fd3ad60cf4908e6aad80f190d73..c7e58faf26b24c62a379eee8c0bc2ed9db65e281 100644 --- a/core/java/android/database/sqlite/SQLiteCursor.java +++ b/core/java/android/database/sqlite/SQLiteCursor.java @@ -36,6 +36,9 @@ import java.util.concurrent.locks.ReentrantLock; /** * A Cursor implementation that exposes results from a query on a * {@link SQLiteDatabase}. + * + * SQLiteCursor is not internally synchronized so code using a SQLiteCursor from multiple + * threads should perform its own synchronization when using the SQLiteCursor. */ public class SQLiteCursor extends AbstractWindowedCursor { static final String TAG = "Cursor"; diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index fb5507dc8f8388f33bc6c6aa27eaf5589716e3fe..d4f9b2008b83f0131a57800eddf636391c88d492 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -1134,7 +1134,8 @@ public class SQLiteDatabase extends SQLiteClosable { * * @param sql The raw SQL statement, may contain ? for unknown values to be * bound later. - * @return a pre-compiled statement object. + * @return A pre-compiled {@link SQLiteStatement} object. Note that + * {@link SQLiteStatement}s are not synchronized, see the documentation for more details. */ public SQLiteStatement compileStatement(String sql) throws SQLException { lock(); @@ -1175,7 +1176,8 @@ public class SQLiteDatabase extends SQLiteClosable { * default sort order, which may be unordered. * @param limit Limits the number of rows returned by the query, * formatted as LIMIT clause. Passing null denotes no LIMIT clause. - * @return A Cursor object, which is positioned before the first entry + * @return A {@link Cursor} object, which is positioned before the first entry. Note that + * {@link Cursor}s are not synchronized, see the documentation for more details. * @see Cursor */ public Cursor query(boolean distinct, String table, String[] columns, @@ -1213,7 +1215,8 @@ public class SQLiteDatabase extends SQLiteClosable { * default sort order, which may be unordered. * @param limit Limits the number of rows returned by the query, * formatted as LIMIT clause. Passing null denotes no LIMIT clause. - * @return A Cursor object, which is positioned before the first entry + * @return A {@link Cursor} object, which is positioned before the first entry. Note that + * {@link Cursor}s are not synchronized, see the documentation for more details. * @see Cursor */ public Cursor queryWithFactory(CursorFactory cursorFactory, @@ -1254,7 +1257,8 @@ public class SQLiteDatabase extends SQLiteClosable { * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause * (excluding the ORDER BY itself). Passing null will use the * default sort order, which may be unordered. - * @return A {@link Cursor} object, which is positioned before the first entry + * @return A {@link Cursor} object, which is positioned before the first entry. Note that + * {@link Cursor}s are not synchronized, see the documentation for more details. * @see Cursor */ public Cursor query(String table, String[] columns, String selection, @@ -1291,7 +1295,8 @@ public class SQLiteDatabase extends SQLiteClosable { * default sort order, which may be unordered. * @param limit Limits the number of rows returned by the query, * formatted as LIMIT clause. Passing null denotes no LIMIT clause. - * @return A {@link Cursor} object, which is positioned before the first entry + * @return A {@link Cursor} object, which is positioned before the first entry. Note that + * {@link Cursor}s are not synchronized, see the documentation for more details. * @see Cursor */ public Cursor query(String table, String[] columns, String selection, @@ -1309,7 +1314,8 @@ public class SQLiteDatabase extends SQLiteClosable { * @param selectionArgs You may include ?s in where clause in the query, * which will be replaced by the values from selectionArgs. The * values will be bound as Strings. - * @return A {@link Cursor} object, which is positioned before the first entry + * @return A {@link Cursor} object, which is positioned before the first entry. Note that + * {@link Cursor}s are not synchronized, see the documentation for more details. */ public Cursor rawQuery(String sql, String[] selectionArgs) { return rawQueryWithFactory(null, sql, selectionArgs, null); @@ -1324,7 +1330,8 @@ public class SQLiteDatabase extends SQLiteClosable { * which will be replaced by the values from selectionArgs. The * values will be bound as Strings. * @param editTable the name of the first table, which is editable - * @return A {@link Cursor} object, which is positioned before the first entry + * @return A {@link Cursor} object, which is positioned before the first entry. Note that + * {@link Cursor}s are not synchronized, see the documentation for more details. */ public Cursor rawQueryWithFactory( CursorFactory cursorFactory, String sql, String[] selectionArgs, @@ -1379,7 +1386,8 @@ public class SQLiteDatabase extends SQLiteClosable { * values will be bound as Strings. * @param initialRead set the initial count of items to read from the cursor * @param maxRead set the count of items to read on each iteration after the first - * @return A {@link Cursor} object, which is positioned before the first entry + * @return A {@link Cursor} object, which is positioned before the first entry. Note that + * {@link Cursor}s are not synchronized, see the documentation for more details. * * This work is incomplete and not fully tested or reviewed, so currently * hidden. diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java index 89a5f0d1e983715ded4cf6b3e615ca5e20e06979..4d96f12c794691cbaf02c845f4344858a274a069 100644 --- a/core/java/android/database/sqlite/SQLiteProgram.java +++ b/core/java/android/database/sqlite/SQLiteProgram.java @@ -20,6 +20,9 @@ import android.util.Log; /** * A base class for compiled SQLite programs. + * + * SQLiteProgram is not internally synchronized so code using a SQLiteProgram from multiple + * threads should perform its own synchronization when using the SQLiteProgram. */ public abstract class SQLiteProgram extends SQLiteClosable { diff --git a/core/java/android/database/sqlite/SQLiteQuery.java b/core/java/android/database/sqlite/SQLiteQuery.java index 43d2fac8b7e69e7b6f5e88d976ecc2be3c51db7a..905b66b78cd6e573651a626b81b46c2a46c52b49 100644 --- a/core/java/android/database/sqlite/SQLiteQuery.java +++ b/core/java/android/database/sqlite/SQLiteQuery.java @@ -23,6 +23,9 @@ import android.util.Log; /** * A SQLite program that represents a query that reads the resulting rows into a CursorWindow. * This class is used by SQLiteCursor and isn't useful itself. + * + * SQLiteQuery is not internally synchronized so code using a SQLiteQuery from multiple + * threads should perform its own synchronization when using the SQLiteQuery. */ public class SQLiteQuery extends SQLiteProgram { private static final String TAG = "Cursor"; diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java index 98da41449476604863f28c06484a7f40883faa7d..47cca873e91f7e466aa334773d7e31472ee19b15 100644 --- a/core/java/android/database/sqlite/SQLiteStatement.java +++ b/core/java/android/database/sqlite/SQLiteStatement.java @@ -23,6 +23,9 @@ import android.os.SystemClock; * The statement cannot return multiple rows, but 1x1 result sets are allowed. * Don't use SQLiteStatement constructor directly, please use * {@link SQLiteDatabase#compileStatement(String)} + * + * SQLiteStatement is not internally synchronized so code using a SQLiteStatement from multiple + * threads should perform its own synchronization when using the SQLiteStatement. */ public class SQLiteStatement extends SQLiteProgram { diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 8687a8964491e0ed9f3df3eddbcc9bdd3e8cd5df..54aa363551c65404a1e7ad456ce9bad812b46da5 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -58,7 +58,7 @@ import android.os.Message; public class Camera { private static final String TAG = "Camera"; - // These match the enums in frameworks/base/include/ui/Camera.h + // These match the enums in frameworks/base/include/camera/Camera.h private static final int CAMERA_MSG_ERROR = 0x001; private static final int CAMERA_MSG_SHUTTER = 0x002; private static final int CAMERA_MSG_FOCUS = 0x004; @@ -83,14 +83,30 @@ public class Camera { private boolean mOneShot; private boolean mWithBuffer; + /** + * Returns the number of Cameras available. + * @hide + */ + public native static int getNumberOfCameras(); + /** * Returns a new Camera object. + * If {@link #getNumberOfCameras()} returns N, the valid is is 0 to N-1. + * The id 0 is the default camera. + * @hide + */ + public static Camera open(int cameraId) { + return new Camera(cameraId); + } + + /** + * Returns a new Camera object. This returns the default camera. */ public static Camera open() { - return new Camera(); + return new Camera(0); } - Camera() { + Camera(int cameraId) { mShutterCallback = null; mRawImageCallback = null; mJpegCallback = null; @@ -107,14 +123,14 @@ public class Camera { mEventHandler = null; } - native_setup(new WeakReference(this)); + native_setup(new WeakReference(this), cameraId); } protected void finalize() { native_release(); } - private native final void native_setup(Object camera_this); + private native final void native_setup(Object camera_this, int cameraId); private native final void native_release(); @@ -746,6 +762,8 @@ public class Camera { private static final String KEY_ZOOM_RATIOS = "zoom-ratios"; private static final String KEY_ZOOM_SUPPORTED = "zoom-supported"; private static final String KEY_SMOOTH_ZOOM_SUPPORTED = "smooth-zoom-supported"; + private static final String KEY_FOCUS_DISTANCES = "focus-distances"; + // Parameter key suffix for supported values. private static final String SUPPORTED_VALUES_SUFFIX = "-values"; @@ -807,21 +825,81 @@ public class Camera { */ public static final String FLASH_MODE_TORCH = "torch"; - // Values for scene mode settings. + /** + * Scene mode is off. + */ public static final String SCENE_MODE_AUTO = "auto"; + + /** + * Take photos of fast moving objects. Same as {@link + * #SCENE_MODE_SPORTS}. + */ public static final String SCENE_MODE_ACTION = "action"; + + /** + * Take people pictures. + */ public static final String SCENE_MODE_PORTRAIT = "portrait"; + + /** + * Take pictures on distant objects. + */ public static final String SCENE_MODE_LANDSCAPE = "landscape"; + + /** + * Take photos at night. + */ public static final String SCENE_MODE_NIGHT = "night"; + + /** + * Take people pictures at night. + */ public static final String SCENE_MODE_NIGHT_PORTRAIT = "night-portrait"; + + /** + * Take photos in a theater. Flash light is off. + */ public static final String SCENE_MODE_THEATRE = "theatre"; + + /** + * Take pictures on the beach. + */ public static final String SCENE_MODE_BEACH = "beach"; + + /** + * Take pictures on the snow. + */ public static final String SCENE_MODE_SNOW = "snow"; + + /** + * Take sunset photos. + */ public static final String SCENE_MODE_SUNSET = "sunset"; + + /** + * Avoid blurry pictures (for example, due to hand shake). + */ public static final String SCENE_MODE_STEADYPHOTO = "steadyphoto"; + + /** + * For shooting firework displays. + */ public static final String SCENE_MODE_FIREWORKS = "fireworks"; + + /** + * Take photos of fast moving objects. Same as {@link + * #SCENE_MODE_ACTION}. + */ public static final String SCENE_MODE_SPORTS = "sports"; + + /** + * Take indoor low-light shot. + */ public static final String SCENE_MODE_PARTY = "party"; + + /** + * Capture the naturally warm color of scenes lit by candles. + */ public static final String SCENE_MODE_CANDLELIGHT = "candlelight"; /** @@ -858,6 +936,36 @@ public class Camera { */ public static final String FOCUS_MODE_EDOF = "edof"; + // Indices for focus distance array. + /** + * The array index of near focus distance for use with + * {@link #getFocusDistances(float[])}. + */ + public static final int FOCUS_DISTANCE_NEAR_INDEX = 0; + + /** + * The array index of optimal focus distance for use with + * {@link #getFocusDistances(float[])}. + */ + public static final int FOCUS_DISTANCE_OPTIMAL_INDEX = 1; + + /** + * The array index of far focus distance for use with + * {@link #getFocusDistances(float[])}. + */ + public static final int FOCUS_DISTANCE_FAR_INDEX = 2; + + /** + * Continuous focus mode. The camera continuously tries to focus. This + * is ideal for shooting video or shooting photo of moving object. + * Continuous focus starts when {@link #autoFocus(AutoFocusCallback)} is + * called. Continuous focus stops when {@link #cancelAutoFocus()} is + * called. AutoFocusCallback will be only called once as soon as the + * picture is in focus. + */ + public static final String FOCUS_MODE_CONTINUOUS = "continuous"; + + // Formats for setPreviewFormat and setPictureFormat. private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp"; private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp"; @@ -1788,6 +1896,40 @@ public class Camera { return TRUE.equals(str); } + /** + * Gets the distances from the camera to where an object appears to be + * in focus. The object is sharpest at the optimal focus distance. The + * depth of field is the far focus distance minus near focus distance. + * + * Focus distances may change after calling {@link + * #autoFocus(AutoFocusCallback)}, {@link #cancelAutoFocus}, or {@link + * #startPreview()}. Applications can call {@link #getParameters()} + * and this method anytime to get the latest focus distances. If the + * focus mode is FOCUS_MODE_CONTINUOUS and autofocus has started, focus + * distances may change from time to time. + * + * Far focus distance >= optimal focus distance >= near focus distance. + * If the focus distance is infinity, the value will be + * Float.POSITIVE_INFINITY. + * + * @param output focus distances in meters. output must be a float + * array with three elements. Near focus distance, optimal focus + * distance, and far focus distance will be filled in the array. + * @see #FOCUS_DISTANCE_NEAR_INDEX + * @see #FOCUS_DISTANCE_OPTIMAL_INDEX + * @see #FOCUS_DISTANCE_FAR_INDEX + */ + public void getFocusDistances(float[] output) { + if (output == null || output.length != 3) { + throw new IllegalArgumentException( + "output must be an float array with three elements."); + } + List distances = splitFloat(get(KEY_FOCUS_DISTANCES)); + output[0] = distances.get(0); + output[1] = distances.get(1); + output[2] = distances.get(2); + } + // Splits a comma delimited string to an ArrayList of String. // Return null if the passing string is null or the size is 0. private ArrayList split(String str) { @@ -1817,6 +1959,21 @@ public class Camera { return substrings; } + // Splits a comma delimited string to an ArrayList of Float. + // Return null if the passing string is null or the size is 0. + private ArrayList splitFloat(String str) { + if (str == null) return null; + + StringTokenizer tokenizer = new StringTokenizer(str, ","); + ArrayList substrings = new ArrayList(); + while (tokenizer.hasMoreElements()) { + String token = tokenizer.nextToken(); + substrings.add(Float.parseFloat(token)); + } + if (substrings.size() == 0) return null; + return substrings; + } + // Returns the value of a float parameter. private float getFloat(String key, float defaultValue) { try { diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java index 80e9865e5a81fdf60fb329cd5ad6d5e544ac987c..44f30f7c5dac70df791a493b69d0247e535707a9 100644 --- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java @@ -47,9 +47,10 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub private static final int DO_UPDATE_CURSOR = 95; private static final int DO_APP_PRIVATE_COMMAND = 100; private static final int DO_TOGGLE_SOFT_INPUT = 105; - - final HandlerCaller mCaller; - final InputMethodSession mInputMethodSession; + private static final int DO_FINISH_SESSION = 110; + + HandlerCaller mCaller; + InputMethodSession mInputMethodSession; // NOTE: we should have a cache of these. static class InputMethodEventCallbackWrapper implements InputMethodSession.EventCallback { @@ -127,6 +128,10 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub mInputMethodSession.toggleSoftInput(msg.arg1, msg.arg2); return; } + case DO_FINISH_SESSION: { + mInputMethodSession = null; + return; + } } Log.w(TAG, "Unhandled message code: " + msg.what); } @@ -174,4 +179,8 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub public void toggleSoftInput(int showFlags, int hideFlags) { mCaller.executeOrSendMessage(mCaller.obtainMessageII(DO_TOGGLE_SOFT_INPUT, showFlags, hideFlags)); } + + public void finishSession() { + mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_SESSION)); + } } diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java index bfa82ee0d13c0f232985bcf332e8eb2948d5fb69..35fd46f5a2f2ec40b7a6d1062ad2857d4e95fe66 100644 --- a/core/java/android/inputmethodservice/IInputMethodWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java @@ -39,6 +39,7 @@ import android.view.inputmethod.InputMethodSession; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.ref.WeakReference; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -64,9 +65,9 @@ class IInputMethodWrapper extends IInputMethod.Stub private static final int DO_SHOW_SOFT_INPUT = 60; private static final int DO_HIDE_SOFT_INPUT = 70; - final AbstractInputMethodService mTarget; + final WeakReference mTarget; final HandlerCaller mCaller; - final InputMethod mInputMethod; + final WeakReference mInputMethod; static class Notifier { boolean notified; @@ -96,21 +97,32 @@ class IInputMethodWrapper extends IInputMethod.Stub public IInputMethodWrapper(AbstractInputMethodService context, InputMethod inputMethod) { - mTarget = context; - mCaller = new HandlerCaller(context, this); - mInputMethod = inputMethod; + mTarget = new WeakReference(context); + mCaller = new HandlerCaller(context.getApplicationContext(), this); + mInputMethod = new WeakReference(inputMethod); } public InputMethod getInternalInputMethod() { - return mInputMethod; + return mInputMethod.get(); } public void executeMessage(Message msg) { + InputMethod inputMethod = mInputMethod.get(); + // Need a valid reference to the inputMethod for everything except a dump. + if (inputMethod == null && msg.what != DO_DUMP) { + Log.w(TAG, "Input method reference was null, ignoring message: " + msg.what); + return; + } + switch (msg.what) { case DO_DUMP: { + AbstractInputMethodService target = mTarget.get(); + if (target == null) { + return; + } HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj; try { - mTarget.dump((FileDescriptor)args.arg1, + target.dump((FileDescriptor)args.arg1, (PrintWriter)args.arg2, (String[])args.arg3); } catch (RuntimeException e) { ((PrintWriter)args.arg2).println("Exception: " + e); @@ -122,22 +134,22 @@ class IInputMethodWrapper extends IInputMethod.Stub } case DO_ATTACH_TOKEN: { - mInputMethod.attachToken((IBinder)msg.obj); + inputMethod.attachToken((IBinder)msg.obj); return; } case DO_SET_INPUT_CONTEXT: { - mInputMethod.bindInput((InputBinding)msg.obj); + inputMethod.bindInput((InputBinding)msg.obj); return; } case DO_UNSET_INPUT_CONTEXT: - mInputMethod.unbindInput(); + inputMethod.unbindInput(); return; case DO_START_INPUT: { HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj; IInputContext inputContext = (IInputContext)args.arg1; InputConnection ic = inputContext != null ? new InputConnectionWrapper(inputContext) : null; - mInputMethod.startInput(ic, (EditorInfo)args.arg2); + inputMethod.startInput(ic, (EditorInfo)args.arg2); return; } case DO_RESTART_INPUT: { @@ -145,33 +157,37 @@ class IInputMethodWrapper extends IInputMethod.Stub IInputContext inputContext = (IInputContext)args.arg1; InputConnection ic = inputContext != null ? new InputConnectionWrapper(inputContext) : null; - mInputMethod.restartInput(ic, (EditorInfo)args.arg2); + inputMethod.restartInput(ic, (EditorInfo)args.arg2); return; } case DO_CREATE_SESSION: { - mInputMethod.createSession(new InputMethodSessionCallbackWrapper( + inputMethod.createSession(new InputMethodSessionCallbackWrapper( mCaller.mContext, (IInputMethodCallback)msg.obj)); return; } case DO_SET_SESSION_ENABLED: - mInputMethod.setSessionEnabled((InputMethodSession)msg.obj, + inputMethod.setSessionEnabled((InputMethodSession)msg.obj, msg.arg1 != 0); return; case DO_REVOKE_SESSION: - mInputMethod.revokeSession((InputMethodSession)msg.obj); + inputMethod.revokeSession((InputMethodSession)msg.obj); return; case DO_SHOW_SOFT_INPUT: - mInputMethod.showSoftInput(msg.arg1, (ResultReceiver)msg.obj); + inputMethod.showSoftInput(msg.arg1, (ResultReceiver)msg.obj); return; case DO_HIDE_SOFT_INPUT: - mInputMethod.hideSoftInput(msg.arg1, (ResultReceiver)msg.obj); + inputMethod.hideSoftInput(msg.arg1, (ResultReceiver)msg.obj); return; } Log.w(TAG, "Unhandled message code: " + msg.what); } @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { - if (mTarget.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + AbstractInputMethodService target = mTarget.get(); + if (target == null) { + return; + } + if (target.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { fout.println("Permission Denial: can't dump InputMethodManager from from pid=" diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 8c8d3e59b8b47839b4f41ba02c1b6561d18dfa88..1a261d3fa6ba347511e740b02ab4596b8a8dcdb7 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1988,15 +1988,19 @@ public class InputMethodService extends AbstractInputMethodService { ei.inputType != InputType.TYPE_NULL); if (hasAction) { mExtractAccessories.setVisibility(View.VISIBLE); - if (ei.actionLabel != null) { - mExtractAction.setText(ei.actionLabel); - } else { - mExtractAction.setText(getTextForImeAction(ei.imeOptions)); + if (mExtractAction != null) { + if (ei.actionLabel != null) { + mExtractAction.setText(ei.actionLabel); + } else { + mExtractAction.setText(getTextForImeAction(ei.imeOptions)); + } + mExtractAction.setOnClickListener(mActionClickListener); } - mExtractAction.setOnClickListener(mActionClickListener); } else { mExtractAccessories.setVisibility(View.GONE); - mExtractAction.setOnClickListener(null); + if (mExtractAction != null) { + mExtractAction.setOnClickListener(null); + } } } diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java index 98f32b36e99e53957ecee63b4ab136c2d95c0da6..214510d885d546ff26bd2561ac49f2783450fc74 100644 --- a/core/java/android/net/MobileDataStateTracker.java +++ b/core/java/android/net/MobileDataStateTracker.java @@ -310,6 +310,9 @@ public class MobileDataStateTracker extends NetworkStateTracker { case TelephonyManager.NETWORK_TYPE_EVDO_A: networkTypeStr = "evdo"; break; + case TelephonyManager.NETWORK_TYPE_EVDO_B: + networkTypeStr = "evdo"; + break; } return "net.tcp.buffersize." + networkTypeStr; } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 3e9fd420a3fea0e11db8023df3938ccb81b067e6..9d1a6347cd4f62a7663d7971c35d3af9110ff67a 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -180,6 +180,10 @@ public class Build { public static final int ECLAIR_MR1 = 7; public static final int FROYO = 8; + + public static final int KRAKEN = CUR_DEVELOPMENT; + + public static final int GINGERBREAD = CUR_DEVELOPMENT; } /** The type of build, like "user" or "eng". */ diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 812391c48e5fa22da51eacd6df9547a2a96bb21b..c7cbed6e4ced990e59dbf8f8c735f13d6cfcaaad 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -28,6 +28,8 @@ public class Environment { private static final File ROOT_DIRECTORY = getDirectory("ANDROID_ROOT", "/system"); + private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; + private static IMountService mMntSvc = null; /** @@ -37,9 +39,55 @@ public class Environment { return ROOT_DIRECTORY; } + /** + * Gets the system directory available for secure storage. + * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system). + * Otherwise, it returns the unencrypted /data/system directory. + * @return File object representing the secure storage system directory. + * @hide + */ + public static File getSystemSecureDirectory() { + if (isEncryptedFilesystemEnabled()) { + return new File(SECURE_DATA_DIRECTORY, "system"); + } else { + return new File(DATA_DIRECTORY, "system"); + } + } + + /** + * Gets the data directory for secure storage. + * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure). + * Otherwise, it returns the unencrypted /data directory. + * @return File object representing the data directory for secure storage. + * @hide + */ + public static File getSecureDataDirectory() { + if (isEncryptedFilesystemEnabled()) { + return SECURE_DATA_DIRECTORY; + } else { + return DATA_DIRECTORY; + } + } + + /** + * Returns whether the Encrypted File System feature is enabled on the device or not. + * @return true if Encrypted File System feature is enabled, false + * if disabled. + * @hide + */ + public static boolean isEncryptedFilesystemEnabled() { + return SystemProperties.getBoolean(SYSTEM_PROPERTY_EFS_ENABLED, false); + } + private static final File DATA_DIRECTORY = getDirectory("ANDROID_DATA", "/data"); + /** + * @hide + */ + private static final File SECURE_DATA_DIRECTORY + = getDirectory("ANDROID_SECURE_DATA", "/data/secure"); + private static final File EXTERNAL_STORAGE_DIRECTORY = getDirectory("EXTERNAL_STORAGE", "/sdcard"); diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java index bc653d64864d6e76733cb93bd891a203a599cb3f..d394a4628f04713b5f7bef58c3105684af9173b9 100644 --- a/core/java/android/os/MessageQueue.java +++ b/core/java/android/os/MessageQueue.java @@ -36,8 +36,9 @@ public class MessageQueue { Message mMessages; private final ArrayList mIdleHandlers = new ArrayList(); private boolean mQuiting = false; + private int mObject = 0; // used by native code boolean mQuitAllowed = true; - + /** * Callback interface for discovering when a thread is going to block * waiting for more messages. @@ -85,16 +86,49 @@ public class MessageQueue { } } + // Add an input pipe to the set being selected over. If token is + // negative, remove 'handler's entry from the current set and forget + // about it. + void setInputToken(int token, int region, Handler handler) { + if (token >= 0) nativeRegisterInputStream(token, region, handler); + else nativeUnregisterInputStream(token); + } + MessageQueue() { + nativeInit(); } + private native void nativeInit(); + + /** + * @param token fd of the readable end of the input stream + * @param region fd of the ashmem region used for data transport alongside the 'token' fd + * @param handler Handler from which to make input messages based on data read from the fd + */ + private native void nativeRegisterInputStream(int token, int region, Handler handler); + private native void nativeUnregisterInputStream(int token); + private native void nativeSignal(); + + /** + * Wait until the designated time for new messages to arrive. + * + * @param when Timestamp in SystemClock.uptimeMillis() base of the next message in the queue. + * If 'when' is zero, the method will check for incoming messages without blocking. If + * 'when' is negative, the method will block forever waiting for the next message. + * @return + */ + private native int nativeWaitForNext(long when); final Message next() { boolean tryIdle = true; + // when we start out, we'll just touch the input pipes and then go from there + long timeToNextEventMillis = 0; while (true) { long now; Object[] idlers = null; - + + nativeWaitForNext(timeToNextEventMillis); + // Try to retrieve the next message, returning if found. synchronized (this) { now = SystemClock.uptimeMillis(); @@ -135,20 +169,17 @@ public class MessageQueue { synchronized (this) { // No messages, nobody to tell about it... time to wait! - try { - if (mMessages != null) { - if (mMessages.when-now > 0) { - Binder.flushPendingCommands(); - this.wait(mMessages.when-now); - } - } else { + if (mMessages != null) { + if (mMessages.when - now > 0) { Binder.flushPendingCommands(); - this.wait(); + timeToNextEventMillis = mMessages.when - now; } - } - catch (InterruptedException e) { + } else { + Binder.flushPendingCommands(); + timeToNextEventMillis = -1; } } + // loop to the while(true) and do the appropriate nativeWait(when) } } @@ -190,7 +221,6 @@ public class MessageQueue { if (p == null || when == 0 || when < p.when) { msg.next = p; mMessages = msg; - this.notify(); } else { Message prev = null; while (p != null && p.when <= when) { @@ -199,8 +229,8 @@ public class MessageQueue { } msg.next = prev.next; prev.next = msg; - this.notify(); } + nativeSignal(); } return true; } @@ -321,7 +351,7 @@ public class MessageQueue { void poke() { synchronized (this) { - this.notify(); + nativeSignal(); } } } diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java index 0a3b2cf77f83b18bf643bb7c5894d854315970ba..d26f0664e372268121bee825cc2fbfe01697f950 100644 --- a/core/java/android/os/ParcelFileDescriptor.java +++ b/core/java/android/os/ParcelFileDescriptor.java @@ -179,7 +179,7 @@ public class ParcelFileDescriptor implements Parcelable { /** * An InputStream you can create on a ParcelFileDescriptor, which will * take care of calling {@link ParcelFileDescriptor#close - * ParcelFileDescritor.close()} for you when the stream is closed. + * ParcelFileDescriptor.close()} for you when the stream is closed. */ public static class AutoCloseInputStream extends FileInputStream { private final ParcelFileDescriptor mFd; @@ -198,7 +198,7 @@ public class ParcelFileDescriptor implements Parcelable { /** * An OutputStream you can create on a ParcelFileDescriptor, which will * take care of calling {@link ParcelFileDescriptor#close - * ParcelFileDescritor.close()} for you when the stream is closed. + * ParcelFileDescriptor.close()} for you when the stream is closed. */ public static class AutoCloseOutputStream extends FileOutputStream { private final ParcelFileDescriptor mFd; diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index b6dc1b52dffae5ee48de552ec2356f2b53320c00..5fea6fec453fb0d16244b3de464e10428f048766 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -347,6 +347,23 @@ public class RecoverySystem { bootCommand(context, "--wipe_data"); } + /** + * Reboot into the recovery system to wipe the /data partition and toggle + * Encrypted File Systems on/off. + * @param extras to add to the RECOVERY_COMPLETED intent after rebooting. + * @throws IOException if something goes wrong. + * + * @hide + */ + public static void rebootToggleEFS(Context context, boolean efsEnabled) + throws IOException { + if (efsEnabled) { + bootCommand(context, "--set_encrypted_filesystem=on"); + } else { + bootCommand(context, "--set_encrypted_filesystem=off"); + } + } + /** * Reboot into the recovery system with the supplied argument. * @param arg to pass to the recovery utility. diff --git a/core/java/android/pim/vcard/VCardBuilder.java b/core/java/android/pim/vcard/VCardBuilder.java index 0a6415dd200cd6494a63ac1c1e8cc6f21d72ec2c..1da6d7a252fda7ce8c5aafdc240a3b70e6438d61 100644 --- a/core/java/android/pim/vcard/VCardBuilder.java +++ b/core/java/android/pim/vcard/VCardBuilder.java @@ -642,22 +642,18 @@ public class VCardBuilder { if (TextUtils.isEmpty(phoneNumber)) { continue; } - int type = (typeAsObject != null ? typeAsObject : DEFAULT_PHONE_TYPE); - if (type == Phone.TYPE_PAGER) { + + // PAGER number needs unformatted "phone number". + final int type = (typeAsObject != null ? typeAsObject : DEFAULT_PHONE_TYPE); + if (type == Phone.TYPE_PAGER || + VCardConfig.refrainPhoneNumberFormatting(mVCardType)) { phoneLineExists = true; if (!phoneSet.contains(phoneNumber)) { phoneSet.add(phoneNumber); appendTelLine(type, label, phoneNumber, isPrimary); } } else { - // The entry "may" have several phone numbers when the contact entry is - // corrupted because of its original source. - // - // e.g. I encountered the entry like the following. - // "111-222-3333 (Miami)\n444-555-6666 (Broward; 305-653-6796 (Miami); ..." - // This kind of entry is not able to be inserted via Android devices, but - // possible if the source of the data is already corrupted. - List phoneNumberList = splitIfSeveralPhoneNumbersExist(phoneNumber); + final List phoneNumberList = splitAndTrimPhoneNumbers(phoneNumber); if (phoneNumberList.isEmpty()) { continue; } @@ -670,7 +666,7 @@ public class VCardBuilder { phoneSet.add(actualPhoneNumber); appendTelLine(type, label, formattedPhoneNumber, isPrimary); } - } + } // for (String actualPhoneNumber : phoneNumberList) { } } } @@ -682,15 +678,38 @@ public class VCardBuilder { return this; } - private List splitIfSeveralPhoneNumbersExist(final String phoneNumber) { - List phoneList = new ArrayList(); + /** + *

+ * Splits a given string expressing phone numbers into several strings, and remove + * unnecessary characters inside them. The size of a returned list becomes 1 when + * no split is needed. + *

+ *

+ * The given number "may" have several phone numbers when the contact entry is corrupted + * because of its original source. + * e.g. "111-222-3333 (Miami)\n444-555-6666 (Broward; 305-653-6796 (Miami)" + *

+ *

+ * This kind of "phone numbers" will not be created with Android vCard implementation, + * but we may encounter them if the source of the input data has already corrupted + * implementation. + *

+ *

+ * To handle this case, this method first splits its input into multiple parts + * (e.g. "111-222-3333 (Miami)", "444-555-6666 (Broward", and 305653-6796 (Miami)") and + * removes unnecessary strings like "(Miami)". + *

+ *

+ * Do not call this method when trimming is inappropriate for its receivers. + *

+ */ + private List splitAndTrimPhoneNumbers(final String phoneNumber) { + final List phoneList = new ArrayList(); StringBuilder builder = new StringBuilder(); final int length = phoneNumber.length(); for (int i = 0; i < length; i++) { final char ch = phoneNumber.charAt(i); - // TODO: add a test case for string with '+', and care the other possible issues - // which may happen by ignoring non-digits other than '+'. if (Character.isDigit(ch) || ch == '+') { builder.append(ch); } else if ((ch == ';' || ch == '\n') && builder.length() > 0) { diff --git a/core/java/android/pim/vcard/VCardConfig.java b/core/java/android/pim/vcard/VCardConfig.java index 3409be6b91e1fdd0e90eb8646e9f1dd7fd68266b..82198406cb5b65f7f683a0d31e9434e0a6878b98 100644 --- a/core/java/android/pim/vcard/VCardConfig.java +++ b/core/java/android/pim/vcard/VCardConfig.java @@ -15,6 +15,7 @@ */ package android.pim.vcard; +import android.telephony.PhoneNumberUtils; import android.util.Log; import java.util.HashMap; @@ -190,6 +191,30 @@ public class VCardConfig { */ public static final int FLAG_REFRAIN_IMAGE_EXPORT = 0x02000000; + /** + *

+ * The flag indicating the vCard composer does touch nothing toward phone number Strings + * but leave it as is. + *

+ *

+ * The vCard specifications mention nothing toward phone numbers, while some devices + * do (wrongly, but with innevitable reasons). + * For example, there's a possibility Japanese mobile phones are expected to have + * just numbers, hypens, plus, etc. but not usual alphabets, while US mobile phones + * should get such characters. To make exported vCard simple for external parsers, + * we have used {@link PhoneNumberUtils#formatNumber(String)} during export, and + * removed unnecessary characters inside the number (e.g. "111-222-3333 (Miami)" + * becomes "111-222-3333"). + * Unfortunate side effect of that use was some control characters used in the other + * areas may be badly affected by the formatting. + *

+ *

+ * This flag disables that formatting, affecting both importer and exporter. + * If the user is aware of some side effects due to the implicit formatting, use this flag. + *

+ */ + public static final int FLAG_REFRAIN_PHONE_NUMBER_FORMATTING = 0x02000000; + //// The followings are VCard types available from importer/exporter. //// /** @@ -431,6 +456,10 @@ public class VCardConfig { return sJapaneseMobileTypeSet.contains(vcardType); } + /* package */ static boolean refrainPhoneNumberFormatting(final int vcardType) { + return ((vcardType & FLAG_REFRAIN_PHONE_NUMBER_FORMATTING) != 0); + } + public static boolean needsToConvertPhoneticString(final int vcardType) { return ((vcardType & FLAG_CONVERT_PHONETIC_NAME_STRINGS) != 0); } @@ -445,4 +474,4 @@ public class VCardConfig { private VCardConfig() { } -} \ No newline at end of file +} diff --git a/core/java/android/pim/vcard/VCardEntry.java b/core/java/android/pim/vcard/VCardEntry.java index 13277704bdcf82082021285acf6b6de208802495..7c7e9b83094f7b38df1a1ca0bdb92bebac3e5b88 100644 --- a/core/java/android/pim/vcard/VCardEntry.java +++ b/core/java/android/pim/vcard/VCardEntry.java @@ -488,7 +488,7 @@ public class VCardEntry { final StringBuilder builder = new StringBuilder(); final String trimed = data.trim(); final String formattedNumber; - if (type == Phone.TYPE_PAGER) { + if (type == Phone.TYPE_PAGER || VCardConfig.refrainPhoneNumberFormatting(mVCardType)) { formattedNumber = trimed; } else { final int length = trimed.length(); @@ -500,8 +500,7 @@ public class VCardEntry { } // Use NANP in default when there's no information about locale. - final int formattingType = (VCardConfig.isJapaneseDevice(mVCardType) ? - PhoneNumberUtils.FORMAT_JAPAN : PhoneNumberUtils.FORMAT_NANP); + final int formattingType = VCardUtils.getPhoneNumberFormat(mVCardType); formattedNumber = PhoneNumberUtils.formatNumber(builder.toString(), formattingType); } PhoneData phoneData = new PhoneData(type, formattedNumber, label, isPrimary); diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java index cc48aeb70844986fa47f923d4b921425309120a0..bbad2b6d432ce44ad05ddbc44487000b150135ef 100644 --- a/core/java/android/preference/DialogPreference.java +++ b/core/java/android/preference/DialogPreference.java @@ -33,7 +33,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.Window; import android.view.WindowManager; -import android.view.inputmethod.InputMethodManager; import android.widget.TextView; /** @@ -275,7 +274,7 @@ public abstract class DialogPreference extends Preference implements protected void showDialog(Bundle state) { Context context = getContext(); - mWhichButtonClicked = DialogInterface.BUTTON2; + mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE; mBuilder = new AlertDialog.Builder(context) .setTitle(mDialogTitle) diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index c9d125b9159f92adc7f02ba0537e803a6da590ac..40ed980d6c66fadcbc3382147a1f9c4185e348a6 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -1819,4 +1819,12 @@ public final class MediaStore { * Name of current volume being scanned by the media scanner. */ public static final String MEDIA_SCANNER_VOLUME = "volume"; + + /** + * Name of the file signaling the media scanner to ignore media in the containing directory + * and its subdirectories. Developers should use this to avoid application graphics showing + * up in the Gallery and likewise prevent application sounds and music from showing up in + * the Music app. + */ + public static final String MEDIA_IGNORE_FILENAME = ".nomedia"; } diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index 893db2e748c6faa6dc1c6a559d244e181c71eb07..ac89934ada60347ad5031485596a44a3e8c60318 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -554,6 +554,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { if (!result) { if (deviceObjectPath != null) { String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath); + if (address == null) return; BluetoothDevice device = mAdapter.getRemoteDevice(address); int state = getSinkState(device); handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTED); diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 3d1d7d63b3ed4b626f98c83bd4baf749f2edbbf9..2ade44e99e10a628f570aebcdeaa52131734d73d 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -522,20 +522,14 @@ public abstract class WallpaperService extends Service { } try { - SurfaceHolder.Callback callbacks[] = null; - synchronized (mSurfaceHolder.mCallbacks) { - final int N = mSurfaceHolder.mCallbacks.size(); - if (N > 0) { - callbacks = new SurfaceHolder.Callback[N]; - mSurfaceHolder.mCallbacks.toArray(callbacks); - } - } + mSurfaceHolder.ungetCallbacks(); if (surfaceCreating) { mIsCreating = true; if (DEBUG) Log.v(TAG, "onSurfaceCreated(" + mSurfaceHolder + "): " + this); onSurfaceCreated(mSurfaceHolder); + SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); if (callbacks != null) { for (SurfaceHolder.Callback c : callbacks) { c.surfaceCreated(mSurfaceHolder); @@ -557,6 +551,7 @@ public abstract class WallpaperService extends Service { + "): " + this); onSurfaceChanged(mSurfaceHolder, mFormat, mCurWidth, mCurHeight); + SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); if (callbacks != null) { for (SurfaceHolder.Callback c : callbacks) { c.surfaceChanged(mSurfaceHolder, mFormat, @@ -698,14 +693,12 @@ public abstract class WallpaperService extends Service { void reportSurfaceDestroyed() { if (mSurfaceCreated) { mSurfaceCreated = false; - SurfaceHolder.Callback callbacks[]; - synchronized (mSurfaceHolder.mCallbacks) { - callbacks = new SurfaceHolder.Callback[ - mSurfaceHolder.mCallbacks.size()]; - mSurfaceHolder.mCallbacks.toArray(callbacks); - } - for (SurfaceHolder.Callback c : callbacks) { - c.surfaceDestroyed(mSurfaceHolder); + mSurfaceHolder.ungetCallbacks(); + SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); + if (callbacks != null) { + for (SurfaceHolder.Callback c : callbacks) { + c.surfaceDestroyed(mSurfaceHolder); + } } if (DEBUG) Log.v(TAG, "onSurfaceDestroyed(" + mSurfaceHolder + "): " + this); diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index 2628eb4026d58d6210a617a76d0511c670209fe6..76d81065f2e5ee8fb03f45e085eeba70506bae30 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -135,6 +135,7 @@ public class DisplayMetrics { int screenLayout) { boolean expandable = compatibilityInfo.isConfiguredExpandable(); boolean largeScreens = compatibilityInfo.isConfiguredLargeScreens(); + boolean xlargeScreens = compatibilityInfo.isConfiguredXLargeScreens(); // Note: this assume that configuration is updated before calling // updateMetrics method. @@ -157,8 +158,18 @@ public class DisplayMetrics { compatibilityInfo.setLargeScreens(false); } } + if (!xlargeScreens) { + if ((screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) + != Configuration.SCREENLAYOUT_SIZE_XLARGE) { + xlargeScreens = true; + // the current screen size is not large. + compatibilityInfo.setXLargeScreens(true); + } else { + compatibilityInfo.setXLargeScreens(false); + } + } - if (!expandable || !largeScreens) { + if (!expandable || (!largeScreens && !xlargeScreens)) { // This is a larger screen device and the app is not // compatible with large screens, so diddle it. diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java old mode 100644 new mode 100755 index d4f978756f4d4284968ee0d8f2d458a5e21c07fd..9aa16b53216d796e47cd3b3b7fbfae61f711a5f2 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -120,6 +120,10 @@ public class KeyEvent implements Parcelable { public static final int KEYCODE_MEDIA_REWIND = 89; public static final int KEYCODE_MEDIA_FAST_FORWARD = 90; public static final int KEYCODE_MUTE = 91; + public static final int KEYCODE_PAGE_UP = 92; + public static final int KEYCODE_PAGE_DOWN = 93; + public static final int KEYCODE_PICTSYMBOLS = 94; // switch symbol-sets (Emoji,Kao-moji) + public static final int KEYCODE_SWITCH_CHARSET = 95; // switch char-sets (Kanji,Katakana) // NOTE: If you add a new keycode here you must also add it to: // isSystem() @@ -135,7 +139,7 @@ public class KeyEvent implements Parcelable { // those new codes. This is intended to maintain a consistent // set of key code definitions across all Android devices. - private static final int LAST_KEYCODE = KEYCODE_MUTE; + private static final int LAST_KEYCODE = KEYCODE_SWITCH_CHARSET; /** * @deprecated There are now more than MAX_KEYCODE keycodes. @@ -692,6 +696,8 @@ public class KeyEvent implements Parcelable { case KEYCODE_CAMERA: case KEYCODE_FOCUS: case KEYCODE_SEARCH: + case KEYCODE_PICTSYMBOLS: + case KEYCODE_SWITCH_CHARSET: return true; default: return false; diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 83ef8ba51747ad99b30117f2cf12a05b55fff337..cd0ae3b02fbb3766fb13e5c983265a7dc298838e 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -139,14 +139,14 @@ public class Surface implements Parcelable { */ public static final int FLAGS_ORIENTATION_ANIMATION_DISABLE = 0x000000001; - @SuppressWarnings("unused") - private int mSurface; @SuppressWarnings("unused") private int mSurfaceControl; @SuppressWarnings("unused") private int mSaveCount; @SuppressWarnings("unused") private Canvas mCanvas; + @SuppressWarnings("unused") + private int mNativeSurface; private String mName; // The display metrics used to provide the pseudo canvas size for applications @@ -422,13 +422,13 @@ public class Surface implements Parcelable { /* no user serviceable parts here ... */ @Override protected void finalize() throws Throwable { - if (mSurface != 0 || mSurfaceControl != 0) { + if (mNativeSurface != 0 || mSurfaceControl != 0) { if (DEBUG_RELEASE) { Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" - + mSurface + ", " + mSurfaceControl + ")", mCreationStack); + + mNativeSurface + ", " + mSurfaceControl + ")", mCreationStack); } else { Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" - + mSurface + ", " + mSurfaceControl + ")"); + + mNativeSurface + ", " + mSurfaceControl + ")"); } } release(); diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java index 64a10d194f5ef7b5d1d8a5764f86675fc6dff539..34e4638728e9899d420fcf54fb18f3e2e4503513 100644 --- a/core/java/android/view/SurfaceHolder.java +++ b/core/java/android/view/SurfaceHolder.java @@ -182,7 +182,6 @@ public interface SurfaceHolder { /** * Enable or disable option to keep the screen turned on while this * surface is displayed. The default is false, allowing it to turn off. - * Enabling the option effectivelty. * This is safe to call from any thread. * * @param screenOn Supply to true to force the screen to stay on, false diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 2a3f03269cd9a1397736138672db632b5c408216..cc30d71de3130d34dbf4b100a9213c94a21e4c82 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -140,7 +140,10 @@ public class SurfaceView extends View { boolean mViewVisibility = false; int mRequestedWidth = -1; int mRequestedHeight = -1; - int mRequestedFormat = PixelFormat.OPAQUE; + /* Set SurfaceView's format to 565 by default to maintain backward + * compatibility with applications assuming this format. + */ + int mRequestedFormat = PixelFormat.RGB_565; int mRequestedType = -1; boolean mHaveFrame = false; @@ -163,16 +166,20 @@ public class SurfaceView extends View { public SurfaceView(Context context) { super(context); - setWillNotDraw(true); + init(); } public SurfaceView(Context context, AttributeSet attrs) { super(context, attrs); - setWillNotDraw(true); + init(); } public SurfaceView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + init(); + } + + private void init() { setWillNotDraw(true); } diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java index aab76c4fdfcf8da3c51ccc36b56ddc4b81ee940c..e69b80721bab756ce94abce6aabefca7a4d092ee 100644 --- a/core/java/android/view/VelocityTracker.java +++ b/core/java/android/view/VelocityTracker.java @@ -206,7 +206,7 @@ public final class VelocityTracker implements Poolable { final long oldestTime = pastTime[oldestTouch]; float accumX = 0; float accumY = 0; - float N = (lastTouch - oldestTouch + NUM_PAST) % NUM_PAST + 1; + int N = (lastTouch - oldestTouch + NUM_PAST) % NUM_PAST + 1; // Skip the last received event, since it is probably pretty noisy. if (N > 3) N--; diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 03efea964c26edde9588325d4e40fcff4526dd1b..aa124e6a6e20f0299383c4441b1252699458f280 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -16,8 +16,10 @@ package android.view; +import com.android.internal.view.BaseSurfaceHolder; import com.android.internal.view.IInputMethodCallback; import com.android.internal.view.IInputMethodSession; +import com.android.internal.view.RootViewSurfaceTaker; import android.graphics.Canvas; import android.graphics.PixelFormat; @@ -26,12 +28,12 @@ import android.graphics.Rect; import android.graphics.Region; import android.os.*; import android.os.Process; -import android.os.SystemProperties; import android.util.AndroidRuntimeException; import android.util.Config; import android.util.DisplayMetrics; import android.util.Log; import android.util.EventLog; +import android.util.Slog; import android.util.SparseArray; import android.view.View.MeasureSpec; import android.view.accessibility.AccessibilityEvent; @@ -50,6 +52,7 @@ import android.Manifest; import android.media.AudioManager; import java.lang.ref.WeakReference; +import java.io.FileDescriptor; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; @@ -76,6 +79,7 @@ public final class ViewRoot extends Handler implements ViewParent, /** @noinspection PointlessBooleanExpression*/ private static final boolean DEBUG_DRAW = false || LOCAL_LOGV; private static final boolean DEBUG_LAYOUT = false || LOCAL_LOGV; + private static final boolean DEBUG_INPUT = true || LOCAL_LOGV; private static final boolean DEBUG_INPUT_RESIZE = false || LOCAL_LOGV; private static final boolean DEBUG_ORIENTATION = false || LOCAL_LOGV; private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV; @@ -133,6 +137,11 @@ public final class ViewRoot extends Handler implements ViewParent, int mViewVisibility; boolean mAppVisible = true; + SurfaceHolder.Callback mSurfaceHolderCallback; + BaseSurfaceHolder mSurfaceHolder; + boolean mIsCreating; + boolean mDrawingAllowed; + final Region mTransparentRegion; final Region mPreviousTransparentRegion; @@ -425,6 +434,9 @@ public final class ViewRoot extends Handler implements ViewParent, } } + // fd [0] is the receiver, [1] is the sender + private native int[] makeInputChannel(); + /** * We have one child */ @@ -435,6 +447,13 @@ public final class ViewRoot extends Handler implements ViewParent, mView = view; mWindowAttributes.copyFrom(attrs); attrs = mWindowAttributes; + if (view instanceof RootViewSurfaceTaker) { + mSurfaceHolderCallback = + ((RootViewSurfaceTaker)view).willYouTakeTheSurface(); + if (mSurfaceHolderCallback != null) { + mSurfaceHolder = new TakenSurfaceHolder(); + } + } Resources resources = mView.getContext().getResources(); CompatibilityInfo compatibilityInfo = resources.getCompatibilityInfo(); mTranslator = compatibilityInfo.getTranslator(); @@ -469,6 +488,14 @@ public final class ViewRoot extends Handler implements ViewParent, mAdded = true; int res; /* = WindowManagerImpl.ADD_OKAY; */ + // Set up the input event channel + if (false) { + int[] fds = makeInputChannel(); + if (DEBUG_INPUT) { + Log.v(TAG, "makeInputChannel() returned " + fds); + } + } + // Schedule the first layout -before- adding to the window // manager, to make sure we do the relayout before receiving // any other events from the system. @@ -682,6 +709,7 @@ public final class ViewRoot extends Handler implements ViewParent, boolean windowResizesToFitContent = false; boolean fullRedrawNeeded = mFullRedrawNeeded; boolean newSurface = false; + boolean surfaceChanged = false; WindowManager.LayoutParams lp = mWindowAttributes; int desiredWindowWidth; @@ -700,6 +728,7 @@ public final class ViewRoot extends Handler implements ViewParent, WindowManager.LayoutParams params = null; if (mWindowAttributesChanged) { mWindowAttributesChanged = false; + surfaceChanged = true; params = lp; } Rect frame = mWinFrame; @@ -886,11 +915,18 @@ public final class ViewRoot extends Handler implements ViewParent, } } + if (mSurfaceHolder != null) { + mSurfaceHolder.mSurfaceLock.lock(); + mDrawingAllowed = true; + lp.format = mSurfaceHolder.getRequestedFormat(); + lp.type = mSurfaceHolder.getRequestedType(); + } + boolean initialized = false; boolean contentInsetsChanged = false; boolean visibleInsetsChanged; + boolean hadSurface = mSurface.isValid(); try { - boolean hadSurface = mSurface.isValid(); int fl = 0; if (params != null) { fl = params.flags; @@ -965,6 +1001,7 @@ public final class ViewRoot extends Handler implements ViewParent, } } catch (RemoteException e) { } + if (DEBUG_ORIENTATION) Log.v( "ViewRoot", "Relayout returned: frame=" + frame + ", surface=" + mSurface); @@ -977,6 +1014,57 @@ public final class ViewRoot extends Handler implements ViewParent, mWidth = frame.width(); mHeight = frame.height(); + if (mSurfaceHolder != null) { + // The app owns the surface; tell it about what is going on. + if (mSurface.isValid()) { + // XXX .copyFrom() doesn't work! + //mSurfaceHolder.mSurface.copyFrom(mSurface); + mSurfaceHolder.mSurface = mSurface; + } + mSurfaceHolder.mSurfaceLock.unlock(); + if (mSurface.isValid()) { + if (!hadSurface) { + mSurfaceHolder.ungetCallbacks(); + + mIsCreating = true; + mSurfaceHolderCallback.surfaceCreated(mSurfaceHolder); + SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); + if (callbacks != null) { + for (SurfaceHolder.Callback c : callbacks) { + c.surfaceCreated(mSurfaceHolder); + } + } + surfaceChanged = true; + } + if (surfaceChanged) { + mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder, + lp.format, mWidth, mHeight); + SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); + if (callbacks != null) { + for (SurfaceHolder.Callback c : callbacks) { + c.surfaceChanged(mSurfaceHolder, lp.format, + mWidth, mHeight); + } + } + } + mIsCreating = false; + } else if (hadSurface) { + mSurfaceHolder.ungetCallbacks(); + SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); + mSurfaceHolderCallback.surfaceDestroyed(mSurfaceHolder); + if (callbacks != null) { + for (SurfaceHolder.Callback c : callbacks) { + c.surfaceDestroyed(mSurfaceHolder); + } + } + mSurfaceHolder.mSurfaceLock.lock(); + // Make surface invalid. + //mSurfaceHolder.mSurface.copyFrom(mSurface); + mSurfaceHolder.mSurface = new Surface(); + mSurfaceHolder.mSurfaceLock.unlock(); + } + } + if (initialized) { mGlCanvas.setViewport((int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f)); @@ -1268,6 +1356,12 @@ public final class ViewRoot extends Handler implements ViewParent, boolean scalingRequired = mAttachInfo.mScalingRequired; Rect dirty = mDirty; + if (mSurfaceHolder != null) { + // The app owns the surface, we won't draw. + dirty.setEmpty(); + return; + } + if (mUseGL) { if (!dirty.isEmpty()) { Canvas canvas = mGlCanvas; @@ -1332,103 +1426,105 @@ public final class ViewRoot extends Handler implements ViewParent, appScale + ", width=" + mWidth + ", height=" + mHeight); } - Canvas canvas; - try { - int left = dirty.left; - int top = dirty.top; - int right = dirty.right; - int bottom = dirty.bottom; - canvas = surface.lockCanvas(dirty); - - if (left != dirty.left || top != dirty.top || right != dirty.right || - bottom != dirty.bottom) { - mAttachInfo.mIgnoreDirtyState = true; - } - - // TODO: Do this in native - canvas.setDensity(mDensity); - } catch (Surface.OutOfResourcesException e) { - Log.e("ViewRoot", "OutOfResourcesException locking surface", e); - // TODO: we should ask the window manager to do something! - // for now we just do nothing - return; - } catch (IllegalArgumentException e) { - Log.e("ViewRoot", "IllegalArgumentException locking surface", e); - // TODO: we should ask the window manager to do something! - // for now we just do nothing - return; - } + if (!dirty.isEmpty() || mIsAnimating) { + Canvas canvas; + try { + int left = dirty.left; + int top = dirty.top; + int right = dirty.right; + int bottom = dirty.bottom; + canvas = surface.lockCanvas(dirty); + + if (left != dirty.left || top != dirty.top || right != dirty.right || + bottom != dirty.bottom) { + mAttachInfo.mIgnoreDirtyState = true; + } - try { - if (!dirty.isEmpty() || mIsAnimating) { - long startTime = 0L; + // TODO: Do this in native + canvas.setDensity(mDensity); + } catch (Surface.OutOfResourcesException e) { + Log.e("ViewRoot", "OutOfResourcesException locking surface", e); + // TODO: we should ask the window manager to do something! + // for now we just do nothing + return; + } catch (IllegalArgumentException e) { + Log.e("ViewRoot", "IllegalArgumentException locking surface", e); + // TODO: we should ask the window manager to do something! + // for now we just do nothing + return; + } - if (DEBUG_ORIENTATION || DEBUG_DRAW) { - Log.v("ViewRoot", "Surface " + surface + " drawing to bitmap w=" - + canvas.getWidth() + ", h=" + canvas.getHeight()); - //canvas.drawARGB(255, 255, 0, 0); - } + try { + if (!dirty.isEmpty() || mIsAnimating) { + long startTime = 0L; - if (Config.DEBUG && ViewDebug.profileDrawing) { - startTime = SystemClock.elapsedRealtime(); - } + if (DEBUG_ORIENTATION || DEBUG_DRAW) { + Log.v("ViewRoot", "Surface " + surface + " drawing to bitmap w=" + + canvas.getWidth() + ", h=" + canvas.getHeight()); + //canvas.drawARGB(255, 255, 0, 0); + } - // If this bitmap's format includes an alpha channel, we - // need to clear it before drawing so that the child will - // properly re-composite its drawing on a transparent - // background. This automatically respects the clip/dirty region - // or - // If we are applying an offset, we need to clear the area - // where the offset doesn't appear to avoid having garbage - // left in the blank areas. - if (!canvas.isOpaque() || yoff != 0) { - canvas.drawColor(0, PorterDuff.Mode.CLEAR); - } + if (Config.DEBUG && ViewDebug.profileDrawing) { + startTime = SystemClock.elapsedRealtime(); + } - dirty.setEmpty(); - mIsAnimating = false; - mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); - mView.mPrivateFlags |= View.DRAWN; + // If this bitmap's format includes an alpha channel, we + // need to clear it before drawing so that the child will + // properly re-composite its drawing on a transparent + // background. This automatically respects the clip/dirty region + // or + // If we are applying an offset, we need to clear the area + // where the offset doesn't appear to avoid having garbage + // left in the blank areas. + if (!canvas.isOpaque() || yoff != 0) { + canvas.drawColor(0, PorterDuff.Mode.CLEAR); + } - if (DEBUG_DRAW) { - Context cxt = mView.getContext(); - Log.i(TAG, "Drawing: package:" + cxt.getPackageName() + - ", metrics=" + cxt.getResources().getDisplayMetrics() + - ", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo()); - } - int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); - try { - canvas.translate(0, -yoff); - if (mTranslator != null) { - mTranslator.translateCanvas(canvas); + dirty.setEmpty(); + mIsAnimating = false; + mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); + mView.mPrivateFlags |= View.DRAWN; + + if (DEBUG_DRAW) { + Context cxt = mView.getContext(); + Log.i(TAG, "Drawing: package:" + cxt.getPackageName() + + ", metrics=" + cxt.getResources().getDisplayMetrics() + + ", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo()); + } + int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); + try { + canvas.translate(0, -yoff); + if (mTranslator != null) { + mTranslator.translateCanvas(canvas); + } + canvas.setScreenDensity(scalingRequired + ? DisplayMetrics.DENSITY_DEVICE : 0); + mView.draw(canvas); + } finally { + mAttachInfo.mIgnoreDirtyState = false; + canvas.restoreToCount(saveCount); } - canvas.setScreenDensity(scalingRequired - ? DisplayMetrics.DENSITY_DEVICE : 0); - mView.draw(canvas); - } finally { - mAttachInfo.mIgnoreDirtyState = false; - canvas.restoreToCount(saveCount); - } - if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) { - mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING); - } + if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) { + mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING); + } - if (SHOW_FPS || Config.DEBUG && ViewDebug.showFps) { - int now = (int)SystemClock.elapsedRealtime(); - if (sDrawTime != 0) { - nativeShowFPS(canvas, now - sDrawTime); + if (SHOW_FPS || Config.DEBUG && ViewDebug.showFps) { + int now = (int)SystemClock.elapsedRealtime(); + if (sDrawTime != 0) { + nativeShowFPS(canvas, now - sDrawTime); + } + sDrawTime = now; } - sDrawTime = now; - } - if (Config.DEBUG && ViewDebug.profileDrawing) { - EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime); + if (Config.DEBUG && ViewDebug.profileDrawing) { + EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime); + } } - } - } finally { - surface.unlockCanvasAndPost(canvas); + } finally { + surface.unlockCanvasAndPost(canvas); + } } if (LOCAL_LOGV) { @@ -2813,6 +2909,46 @@ public final class ViewRoot extends Handler implements ViewParent, return scrollToRectOrFocus(rectangle, immediate); } + class TakenSurfaceHolder extends BaseSurfaceHolder { + @Override + public boolean onAllowLockCanvas() { + return mDrawingAllowed; + } + + @Override + public void onRelayoutContainer() { + // Not currently interesting -- from changing between fixed and layout size. + } + + public void setFormat(int format) { + ((RootViewSurfaceTaker)mView).setSurfaceFormat(format); + } + + public void setType(int type) { + ((RootViewSurfaceTaker)mView).setSurfaceType(type); + } + + @Override + public void onUpdateSurface() { + // We take care of format and type changes on our own. + throw new IllegalStateException("Shouldn't be here"); + } + + public boolean isCreating() { + return mIsCreating; + } + + @Override + public void setFixedSize(int width, int height) { + throw new UnsupportedOperationException( + "Currently only support sizing from layout"); + } + + public void setKeepScreenOn(boolean screenOn) { + ((RootViewSurfaceTaker)mView).setSurfaceKeepScreenOn(screenOn); + } + } + static class InputMethodCallback extends IInputMethodCallback.Stub { private WeakReference mViewRoot; diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 7dd5085f1075cde34922e57450d259ed745d46a2..234deba75b7112891a1f85e6a35cef290d85ae9b 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -472,6 +472,14 @@ public abstract class Window { return mCallback; } + /** + * Take ownership of this window's surface. The window's view hierarchy + * will no longer draw into the surface, though it will otherwise continue + * to operate (such as for receiving input events). The given SurfaceHolder + * callback will be used to tell you about state changes to the surface. + */ + public abstract void takeSurface(SurfaceHolder.Callback callback); + /** * Return whether this window is being displayed with a floating style * (based on the {@link android.R.attr#windowIsFloating} attribute in diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java index 034c88ae07313ca998773a205f0ed3b0795e59ca..ca9ad53c52a5c12100657b96e958ee5a38d955df 100644 --- a/core/java/android/webkit/MimeTypeMap.java +++ b/core/java/android/webkit/MimeTypeMap.java @@ -67,7 +67,7 @@ public class MimeTypeMap { // if the filename contains special characters, we don't // consider it valid for our matching purposes: if (filename.length() > 0 && - Pattern.matches("[a-zA-Z_0-9\\.\\-\\(\\)]+", filename)) { + Pattern.matches("[a-zA-Z_0-9\\.\\-\\(\\)\\%]+", filename)) { int dotPos = filename.lastIndexOf('.'); if (0 <= dotPos) { return filename.substring(dotPos + 1); diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java index b3d5f1af58a747661987eb10a44a0b510d405db2..1fc23abe1eb2d8e5fad77da49c91a9d8483fb766 100644 --- a/core/java/android/widget/DatePicker.java +++ b/core/java/android/widget/DatePicker.java @@ -328,6 +328,7 @@ public class DatePicker extends FrameLayout { mYear = ss.getYear(); mMonth = ss.getMonth(); mDay = ss.getDay(); + updateSpinners(); } /** diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java index f34823cb484a3755202c0790646861a5c7468f59..1ed6b166ee04b8057d25c1e448d1cae99198952b 100644 --- a/core/java/android/widget/Gallery.java +++ b/core/java/android/widget/Gallery.java @@ -1087,7 +1087,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList @Override public boolean dispatchKeyEvent(KeyEvent event) { // Gallery steals all key events - return event.dispatch(this); + return event.dispatch(this, null, null); } /** diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index 202e65852149e9ffcd5787cef3db6be02dea3527..8e9eb05a066e0312a1ec6a2405ac69d883b901d0 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -947,4 +947,20 @@ public class ProgressBar extends View { setProgress(ss.progress); setSecondaryProgress(ss.secondaryProgress); } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (mIndeterminate) { + startAnimation(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mIndeterminate) { + stopAnimation(); + } + } } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 64c9c9964d167532097964937dc9056d70ad0995..950012c8bf133f3bc04412f8dc42ab5d3e279663 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4547,6 +4547,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener outText.text = TextUtils.substring(content, partialStartOffset, partialEndOffset); } + } else { + outText.partialStartOffset = 0; + outText.partialEndOffset = 0; + outText.text = ""; } outText.flags = 0; if (MetaKeyKeyListener.getMetaState(mText, MetaKeyKeyListener.META_SELECTING) != 0) { diff --git a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java index 7e9bbd198c1283c9c0811e5b52de2494d44746ad..98dcb8bcbf07bddb30053384d7569f7213e3173e 100644 --- a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java +++ b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java @@ -23,13 +23,10 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; -import android.os.Handler; import android.os.storage.IMountService; -import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.os.Environment; -import android.widget.Toast; import android.util.Log; /** @@ -38,7 +35,7 @@ import android.util.Log; */ public class ExternalMediaFormatActivity extends AlertActivity implements DialogInterface.OnClickListener { - private static final int POSITIVE_BUTTON = AlertDialog.BUTTON1; + private static final int POSITIVE_BUTTON = AlertDialog.BUTTON_POSITIVE; /** Used to detect when the media state changes, in case we need to call finish() */ private BroadcastReceiver mStorageReceiver = new BroadcastReceiver() { diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java index 24818a84a130b2f8397fdba642a281360b4dd78d..36f45b24ee2227677fc1eda3a4d5745ad52b6871 100755 --- a/core/java/com/android/internal/app/NetInitiatedActivity.java +++ b/core/java/com/android/internal/app/NetInitiatedActivity.java @@ -23,14 +23,9 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.RemoteException; -import android.os.ServiceManager; import android.widget.Toast; import android.util.Log; import android.location.LocationManager; -import com.android.internal.location.GpsLocationProvider; import com.android.internal.location.GpsNetInitiatedHandler; /** @@ -44,8 +39,8 @@ public class NetInitiatedActivity extends AlertActivity implements DialogInterfa private static final boolean DEBUG = true; private static final boolean VERBOSE = false; - private static final int POSITIVE_BUTTON = AlertDialog.BUTTON1; - private static final int NEGATIVE_BUTTON = AlertDialog.BUTTON2; + private static final int POSITIVE_BUTTON = AlertDialog.BUTTON_POSITIVE; + private static final int NEGATIVE_BUTTON = AlertDialog.BUTTON_NEGATIVE; // Dialog button text public static final String BUTTON_TEXT_ACCEPT = "Accept"; diff --git a/core/java/com/android/internal/app/RingtonePickerActivity.java b/core/java/com/android/internal/app/RingtonePickerActivity.java index ddddabefba33ebf4208b2b24506f98b7148d5176..5569ffe1bb72eee52eb57d9202e15b90b20b38cf 100644 --- a/core/java/com/android/internal/app/RingtonePickerActivity.java +++ b/core/java/com/android/internal/app/RingtonePickerActivity.java @@ -223,7 +223,7 @@ public final class RingtonePickerActivity extends AlertActivity implements * On click of Ok/Cancel buttons */ public void onClick(DialogInterface dialog, int which) { - boolean positiveResult = which == BUTTON1; + boolean positiveResult = which == DialogInterface.BUTTON_POSITIVE; // Stop playing the previous ringtone mRingtoneManager.stopPreviousRingtone(); diff --git a/core/java/com/android/internal/util/HierarchicalStateMachine.java b/core/java/com/android/internal/util/HierarchicalStateMachine.java index 9911f486d5ac9e1710b09025b3dd2712453d1300..c599d68e7a3c2498f5b14c43f0fbc85684e12d01 100644 --- a/core/java/com/android/internal/util/HierarchicalStateMachine.java +++ b/core/java/com/android/internal/util/HierarchicalStateMachine.java @@ -51,7 +51,7 @@ import java.util.HashMap; mS2 mS1 ----> initial state * After the state machine is created and started, messages are sent to a state - * machine using sendMessagesendMessage and the messages are created using * obtainMessage. When the state machine receives a message the * current state's processMessage is invoked. In the above example * mS1.processMessage will be invoked first. The state may use transitionTo @@ -59,9 +59,9 @@ import java.util.HashMap; * * Each state in the state machine may have a zero or one parent states and if * a child state is unable to handle a message it may have the message processed - * by its parent by returning false. If a message is never processed unhandledMessage - * will be invoked to give one last chance for the state machine to process - * the message. + * by its parent by returning false or NOT_HANDLED. If a message is never processed + * unhandledMessage will be invoked to give one last chance for the state machine + * to process the message. * * When all processing is completed a state machine may choose to call * transitionToHaltingState. When the current processingMessage @@ -95,7 +95,7 @@ import java.util.HashMap; * any other messages that are on the queue or might be added later. Both of * these are protected and may only be invoked from within a state machine. * - * To illustrate some of these properties we'll use state machine with 8 + * To illustrate some of these properties we'll use state machine with an 8 * state hierarchy: mP0 @@ -109,44 +109,19 @@ import java.util.HashMap; * * After starting mS5 the list of active states is mP0, mP1, mS1 and mS5. * So the order of calling processMessage when a message is received is mS5, - * mS1, mP1, mP0 assuming each processMessage indicates it can't handle this - * message by returning false. + * mS1, mP1, mP0 assuming each processMessage indicates it can't handle this + * message by returning false or NOT_HANDLED. * * Now assume mS5.processMessage receives a message it can handle, and during - * the handling determines the machine should changes states. It would call - * transitionTo(mS4) and return true. Immediately after returning from + * the handling determines the machine should change states. It could call + * transitionTo(mS4) and return true or HANDLED. Immediately after returning from * processMessage the state machine runtime will find the common parent, * which is mP1. It will then call mS5.exit, mS1.exit, mS2.enter and then * mS4.enter. The new list of active states is mP0, mP1, mS2 and mS4. So * when the next message is received mS4.processMessage will be invoked. * - * To assist in describing an HSM a simple grammar has been created which - * is informally defined here and a formal EBNF description is at the end - * of the class comment. - * - * An HSM starts with the name and includes a set of hierarchical states. - * A state is preceeded by one or more plus signs (+), to indicate its - * depth and a hash (#) if its the initial state. Child states follow their - * parents and have one more plus sign then their parent. Inside a state - * are a series of messages, the actions they perform and if the processing - * is complete ends with a period (.). If processing isn't complete and - * the parent should process the message it ends with a caret (^). The - * actions include send a message ($MESSAGE), defer a message (%MESSAGE), - * transition to a new state (>MESSAGE) and an if statement - * (if ( expression ) { list of actions }.) - * - * The Hsm HelloWorld could documented as: - * - * HelloWorld { - * + # mState1. - * } - * - * and interpreted as HSM HelloWorld: - * - * mState1 a root state (single +) and initial state (#) which - * processes all messages completely, the period (.). - * - * The implementation is: + * Now for some concrete examples, here is the canonical HelloWorld as an HSM. + * It responds with "Hello World" being printed to the log for every message. class HelloWorld extends HierarchicalStateMachine { Hsm1(String name) { @@ -164,7 +139,7 @@ class HelloWorld extends HierarchicalStateMachine { class State1 extends HierarchicalState { @Override public boolean processMessage(Message message) { Log.d(TAG, "Hello World"); - return true; + return HANDLED; } } State1 mState1 = new State1(); @@ -176,7 +151,7 @@ void testHelloWorld() { } * - * A more interesting state machine is one of four states + * A more interesting state machine is one with four states * with two independent parent states. mP1 mP2 @@ -184,45 +159,68 @@ void testHelloWorld() { mS2 mS1 * - * documented as: + * Here is a description of this state machine using pseudo code. * - * Hsm1 { - * + mP1 { - * CMD_2 { - * $CMD_3 - * %CMD_2 - * >mS2 - * }. - * } - * ++ # mS1 { CMD_1{ >mS1 }^ } - * ++ mS2 { - * CMD_2{$CMD_4}. - * CMD_3{%CMD_3 ; >mP2}. - * } * - * + mP2 e($CMD_5) { - * CMD_3, CMD_4. - * CMD_5{>HALT}. - * } + * state mP1 { + * enter { log("mP1.enter"); } + * exit { log("mP1.exit"); } + * on msg { + * CMD_2 { + * send(CMD_3); + * defer(msg); + * transitonTo(mS2); + * return HANDLED; + * } + * return NOT_HANDLED; + * } * } * - * and interpreted as HierarchicalStateMachine Hsm1: - * - * mP1 a root state. - * processes message CMD_2 which sends CMD_3, defers CMD_2, and transitions to mS2 - * - * mS1 a child of mP1 is the initial state: - * processes message CMD_1 which transitions to itself and returns false to let mP1 handle it. + * INITIAL + * state mS1 parent mP1 { + * enter { log("mS1.enter"); } + * exit { log("mS1.exit"); } + * on msg { + * CMD_1 { + * transitionTo(mS1); + * return HANDLED; + * } + * return NOT_HANDLED; + * } + * } * - * mS2 a child of mP1: - * processes message CMD_2 which send CMD_4 - * processes message CMD_3 which defers CMD_3 and transitions to mP2 + * state mS2 parent mP1 { + * enter { log("mS2.enter"); } + * exit { log("mS2.exit"); } + * on msg { + * CMD_2 { + * send(CMD_4); + * return HANDLED; + * } + * CMD_3 { + * defer(msg); + * transitionTo(mP2); + * return HANDLED; + * } + * return NOT_HANDLED; + * } + * } * - * mP2 a root state. - * on enter it sends CMD_5 - * processes message CMD_3 - * processes message CMD_4 - * processes message CMD_5 which transitions to halt state + * state mP2 { + * enter { + * log("mP2.enter"); + * send(CMD_5); + * } + * exit { log("mP2.exit"); } + * on msg { + * CMD_3, CMD_4 { return HANDLED; } + * CMD_5 { + * transitionTo(HaltingState); + * return HANDLED; + * } + * return NOT_HANDLED; + * } + * } * * The implementation is below and also in HierarchicalStateMachineTest: @@ -271,11 +269,11 @@ class Hsm1 extends HierarchicalStateMachine { sendMessage(obtainMessage(CMD_3)); deferMessage(message); transitionTo(mS2); - retVal = true; + retVal = HANDLED; break; default: // Any message we don't understand in this state invokes unhandledMessage - retVal = false; + retVal = NOT_HANDLED; break; } return retVal; @@ -294,10 +292,10 @@ class Hsm1 extends HierarchicalStateMachine { if (message.what == CMD_1) { // Transition to ourself to show that enter/exit is called transitionTo(mS1); - return true; + return HANDLED; } else { // Let parent process all other messages - return false; + return NOT_HANDLED; } } @Override public void exit() { @@ -315,15 +313,15 @@ class Hsm1 extends HierarchicalStateMachine { switch(message.what) { case(CMD_2): sendMessage(obtainMessage(CMD_4)); - retVal = true; + retVal = HANDLED; break; case(CMD_3): deferMessage(message); transitionTo(mP2); - retVal = true; + retVal = HANDLED; break; default: - retVal = false; + retVal = NOT_HANDLED; break; } return retVal; @@ -349,7 +347,7 @@ class Hsm1 extends HierarchicalStateMachine { transitionToHaltingState(); break; } - return true; + return HANDLED; } @Override public void exit() { Log.d(TAG, "mP2.exit"); @@ -357,7 +355,7 @@ class Hsm1 extends HierarchicalStateMachine { } @Override - protected void halting() { + void halting() { Log.d(TAG, "halting"); synchronized (this) { this.notifyAll(); @@ -413,53 +411,32 @@ class Hsm1 extends HierarchicalStateMachine { * D/hsm1 ( 1999): mP2.exit * D/hsm1 ( 1999): halting * - * Here is the HSM a BNF grammar, this is a first stab at creating an - * HSM description language, suggestions corrections or alternatives - * would be much appreciated. - * - * Legend: - * {} ::= zero or more - * {}+ ::= one or more - * [] ::= zero or one - * () ::= define a group with "or" semantics. - * - * HSM EBNF: - * HSM = HSM_NAME "{" { STATE }+ "}" ; - * HSM_NAME = alpha_numeric_name ; - * STATE = INTRODUCE_STATE [ ENTER | [ ENTER EXIT ] "{" [ MESSAGES ] "}" [ EXIT ] ; - * INTRODUCE_STATE = { STATE_DEPTH }+ [ INITIAL_STATE_INDICATOR ] STATE_NAME ; - * STATE_DEPTH = "+" ; - * INITIAL_STATE_INDICATOR = "#" - * ENTER = "e(" SEND_ACTION | TRANSITION_ACTION | HALT_ACTION ")" ; - * MESSAGES = { MSG_LIST MESSAGE_ACTIONS } ; - * MSG_LIST = { MSG_NAME { "," MSG_NAME } }; - * EXIT = "x(" SEND_ACTION | TRANSITION_ACTION | HALT_ACTION ")" ; - * PROCESS_COMPLETION = PROCESS_IN_PARENT_OR_COMPLETE | PROCESS_COMPLETE ; - * SEND_ACTION = "$" MSG_NAME ; - * DEFER_ACTION = "%" MSG_NAME ; - * TRANSITION_ACTION = ">" STATE_NAME ; - * HALT_ACTION = ">" HALT ; - * MESSAGE_ACTIONS = { "{" ACTION_LIST "}" } [ PROCESS_COMPLETION ] ; - * ACTION_LIST = ACTION { (";" | "\n") ACTION } ; - * ACTION = IF_ACTION | SEND_ACTION | DEFER_ACTION | TRANSITION_ACTION | HALT_ACTION ; - * IF_ACTION = "if(" boolean_expression ")" "{" ACTION_LIST "}" - * PROCESS_IN_PARENT_OR_COMPLETE = "^" ; - * PROCESS_COMPLETE = "." ; - * STATE_NAME = alpha_numeric_name ; - * MSG_NAME = alpha_numeric_name | ALL_OTHER_MESSAGES ; - * ALL_OTHER_MESSAGES = "*" ; - * EXP = boolean_expression ; - * - * Idioms: - * * { %* }. ::= All other messages will be deferred. */ public class HierarchicalStateMachine { private static final String TAG = "HierarchicalStateMachine"; private String mName; + /** Message.what value when quitting */ public static final int HSM_QUIT_CMD = -1; + /** Message.what value when initializing */ + public static final int HSM_INIT_CMD = -1; + + /** + * Convenience constant that maybe returned by processMessage + * to indicate the the message was processed and is not to be + * processed by parent states + */ + public static final boolean HANDLED = true; + + /** + * Convenience constant that maybe returned by processMessage + * to indicate the the message was NOT processed and is to be + * processed by parent states + */ + public static final boolean NOT_HANDLED = false; + private static class HsmHandler extends Handler { /** The debug flag */ @@ -468,6 +445,12 @@ public class HierarchicalStateMachine { /** The quit object */ private static final Object mQuitObj = new Object(); + /** The initialization message */ + private static final Message mInitMsg = null; + + /** The current message */ + private Message mMsg; + /** A list of messages that this state machine has processed */ private ProcessedMessages mProcessedMessages = new ProcessedMessages(); @@ -550,8 +533,7 @@ public class HierarchicalStateMachine { private class QuittingState extends HierarchicalState { @Override public boolean processMessage(Message msg) { - // Ignore - return false; + return NOT_HANDLED; } } @@ -565,6 +547,9 @@ public class HierarchicalStateMachine { public final void handleMessage(Message msg) { if (mDbg) Log.d(TAG, "handleMessage: E msg.what=" + msg.what); + /** Save the current message */ + mMsg = msg; + /** * Check that construction was completed */ @@ -679,6 +664,7 @@ public class HierarchicalStateMachine { * starting at the first entry. */ mIsConstructionCompleted = true; + mMsg = obtainMessage(HSM_INIT_CMD); invokeEnterMethods(0); /** @@ -854,6 +840,13 @@ public class HierarchicalStateMachine { moveTempStateStackToStateStack(); } + /** + * @return current message + */ + private final Message getCurrentMessage() { + return mMsg; + } + /** * @return current state */ @@ -1025,6 +1018,14 @@ public class HierarchicalStateMachine { protected final void addState(HierarchicalState state, HierarchicalState parent) { mHsmHandler.addState(state, parent); } + + /** + * @return current message + */ + protected final Message getCurrentMessage() { + return mHsmHandler.getCurrentMessage(); + } + /** * @return current state */ @@ -1032,7 +1033,6 @@ public class HierarchicalStateMachine { return mHsmHandler.getCurrentState(); } - /** * Add a new state to the state machine, parent will be null * @param state to add diff --git a/core/java/com/android/internal/view/BaseSurfaceHolder.java b/core/java/com/android/internal/view/BaseSurfaceHolder.java index e0d3a5f87b2e4a578d5f5aa35ff130b502163286..3a0499359f572a777527033797a26346dc81775d 100644 --- a/core/java/com/android/internal/view/BaseSurfaceHolder.java +++ b/core/java/com/android/internal/view/BaseSurfaceHolder.java @@ -33,9 +33,11 @@ public abstract class BaseSurfaceHolder implements SurfaceHolder { public final ArrayList mCallbacks = new ArrayList(); - + SurfaceHolder.Callback[] mGottenCallbacks; + boolean mHaveGottenCallbacks; + public final ReentrantLock mSurfaceLock = new ReentrantLock(); - public final Surface mSurface = new Surface(); + public Surface mSurface = new Surface(); int mRequestedWidth = -1; int mRequestedHeight = -1; @@ -83,6 +85,31 @@ public abstract class BaseSurfaceHolder implements SurfaceHolder { } } + public SurfaceHolder.Callback[] getCallbacks() { + if (mHaveGottenCallbacks) { + return mGottenCallbacks; + } + + synchronized (mCallbacks) { + final int N = mCallbacks.size(); + if (N > 0) { + if (mGottenCallbacks == null || mGottenCallbacks.length != N) { + mGottenCallbacks = new SurfaceHolder.Callback[N]; + } + mCallbacks.toArray(mGottenCallbacks); + } else { + mGottenCallbacks = null; + } + mHaveGottenCallbacks = true; + } + + return mGottenCallbacks; + } + + public void ungetCallbacks() { + mHaveGottenCallbacks = false; + } + public void setFixedSize(int width, int height) { if (mRequestedWidth != width || mRequestedHeight != height) { mRequestedWidth = width; diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl index a05ff14bcccd6d3480b62114b1e1cf58fc0cb877..338dcaa7db96586a9d23048c585bb9677d49eecb 100644 --- a/core/java/com/android/internal/view/IInputMethodSession.aidl +++ b/core/java/com/android/internal/view/IInputMethodSession.aidl @@ -48,4 +48,6 @@ oneway interface IInputMethodSession { void appPrivateCommand(String action, in Bundle data); void toggleSoftInput(int showFlags, int hideFlags); + + void finishSession(); } diff --git a/core/java/com/android/internal/view/RootViewSurfaceTaker.java b/core/java/com/android/internal/view/RootViewSurfaceTaker.java new file mode 100644 index 0000000000000000000000000000000000000000..fcb1645458faef590c9d69d995267b5f6fae984c --- /dev/null +++ b/core/java/com/android/internal/view/RootViewSurfaceTaker.java @@ -0,0 +1,11 @@ +package com.android.internal.view; + +import android.view.SurfaceHolder; + +/** hahahah */ +public interface RootViewSurfaceTaker { + SurfaceHolder.Callback willYouTakeTheSurface(); + void setSurfaceType(int type); + void setSurfaceFormat(int format); + void setSurfaceKeepScreenOn(boolean keepOn); +} diff --git a/core/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java index 23e2277379a9330c1014ebf9ab4625b8c655173b..fa47ff638cd5154a9848cbae8b5e57673ea83aed 100644 --- a/core/java/com/android/internal/widget/DigitalClock.java +++ b/core/java/com/android/internal/widget/DigitalClock.java @@ -30,7 +30,7 @@ import android.provider.Settings; import android.text.format.DateFormat; import android.util.AttributeSet; import android.view.View; -import android.widget.RelativeLayout; +import android.widget.LinearLayout; import android.widget.TextView; import java.text.DateFormatSymbols; @@ -39,7 +39,7 @@ import java.util.Calendar; /** * Displays the time */ -public class DigitalClock extends RelativeLayout { +public class DigitalClock extends LinearLayout { private final static String M12 = "h:mm"; private final static String M24 = "kk:mm"; diff --git a/core/java/com/google/android/mms/ContentType.java b/core/java/com/google/android/mms/ContentType.java index 94bc9fdcd4bf7f19256a60c450e5ba58f9f8605b..b066fadae2f13faf9d86ac339936ef61fae20c71 100644 --- a/core/java/com/google/android/mms/ContentType.java +++ b/core/java/com/google/android/mms/ContentType.java @@ -26,6 +26,7 @@ public class ContentType { public static final String MMS_GENERIC = "application/vnd.wap.mms-generic"; public static final String MULTIPART_MIXED = "application/vnd.wap.multipart.mixed"; public static final String MULTIPART_RELATED = "application/vnd.wap.multipart.related"; + public static final String MULTIPART_ALTERNATIVE = "application/vnd.wap.multipart.alternative"; public static final String TEXT_PLAIN = "text/plain"; public static final String TEXT_HTML = "text/html"; diff --git a/core/java/com/google/android/mms/pdu/PduParser.java b/core/java/com/google/android/mms/pdu/PduParser.java index d465c5aafb3b94bfd478e11a8e8763239b0a41e2..1cd118b56ac623a40e7fbf04c7b46d329b451814 100644 --- a/core/java/com/google/android/mms/pdu/PduParser.java +++ b/core/java/com/google/android/mms/pdu/PduParser.java @@ -200,7 +200,18 @@ public class PduParser { PduHeaders headers = new PduHeaders(); while (keepParsing && (pduDataStream.available() > 0)) { + pduDataStream.mark(1); int headerField = extractByteValue(pduDataStream); + /* parse custom text header */ + if ((headerField >= TEXT_MIN) && (headerField <= TEXT_MAX)) { + pduDataStream.reset(); + byte [] bVal = parseWapString(pduDataStream, TYPE_TEXT_STRING); + if (LOCAL_LOGV) { + Log.v(LOG_TAG, "TextHeader: " + new String(bVal)); + } + /* we should ignore it at the moment */ + continue; + } switch (headerField) { case PduHeaders.MESSAGE_TYPE: { @@ -778,26 +789,34 @@ public class PduParser { /* get part's data */ if (dataLength > 0) { byte[] partData = new byte[dataLength]; + String partContentType = new String(part.getContentType()); pduDataStream.read(partData, 0, dataLength); - // Check Content-Transfer-Encoding. - byte[] partDataEncoding = part.getContentTransferEncoding(); - if (null != partDataEncoding) { - String encoding = new String(partDataEncoding); - if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) { - // Decode "base64" into "binary". - partData = Base64.decodeBase64(partData); - } else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) { - // Decode "quoted-printable" into "binary". - partData = QuotedPrintable.decodeQuotedPrintable(partData); - } else { - // "binary" is the default encoding. + if (partContentType.equalsIgnoreCase(ContentType.MULTIPART_ALTERNATIVE)) { + // parse "multipart/vnd.wap.multipart.alternative". + PduBody childBody = parseParts(new ByteArrayInputStream(partData)); + // take the first part of children. + part = childBody.getPart(0); + } else { + // Check Content-Transfer-Encoding. + byte[] partDataEncoding = part.getContentTransferEncoding(); + if (null != partDataEncoding) { + String encoding = new String(partDataEncoding); + if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) { + // Decode "base64" into "binary". + partData = Base64.decodeBase64(partData); + } else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) { + // Decode "quoted-printable" into "binary". + partData = QuotedPrintable.decodeQuotedPrintable(partData); + } else { + // "binary" is the default encoding. + } } + if (null == partData) { + log("Decode part data error!"); + return null; + } + part.setData(partData); } - if (null == partData) { - log("Decode part data error!"); - return null; - } - part.setData(partData); } /* add this part to body */ diff --git a/core/jni/Android.mk b/core/jni/Android.mk index a39d06b6c62c141664e7d992c7573e138f6064c9..dbad7e98b1fdf18f4115d7e259841c4ed25d2e6b 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -28,6 +28,7 @@ LOCAL_SRC_FILES:= \ Time.cpp \ com_google_android_gles_jni_EGLImpl.cpp \ com_google_android_gles_jni_GLImpl.cpp.arm \ + android_app_NativeActivity.cpp \ android_opengl_GLES10.cpp \ android_opengl_GLES10Ext.cpp \ android_opengl_GLES11.cpp \ @@ -50,6 +51,7 @@ LOCAL_SRC_FILES:= \ android_os_Debug.cpp \ android_os_FileUtils.cpp \ android_os_MemoryFile.cpp \ + android_os_MessageQueue.cpp \ android_os_ParcelFileDescriptor.cpp \ android_os_Power.cpp \ android_os_StatFs.cpp \ @@ -122,7 +124,6 @@ LOCAL_SRC_FILES:= \ android_server_BluetoothA2dpService.cpp \ android_message_digest_sha1.cpp \ android_ddm_DdmHandleNativeHeap.cpp \ - android_location_GpsLocationProvider.cpp \ com_android_internal_os_ZygoteInit.cpp \ com_android_internal_graphics_NativeUtils.cpp \ android_backup_BackupDataInput.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 9fbf1718dbc80975ed153d5a77ed505e32bb7ef4..76df9dbae13e555e3df7d93343550ee75c4f3178 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -128,6 +128,7 @@ extern int register_android_nio_utils(JNIEnv* env); extern int register_android_pim_EventRecurrence(JNIEnv* env); extern int register_android_text_format_Time(JNIEnv* env); extern int register_android_os_Debug(JNIEnv* env); +extern int register_android_os_MessageQueue(JNIEnv* env); extern int register_android_os_ParcelFileDescriptor(JNIEnv *env); extern int register_android_os_Power(JNIEnv *env); extern int register_android_os_StatFs(JNIEnv *env); @@ -155,11 +156,11 @@ extern int register_android_server_BluetoothEventLoop(JNIEnv *env); extern int register_android_server_BluetoothA2dpService(JNIEnv* env); extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env); extern int register_com_android_internal_os_ZygoteInit(JNIEnv* env); -extern int register_android_location_GpsLocationProvider(JNIEnv* env); extern int register_android_backup_BackupDataInput(JNIEnv *env); extern int register_android_backup_BackupDataOutput(JNIEnv *env); extern int register_android_backup_FileBackupHelperBase(JNIEnv *env); extern int register_android_backup_BackupHelperDispatcher(JNIEnv *env); +extern int register_android_app_NativeActivity(JNIEnv *env); static AndroidRuntime* gCurRuntime = NULL; @@ -1249,6 +1250,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_os_Debug), REG_JNI(register_android_os_FileObserver), REG_JNI(register_android_os_FileUtils), + REG_JNI(register_android_os_MessageQueue), REG_JNI(register_android_os_ParcelFileDescriptor), REG_JNI(register_android_os_Power), REG_JNI(register_android_os_StatFs), @@ -1278,11 +1280,12 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_server_BluetoothA2dpService), REG_JNI(register_android_message_digest_sha1), REG_JNI(register_android_ddm_DdmHandleNativeHeap), - REG_JNI(register_android_location_GpsLocationProvider), REG_JNI(register_android_backup_BackupDataInput), REG_JNI(register_android_backup_BackupDataOutput), REG_JNI(register_android_backup_FileBackupHelperBase), REG_JNI(register_android_backup_BackupHelperDispatcher), + + REG_JNI(register_android_app_NativeActivity), }; /* diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2ab134bfc8bc659d36e91aefcb32425dde3eaa9 --- /dev/null +++ b/core/jni/android_app_NativeActivity.cpp @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2010 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. + */ + +#define LOG_TAG "NativeActivity" +#include + +#include "JNIHelp.h" +#include +#include + +#include + +namespace android +{ + +struct NativeCode { + NativeCode(void* _dlhandle, android_activity_create_t* _createFunc) { + memset(&activity, sizeof(activity), 0); + memset(&callbacks, sizeof(callbacks), 0); + dlhandle = _dlhandle; + createActivityFunc = _createFunc; + surface = NULL; + } + + ~NativeCode() { + if (callbacks.onDestroy != NULL) { + callbacks.onDestroy(&activity); + } + if (dlhandle != NULL) { + dlclose(dlhandle); + } + } + + void setSurface(jobject _surface) { + if (surface != NULL) { + activity.env->DeleteGlobalRef(surface); + } + if (_surface != NULL) { + surface = activity.env->NewGlobalRef(_surface); + } else { + surface = NULL; + } + } + + android_activity_t activity; + android_activity_callbacks_t callbacks; + + void* dlhandle; + android_activity_create_t* createActivityFunc; + + jobject surface; +}; + +static jint +loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path) +{ + const char* pathStr = env->GetStringUTFChars(path, NULL); + NativeCode* code = NULL; + + void* handle = dlopen(pathStr, RTLD_LAZY); + + env->ReleaseStringUTFChars(path, pathStr); + + if (handle != NULL) { + code = new NativeCode(handle, (android_activity_create_t*) + dlsym(handle, "android_onCreateActivity")); + if (code->createActivityFunc == NULL) { + LOGW("android_onCreateActivity not found"); + delete code; + return 0; + } + code->activity.callbacks = &code->callbacks; + code->activity.env = env; + code->activity.clazz = clazz; + code->createActivityFunc(&code->activity, NULL, 0); + } + + return (jint)code; +} + +static void +unloadNativeCode_native(JNIEnv* env, jobject clazz, jint handle) +{ + if (handle != 0) { + NativeCode* code = (NativeCode*)handle; + delete code; + } +} + +static void +onStart_native(JNIEnv* env, jobject clazz, jint handle) +{ + if (handle != 0) { + NativeCode* code = (NativeCode*)handle; + if (code->callbacks.onStart != NULL) { + code->callbacks.onStart(&code->activity); + } + } +} + +static void +onResume_native(JNIEnv* env, jobject clazz, jint handle) +{ + if (handle != 0) { + NativeCode* code = (NativeCode*)handle; + if (code->callbacks.onResume != NULL) { + code->callbacks.onResume(&code->activity); + } + } +} + +static void +onSaveInstanceState_native(JNIEnv* env, jobject clazz, jint handle) +{ + if (handle != 0) { + NativeCode* code = (NativeCode*)handle; + if (code->callbacks.onSaveInstanceState != NULL) { + size_t len = 0; + code->callbacks.onSaveInstanceState(&code->activity, &len); + } + } +} + +static void +onPause_native(JNIEnv* env, jobject clazz, jint handle) +{ + if (handle != 0) { + NativeCode* code = (NativeCode*)handle; + if (code->callbacks.onPause != NULL) { + code->callbacks.onPause(&code->activity); + } + } +} + +static void +onStop_native(JNIEnv* env, jobject clazz, jint handle) +{ + if (handle != 0) { + NativeCode* code = (NativeCode*)handle; + if (code->callbacks.onStop != NULL) { + code->callbacks.onStop(&code->activity); + } + } +} + +static void +onLowMemory_native(JNIEnv* env, jobject clazz, jint handle) +{ + if (handle != 0) { + NativeCode* code = (NativeCode*)handle; + if (code->callbacks.onLowMemory != NULL) { + code->callbacks.onLowMemory(&code->activity); + } + } +} + +static void +onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jint handle, jboolean focused) +{ + if (handle != 0) { + NativeCode* code = (NativeCode*)handle; + if (code->callbacks.onWindowFocusChanged != NULL) { + code->callbacks.onWindowFocusChanged(&code->activity, focused ? 1 : 0); + } + } +} + +static void +onSurfaceCreated_native(JNIEnv* env, jobject clazz, jint handle, jobject surface) +{ + if (handle != 0) { + NativeCode* code = (NativeCode*)handle; + code->setSurface(surface); + if (code->callbacks.onSurfaceCreated != NULL) { + code->callbacks.onSurfaceCreated(&code->activity, + (android_surface_t*)code->surface); + } + } +} + +static void +onSurfaceChanged_native(JNIEnv* env, jobject clazz, jint handle, jobject surface, + jint format, jint width, jint height) +{ + if (handle != 0) { + NativeCode* code = (NativeCode*)handle; + if (code->surface != NULL && code->callbacks.onSurfaceChanged != NULL) { + code->callbacks.onSurfaceChanged(&code->activity, + (android_surface_t*)code->surface, format, width, height); + } + } +} + +static void +onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject surface) +{ + if (handle != 0) { + NativeCode* code = (NativeCode*)handle; + if (code->surface != NULL && code->callbacks.onSurfaceDestroyed != NULL) { + code->callbacks.onSurfaceDestroyed(&code->activity, + (android_surface_t*)code->surface); + } + code->setSurface(NULL); + } +} + +static const JNINativeMethod g_methods[] = { + { "loadNativeCode", "(Ljava/lang/String;)I", (void*)loadNativeCode_native }, + { "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native }, + { "onStartNative", "(I)V", (void*)onStart_native }, + { "onResumeNative", "(I)V", (void*)onResume_native }, + { "onSaveInstanceStateNative", "(I)V", (void*)onSaveInstanceState_native }, + { "onPauseNative", "(I)V", (void*)onPause_native }, + { "onStopNative", "(I)V", (void*)onStop_native }, + { "onLowMemoryNative", "(I)V", (void*)onLowMemory_native }, + { "onWindowFocusChangedNative", "(IZ)V", (void*)onWindowFocusChanged_native }, + { "onSurfaceCreatedNative", "(ILandroid/view/SurfaceHolder;)V", (void*)onSurfaceCreated_native }, + { "onSurfaceChangedNative", "(ILandroid/view/SurfaceHolder;III)V", (void*)onSurfaceChanged_native }, + { "onSurfaceDestroyedNative", "(ILandroid/view/SurfaceHolder;)V", (void*)onSurfaceDestroyed_native }, +}; + +static const char* const kNativeActivityPathName = "android/app/NativeActivity"; + +int register_android_app_NativeActivity(JNIEnv* env) +{ + //LOGD("register_android_app_NativeActivity"); + + jclass clazz; + + clazz = env->FindClass(kNativeActivityPathName); + LOG_FATAL_IF(clazz == NULL, "Unable to find class android.app.NativeActivity"); + + return AndroidRuntime::registerNativeMethods( + env, kNativeActivityPathName, + g_methods, NELEM(g_methods)); +} + +} diff --git a/core/jni/android_bluetooth_HeadsetBase.cpp b/core/jni/android_bluetooth_HeadsetBase.cpp index b0b0cb8200fd794e5180442eea77b286aa04fcab..5593a26b00f821ad44d778e2b3588fc643030de0 100644 --- a/core/jni/android_bluetooth_HeadsetBase.cpp +++ b/core/jni/android_bluetooth_HeadsetBase.cpp @@ -169,7 +169,7 @@ again: // never receive non-ASCII UTF-8). // This was added because of the BMW 2005 E46 which sends binary junk. if (is_ascii(buf)) { - LOG(LOG_INFO, "Bluetooth AT recv", buf); + LOG(LOG_INFO, "Bluetooth AT recv", "%s", buf); } else { LOGW("Ignoring invalid AT command: %s", buf); buf[0] = NULL; @@ -494,7 +494,7 @@ static void pretty_log_urc(const char *urc) { } } } - LOG(LOG_INFO, "Bluetooth AT sent", buf); + LOG(LOG_INFO, "Bluetooth AT sent", "%s", buf); free(buf); } diff --git a/core/jni/android_bluetooth_common.cpp b/core/jni/android_bluetooth_common.cpp index 343fa53904af04dc1c605c258c8719bff179a114..9a8f1b8881f1cbc7fe831493e8e183daebbac274 100644 --- a/core/jni/android_bluetooth_common.cpp +++ b/core/jni/android_bluetooth_common.cpp @@ -65,6 +65,7 @@ static Properties adapter_properties[] = { {"PairableTimeout", DBUS_TYPE_UINT32}, {"Discovering", DBUS_TYPE_BOOLEAN}, {"Devices", DBUS_TYPE_ARRAY}, + {"UUIDs", DBUS_TYPE_ARRAY}, }; typedef union { diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index b85466b5925d69c8dfc3c22190b04808d5be7ba9..c363156064955c0163441eb69fb4d5af7bfe5ed4 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -288,10 +288,16 @@ void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env) } } +static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz) +{ + return Camera::getNumberOfCameras(); +} + // connect to camera service -static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) +static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, + jobject weak_this, jint cameraId) { - sp camera = Camera::connect(); + sp camera = Camera::connect(cameraId); if (camera == NULL) { jniThrowException(env, "java/lang/RuntimeException", @@ -566,8 +572,11 @@ static void android_hardware_Camera_setDisplayOrientation(JNIEnv *env, jobject t //------------------------------------------------- static JNINativeMethod camMethods[] = { + { "getNumberOfCameras", + "()I", + (void *)android_hardware_Camera_getNumberOfCameras }, { "native_setup", - "(Ljava/lang/Object;)V", + "(Ljava/lang/Object;I)V", (void*)android_hardware_Camera_native_setup }, { "native_release", "()V", @@ -659,7 +668,7 @@ int register_android_hardware_Camera(JNIEnv *env) { field fields_to_find[] = { { "android/hardware/Camera", "mNativeContext", "I", &fields.context }, - { "android/view/Surface", "mSurface", "I", &fields.surface } + { "android/view/Surface", ANDROID_VIEW_SURFACE_JNI_ID, "I", &fields.surface } }; if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0) diff --git a/core/jni/android_os_MessageQueue.cpp b/core/jni/android_os_MessageQueue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8984057423be708db300b18a800f0cb769408c3d --- /dev/null +++ b/core/jni/android_os_MessageQueue.cpp @@ -0,0 +1,338 @@ +/* + * Copyright (C) 2010 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. + */ + +#define LOG_TAG "MQNative" + +#include "JNIHelp.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace android; + +// ---------------------------------------------------------------------------- + +static struct { + jclass mClass; + + jfieldID mObject; // native object attached to the DVM MessageQueue +} gMessageQueueOffsets; + +static struct { + jclass mClass; + jmethodID mConstructor; +} gKeyEventOffsets; + +// TODO: also MotionEvent offsets etc. a la gKeyEventOffsets + +static struct { + jclass mClass; + jmethodID mObtain; // obtain(Handler h, int what, Object obj) +} gMessageOffsets; + +// ---------------------------------------------------------------------------- + +static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL) +{ + if (jniThrowException(env, exc, msg) != 0) + assert(false); +} + +// ---------------------------------------------------------------------------- + +class MessageQueueNative { +public: + MessageQueueNative(int readSocket, int writeSocket); + ~MessageQueueNative(); + + // select on all FDs until the designated time; forever if wakeupTime is < 0 + int waitForSignal(jobject mqueue, jlong wakeupTime); + + // signal the queue-ready pipe + void signalQueuePipe(); + + // Specify a new input pipe, passing in responsibility for the socket fd and + // ashmem region + int registerInputPipe(JNIEnv* env, int socketFd, int memRegionFd, jobject handler); + + // Forget about this input pipe, closing the socket and ashmem region as well + int unregisterInputPipe(JNIEnv* env, int socketFd); + + size_t numRegisteredPipes() const { return mInputPipes.size(); } + +private: + struct InputPipe { + int fd; + int region; + jobject handler; + + InputPipe() {} + InputPipe(int _fd, int _r, jobject _h) : fd(_fd), region(_r), handler(_h) {} + }; + + // consume an event from a socket, put it on the DVM MessageQueue indicated, + // and notify the other end of the pipe that we've consumed it. + void queueEventFromPipe(const InputPipe& pipe, jobject mqueue); + + int mQueueReadFd, mQueueWriteFd; + Vector mInputPipes; +}; + +MessageQueueNative::MessageQueueNative(int readSocket, int writeSocket) + : mQueueReadFd(readSocket), mQueueWriteFd(writeSocket) { +} + +MessageQueueNative::~MessageQueueNative() { +} + +int MessageQueueNative::waitForSignal(jobject mqueue, jlong timeoutMillis) { + struct timeval tv, *timeout; + fd_set fdset; + + if (timeoutMillis < 0) { + timeout = NULL; + } else { + if (timeoutMillis == 0) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } else { + tv.tv_sec = (timeoutMillis / 1000); + tv.tv_usec = (timeoutMillis - (1000 * tv.tv_sec)) * 1000; + } + timeout = &tv; + } + + // always rebuild the fd set from scratch + FD_ZERO(&fdset); + + // the queue signalling pipe + FD_SET(mQueueReadFd, &fdset); + int maxFd = mQueueReadFd; + + // and the input sockets themselves + for (size_t i = 0; i < mInputPipes.size(); i++) { + FD_SET(mInputPipes[i].fd, &fdset); + if (maxFd < mInputPipes[i].fd) { + maxFd = mInputPipes[i].fd; + } + } + + // now wait + int res = select(maxFd + 1, &fdset, NULL, NULL, timeout); + + // Error? Just return it and bail + if (res < 0) return res; + + // What happened -- timeout or actual data arrived? + if (res == 0) { + // select() returned zero, which means we timed out, which means that it's time + // to deliver the head element that was already on the queue. Just fall through + // without doing anything else. + } else { + // Data (or a queue signal) arrived! + // + // If it's data, pull the data off the pipe, build a new Message with it, put it on + // the DVM-side MessageQueue (pointed to by the 'mqueue' parameter), then proceed + // into the queue-signal case. + // + // If a queue signal arrived, just consume any data pending in that pipe and + // fall out. + bool queue_signalled = (FD_ISSET(mQueueReadFd, &fdset) != 0); + + for (size_t i = 0; i < mInputPipes.size(); i++) { + if (FD_ISSET(mInputPipes[i].fd, &fdset)) { + queueEventFromPipe(mInputPipes[i], mqueue); + queue_signalled = true; // we know a priori that queueing the event does this + } + } + + // Okay, stuff went on the queue. Consume the contents of the signal pipe + // now that we're awake and about to start dispatching messages again. + if (queue_signalled) { + uint8_t buf[16]; + ssize_t nRead; + do { + nRead = read(mQueueReadFd, buf, sizeof(buf)); + } while (nRead > 0); // in nonblocking mode we'll get -1 when it's drained + } + } + + return 0; +} + +// signals to the queue pipe are one undefined byte. it's just a "data has arrived" token +// and the pipe is drained on receipt of at least one signal +void MessageQueueNative::signalQueuePipe() { + int dummy[1]; + write(mQueueWriteFd, dummy, 1); +} + +void MessageQueueNative::queueEventFromPipe(const InputPipe& inPipe, jobject mqueue) { + // !!! TODO: read the event data from the InputPipe's ashmem region, convert it to a DVM + // event object of the proper type [MotionEvent or KeyEvent], create a Message holding + // it as appropriate, point the Message to the Handler associated with this InputPipe, + // and call up to the DVM MessageQueue implementation to enqueue it for delivery. +} + +// the number of registered pipes on success; < 0 on error +int MessageQueueNative::registerInputPipe(JNIEnv* env, + int socketFd, int memRegionFd, jobject handler) { + // make sure this fd is not already known to us + for (size_t i = 0; i < mInputPipes.size(); i++) { + if (mInputPipes[i].fd == socketFd) { + LOGE("Attempt to re-register input fd %d", socketFd); + return -1; + } + } + + mInputPipes.push( InputPipe(socketFd, memRegionFd, env->NewGlobalRef(handler)) ); + return mInputPipes.size(); +} + +// Remove an input pipe from our bookkeeping. Also closes the socket and ashmem +// region file descriptor! +// +// returns the number of remaining input pipes on success; < 0 on error +int MessageQueueNative::unregisterInputPipe(JNIEnv* env, int socketFd) { + for (size_t i = 0; i < mInputPipes.size(); i++) { + if (mInputPipes[i].fd == socketFd) { + close(mInputPipes[i].fd); + close(mInputPipes[i].region); + env->DeleteGlobalRef(mInputPipes[i].handler); + mInputPipes.removeAt(i); + return mInputPipes.size(); + } + } + LOGW("Tried to unregister input pipe %d but not found!", socketFd); + return -1; +} + +// ---------------------------------------------------------------------------- + +namespace android { + +static void android_os_MessageQueue_init(JNIEnv* env, jobject obj) { + // Create the pipe + int fds[2]; + int err = socketpair(AF_LOCAL, SOCK_STREAM, 0, fds); + if (err != 0) { + doThrow(env, "java/lang/RuntimeException", "Unable to create socket pair"); + } + + MessageQueueNative *mqn = new MessageQueueNative(fds[0], fds[1]); + if (mqn == NULL) { + close(fds[0]); + close(fds[1]); + doThrow(env, "java/lang/RuntimeException", "Unable to allocate native queue"); + } + + int flags = fcntl(fds[0], F_GETFL); + fcntl(fds[0], F_SETFL, flags | O_NONBLOCK); + flags = fcntl(fds[1], F_GETFL); + fcntl(fds[1], F_SETFL, flags | O_NONBLOCK); + + env->SetIntField(obj, gMessageQueueOffsets.mObject, (jint)mqn); +} + +static void android_os_MessageQueue_signal(JNIEnv* env, jobject obj) { + MessageQueueNative *mqn = (MessageQueueNative*) env->GetIntField(obj, gMessageQueueOffsets.mObject); + if (mqn != NULL) { + mqn->signalQueuePipe(); + } else { + doThrow(env, "java/lang/IllegalStateException", "Queue not initialized"); + } +} + +static int android_os_MessageQueue_waitForNext(JNIEnv* env, jobject obj, jlong when) { + MessageQueueNative *mqn = (MessageQueueNative*) env->GetIntField(obj, gMessageQueueOffsets.mObject); + if (mqn != NULL) { + int res = mqn->waitForSignal(obj, when); + return res; // the DVM event, if any, has been constructed and queued now + } + + return -1; +} + +static void android_os_MessageQueue_registerInputStream(JNIEnv* env, jobject obj, + jint socketFd, jint regionFd, jobject handler) { + MessageQueueNative *mqn = (MessageQueueNative*) env->GetIntField(obj, gMessageQueueOffsets.mObject); + if (mqn != NULL) { + mqn->registerInputPipe(env, socketFd, regionFd, handler); + } else { + doThrow(env, "java/lang/IllegalStateException", "Queue not initialized"); + } +} + +static void android_os_MessageQueue_unregisterInputStream(JNIEnv* env, jobject obj, + jint socketFd) { + MessageQueueNative *mqn = (MessageQueueNative*) env->GetIntField(obj, gMessageQueueOffsets.mObject); + if (mqn != NULL) { + mqn->unregisterInputPipe(env, socketFd); + } else { + doThrow(env, "java/lang/IllegalStateException", "Queue not initialized"); + } +} + +// ---------------------------------------------------------------------------- + +const char* const kKeyEventPathName = "android/view/KeyEvent"; +const char* const kMessagePathName = "android/os/Message"; +const char* const kMessageQueuePathName = "android/os/MessageQueue"; + +static JNINativeMethod gMessageQueueMethods[] = { + /* name, signature, funcPtr */ + { "nativeInit", "()V", (void*)android_os_MessageQueue_init }, + { "nativeSignal", "()V", (void*)android_os_MessageQueue_signal }, + { "nativeWaitForNext", "(J)I", (void*)android_os_MessageQueue_waitForNext }, + { "nativeRegisterInputStream", "(IILandroid/os/Handler;)V", (void*)android_os_MessageQueue_registerInputStream }, + { "nativeUnregisterInputStream", "(I)V", (void*)android_os_MessageQueue_unregisterInputStream }, +}; + +int register_android_os_MessageQueue(JNIEnv* env) { + jclass clazz; + + clazz = env->FindClass(kMessageQueuePathName); + LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.MessageQueue"); + gMessageQueueOffsets.mClass = (jclass) env->NewGlobalRef(clazz); + gMessageQueueOffsets.mObject = env->GetFieldID(clazz, "mObject", "I"); + assert(gMessageQueueOffsets.mObject); + + clazz = env->FindClass(kMessagePathName); + LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Message"); + gMessageOffsets.mClass = (jclass) env->NewGlobalRef(clazz); + gMessageOffsets.mObtain = env->GetStaticMethodID(clazz, "obtain", + "(Landroid/os/Handler;ILjava/lang/Object;)Landroid/os/Message;"); + assert(gMessageOffsets.mObtain); + + clazz = env->FindClass(kKeyEventPathName); + LOG_FATAL_IF(clazz == NULL, "Unable to find class android.view.KeyEvent"); + gKeyEventOffsets.mClass = (jclass) env->NewGlobalRef(clazz); + gKeyEventOffsets.mConstructor = env->GetMethodID(clazz, "", "(JJIIIIIII)V"); + assert(gKeyEventOffsets.mConstructor); + + return AndroidRuntime::registerNativeMethods(env, kMessageQueuePathName, + gMessageQueueMethods, NELEM(gMessageQueueMethods)); +} + + +}; // end of namespace android diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index a2b7cc4d1104f87fd82a7aa710beeb06b62a865a..b7d0c67d755526d9cd7365b08c98dea929f88508 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -1504,8 +1504,7 @@ static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* } jobjectArray array = env->NewObjectArray(N, cls, NULL); - if (array == NULL) { - doThrow(env, "java/lang/OutOfMemoryError"); + if (env->ExceptionCheck()) { res.unlockBag(startOfBag); return NULL; } @@ -1533,15 +1532,23 @@ static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* } else { const char16_t* str16 = pool->stringAt(value.data, &strLen); str = env->NewString(str16, strLen); - if (str == NULL) { - doThrow(env, "java/lang/OutOfMemoryError"); - res.unlockBag(startOfBag); - return NULL; - } + } + + // If one of our NewString{UTF} calls failed due to memory, an + // exception will be pending. + if (env->ExceptionCheck()) { + res.unlockBag(startOfBag); + return NULL; } } env->SetObjectArrayElement(array, i, str); + + // If we have a large amount of strings in our array, we might + // overflow the local reference table of the VM. + if (str != NULL) { + env->DeleteLocalRef(str); + } } res.unlockBag(startOfBag); return array; diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 788374b6fa3a5c20ac0ef6da7fd62cda3c3b9e08..838ef22ff4f8c83a5b55c248cceecd3e03957b39 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -19,6 +19,7 @@ #include "android_util_Binder.h" #include +#include #include #include @@ -332,7 +333,7 @@ static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect) SkRegion clipReg; if (dirtyRegion.isRect()) { // very common case - const Rect& b(dirtyRegion.getBounds()); + const Rect b(dirtyRegion.getBounds()); clipReg.setRect(b.left, b.top, b.right, b.bottom); } else { size_t count; @@ -680,7 +681,7 @@ static JNINativeMethod gSurfaceMethods[] = { void nativeClassInit(JNIEnv* env, jclass clazz) { - so.surface = env->GetFieldID(clazz, "mSurface", "I"); + so.surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I"); so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I"); so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I"); so.canvas = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;"); diff --git a/core/jni/android_view_ViewRoot.cpp b/core/jni/android_view_ViewRoot.cpp index 9d62d895927e19bf24fca4e6cdcc08bbd0479463..70ad8c5fa4b8e18566573c2e97b1733b11c3f9c3 100644 --- a/core/jni/android_view_ViewRoot.cpp +++ b/core/jni/android_view_ViewRoot.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -24,6 +25,7 @@ #include "GraphicsJNI.h" #include "jni.h" +#include #include #include @@ -78,6 +80,39 @@ static void android_view_ViewRoot_abandonGlCaches(JNIEnv* env, jobject) { SkGLCanvas::AbandonAllTextures(); } +static jintArray android_view_ViewRoot_makeInputChannel(JNIEnv* env, jobject) { + int fd[2]; + jint* arrayData = NULL; + + // Create the pipe + int err = socketpair(AF_LOCAL, SOCK_STREAM, 0, fd); + if (err != 0) { + fprintf(stderr, "socketpair() failed: %d\n", errno); + doThrow(env, "java/lang/RuntimeException", "Unable to create pipe"); + return NULL; + } + + // Set up the return array + jintArray array = env->NewIntArray(2); + if (env->ExceptionCheck()) { + fprintf(stderr, "Exception allocating fd array"); + goto bail; + } + + arrayData = env->GetIntArrayElements(array, 0); + arrayData[0] = fd[0]; + arrayData[1] = fd[1]; + env->ReleaseIntArrayElements(array, arrayData, 0); + + return array; + +bail: + env->DeleteLocalRef(array); + close(fd[0]); + close(fd[1]); + return NULL; +} + // ---------------------------------------------------------------------------- const char* const kClassPathName = "android/view/ViewRoot"; @@ -86,7 +121,9 @@ static JNINativeMethod gMethods[] = { { "nativeShowFPS", "(Landroid/graphics/Canvas;I)V", (void*)android_view_ViewRoot_showFPS }, { "nativeAbandonGlCaches", "()V", - (void*)android_view_ViewRoot_abandonGlCaches } + (void*)android_view_ViewRoot_abandonGlCaches }, + { "makeInputChannel", "()[I", + (void*)android_view_ViewRoot_makeInputChannel } }; int register_android_view_ViewRoot(JNIEnv* env) { diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp index 6a8c4b9281cc6869998f364a7b05cf384c6822f1..01a15047091afb9b7903a9c681255053c098f997 100644 --- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp +++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp @@ -96,7 +96,7 @@ static void nativeClassInit(JNIEnv *_env, jclass eglImplClass) gConfig_EGLConfigFieldID = _env->GetFieldID(gConfig_class, "mEGLConfig", "I"); jclass surface_class = _env->FindClass("android/view/Surface"); - gSurface_SurfaceFieldID = _env->GetFieldID(surface_class, "mSurface", "I"); + gSurface_SurfaceFieldID = _env->GetFieldID(surface_class, ANDROID_VIEW_SURFACE_JNI_ID, "I"); jclass bitmap_class = _env->FindClass("android/graphics/Bitmap"); gBitmap_NativeBitmapFieldID = _env->GetFieldID(bitmap_class, "mNativeBitmap", "I"); diff --git a/core/res/res/drawable-hdpi/status_bar_background.png b/core/res/res/drawable-hdpi/status_bar_background.png index e6a865a786881b7c7d5fdde71ca7ebc2074695a5..3d00cd0f9a5e6c84fd10e3228a87d8639abc7166 100644 Binary files a/core/res/res/drawable-hdpi/status_bar_background.png and b/core/res/res/drawable-hdpi/status_bar_background.png differ diff --git a/core/res/res/drawable-hdpi/status_bar_close_on.9.png b/core/res/res/drawable-hdpi/status_bar_close_on.9.png index 5acf638489a033ce1860e51cbe56d183b1d53d3a..f313ffba57692f41703eb03a9b165282b2a3a033 100644 Binary files a/core/res/res/drawable-hdpi/status_bar_close_on.9.png and b/core/res/res/drawable-hdpi/status_bar_close_on.9.png differ diff --git a/core/res/res/drawable-hdpi/status_bar_header_background.9.png b/core/res/res/drawable-hdpi/status_bar_header_background.9.png index be36ff26bb8a969ed3fcf060a38c83253c689283..37b5fef592d1dda99f689aaecc47136b63c3864c 100644 Binary files a/core/res/res/drawable-hdpi/status_bar_header_background.9.png and b/core/res/res/drawable-hdpi/status_bar_header_background.9.png differ diff --git a/core/res/res/drawable-hdpi/statusbar_background.9.png b/core/res/res/drawable-hdpi/statusbar_background.9.png index dcca6951d3aec372246a84180beaab77740672db..a4be298796632accec380d660b1ff1589d920515 100644 Binary files a/core/res/res/drawable-hdpi/statusbar_background.9.png and b/core/res/res/drawable-hdpi/statusbar_background.9.png differ diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml index 200a1b294c0b3aa2af6ea495adf6420825824dc1..6edbdf9300d99ecfa3578a10eded2d9335cc9338 100644 --- a/core/res/res/layout/keyguard_screen_tab_unlock.xml +++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml @@ -41,7 +41,6 @@ android:ellipsize="marquee" android:gravity="right|bottom" android:textAppearance="?android:attr/textAppearanceMedium" - android:textSize="22sp" /> @@ -65,7 +64,7 @@ android:layout_below="@id/carrier" android:layout_marginTop="52dip" android:layout_marginLeft="20dip" - android:paddingBottom="8dip" + android:layout_marginBottom="8dip" > @@ -66,7 +65,7 @@ android:layout_height="wrap_content" android:layout_below="@id/carrier" android:layout_marginTop="56dip" - android:paddingBottom="8dip" + android:layout_marginBottom="8dip" > - + /> + /> diff --git a/core/res/res/layout/status_bar_expanded.xml b/core/res/res/layout/status_bar_expanded.xml index 30138a742c74dcf46f8c848c328e32cfb7919233..68eb9222bb4b448914994477b97890b7258f371b 100644 --- a/core/res/res/layout/status_bar_expanded.xml +++ b/core/res/res/layout/status_bar_expanded.xml @@ -48,7 +48,7 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textAppearance="?android:attr/textAppearanceLarge" - android:textColor="?android:attr/textColorSecondaryInverse" + android:textColor="?android:attr/textColorSecondary" android:paddingLeft="4dp" /> @@ -67,7 +67,7 @@ android:layout_marginTop="4dp" android:layout_marginBottom="1dp" android:textSize="14sp" - android:textColor="#ff000000" + android:textColor="?android:attr/textColorPrimaryInverse" android:text="@string/status_bar_clear_all_button" style="?android:attr/buttonStyle" android:paddingLeft="15dp" @@ -99,7 +99,7 @@ android:layout_height="wrap_content" android:background="@drawable/title_bar_portrait" android:paddingLeft="5dp" - android:textAppearance="@style/TextAppearance.StatusBarTitle" + android:textAppearance="@style/TextAppearance.StatusBar.Title" android:text="@string/status_bar_no_notifications_title" /> @@ -108,7 +108,7 @@ android:layout_height="wrap_content" android:background="@drawable/title_bar_portrait" android:paddingLeft="5dp" - android:textAppearance="@style/TextAppearance.StatusBarTitle" + android:textAppearance="@style/TextAppearance.StatusBar.Title" android:text="@string/status_bar_ongoing_events_title" /> + /> + /> diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml index 4672c0ed7ca47337051a1eefc3dd07c04f48d011..a0bc5b36923f5d88d4bbc98645d29340d187d434 100644 --- a/core/res/res/values/arrays.xml +++ b/core/res/res/values/arrays.xml @@ -128,11 +128,11 @@ phone_evdo_signal data_connection cdma_eri + wifi tty volume mute speakerphone - wifi tty bluetooth gps diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml old mode 100644 new mode 100755 index 6d6c47f3b3d056d558d9d5d81b8087d5598a8a93..8d4fa4eebcaea13f1b13e4e4dc9db082ec57f2df --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -916,6 +916,10 @@ + + + + diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index ed7447c71516a12292bd02e706b9c942c13e8131..b4c4811bec726a6b56fdfa35f898b21d5d98c955 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -62,6 +62,22 @@ a reference to a Drawable resource containing the image definition. --> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 86bfe94cbf8f772447ce12525cc147aba1281f29..1e007d3654c075234b6f8b2483298cd2cf6996ed 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -60,6 +60,10 @@ Connection problem or invalid MMI code. + + Operation is restricted to fixed dialing numbers only. + Service was enabled. - + + + + + + diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml index c318577ff91a60c8dc80cadd11f067416b425efa..548099397c3bd1fa994eb83241032e726bf0d414 100644 --- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml +++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml @@ -24,17 +24,19 @@ + android:label="@string/app_name"> - + + + ConnectivityManagerTest + diff --git a/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java b/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java index 89b3fb61ddd27af114430ac11f25e977be0fe986..639372b2aedc8ed1b5a08229f68d3821f9914493 100644 --- a/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java +++ b/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java @@ -74,15 +74,15 @@ public class HierarchicalStateMachineTest extends TestCase { if (isQuit(message)) { mQuitCount += 1; if (mQuitCount > 2) { - // Returning false to actually quit - return false; + // Returning NOT_HANDLED to actually quit + return NOT_HANDLED; } else { // Do NOT quit - return true; + return HANDLED; } } else { // All other message are handled - return true; + return HANDLED; } } } @@ -172,12 +172,18 @@ public class HierarchicalStateMachineTest extends TestCase { class S1 extends HierarchicalState { @Override protected void enter() { + // Test that message is HSM_INIT_CMD + assertEquals(HSM_INIT_CMD, getCurrentMessage().what); + // Test that a transition in enter and the initial state works mS1EnterCount += 1; transitionTo(mS2); Log.d(TAG, "S1.enter"); } @Override protected void exit() { + // Test that message is HSM_INIT_CMD + assertEquals(HSM_INIT_CMD, getCurrentMessage().what); + mS1ExitCount += 1; Log.d(TAG, "S1.exit"); } @@ -185,10 +191,16 @@ public class HierarchicalStateMachineTest extends TestCase { class S2 extends HierarchicalState { @Override protected void enter() { + // Test that message is HSM_INIT_CMD + assertEquals(HSM_INIT_CMD, getCurrentMessage().what); + mS2EnterCount += 1; Log.d(TAG, "S2.enter"); } @Override protected void exit() { + // Test that message is TEST_CMD_1 + assertEquals(TEST_CMD_1, getCurrentMessage().what); + // Test transition in exit work mS2ExitCount += 1; transitionTo(mS4); @@ -196,10 +208,10 @@ public class HierarchicalStateMachineTest extends TestCase { } @Override protected boolean processMessage(Message message) { // Start a transition to S3 but it will be - // changed to a transition to S4 + // changed to a transition to S4 in exit transitionTo(mS3); Log.d(TAG, "S2.processMessage"); - return true; + return HANDLED; } } @@ -264,7 +276,7 @@ public class HierarchicalStateMachineTest extends TestCase { } synchronized (smEnterExitTranstionToTest) { - smEnterExitTranstionToTest.sendMessage(1); + smEnterExitTranstionToTest.sendMessage(TEST_CMD_1); try { // wait for the messages to be handled @@ -321,7 +333,7 @@ public class HierarchicalStateMachineTest extends TestCase { if (message.what == TEST_CMD_6) { transitionToHaltingState(); } - return true; + return HANDLED; } } @@ -415,7 +427,7 @@ public class HierarchicalStateMachineTest extends TestCase { assertEquals(1, mExitCount); transitionToHaltingState(); } - return true; + return HANDLED; } @Override protected void exit() { @@ -510,7 +522,7 @@ public class HierarchicalStateMachineTest extends TestCase { if (message.what == TEST_CMD_2) { transitionTo(mS2); } - return true; + return HANDLED; } @Override protected void exit() { @@ -523,7 +535,7 @@ public class HierarchicalStateMachineTest extends TestCase { if (message.what == TEST_CMD_2) { transitionToHaltingState(); } - return true; + return HANDLED; } } @@ -612,13 +624,13 @@ public class HierarchicalStateMachineTest extends TestCase { if (message.what == TEST_CMD_2) { transitionToHaltingState(); } - return true; + return HANDLED; } } class ChildState extends HierarchicalState { @Override protected boolean processMessage(Message message) { - return false; + return NOT_HANDLED; } } @@ -697,20 +709,20 @@ public class HierarchicalStateMachineTest extends TestCase { if (message.what == TEST_CMD_2) { transitionToHaltingState(); } - return true; + return HANDLED; } } class ChildState1 extends HierarchicalState { @Override protected boolean processMessage(Message message) { transitionTo(mChildState2); - return true; + return HANDLED; } } class ChildState2 extends HierarchicalState { @Override protected boolean processMessage(Message message) { - return false; + return NOT_HANDLED; } } @@ -794,7 +806,7 @@ public class HierarchicalStateMachineTest extends TestCase { mParentState1EnterCount += 1; } @Override protected boolean processMessage(Message message) { - return true; + return HANDLED; } @Override protected void exit() { mParentState1ExitCount += 1; @@ -822,7 +834,7 @@ public class HierarchicalStateMachineTest extends TestCase { assertEquals(0, mChildState5ExitCount); transitionTo(mChildState2); - return true; + return HANDLED; } @Override protected void exit() { mChildState1ExitCount += 1; @@ -850,7 +862,7 @@ public class HierarchicalStateMachineTest extends TestCase { assertEquals(0, mChildState5ExitCount); transitionTo(mChildState5); - return true; + return HANDLED; } @Override protected void exit() { mChildState2ExitCount += 1; @@ -878,7 +890,7 @@ public class HierarchicalStateMachineTest extends TestCase { assertEquals(1, mChildState5ExitCount); transitionToHaltingState(); - return true; + return HANDLED; } @Override protected void exit() { mParentState2ExitCount += 1; @@ -906,7 +918,7 @@ public class HierarchicalStateMachineTest extends TestCase { assertEquals(1, mChildState5ExitCount); transitionTo(mChildState4); - return true; + return HANDLED; } @Override protected void exit() { mChildState3ExitCount += 1; @@ -934,7 +946,7 @@ public class HierarchicalStateMachineTest extends TestCase { assertEquals(1, mChildState5ExitCount); transitionTo(mParentState2); - return true; + return HANDLED; } @Override protected void exit() { mChildState4ExitCount += 1; @@ -962,7 +974,7 @@ public class HierarchicalStateMachineTest extends TestCase { assertEquals(0, mChildState5ExitCount); transitionTo(mChildState3); - return true; + return HANDLED; } @Override protected void exit() { mChildState5ExitCount += 1; @@ -1108,7 +1120,7 @@ public class HierarchicalStateMachineTest extends TestCase { mArrivalTimeMsg2 = SystemClock.elapsedRealtime(); transitionToHaltingState(); } - return true; + return HANDLED; } @Override protected void exit() { @@ -1190,7 +1202,7 @@ public class HierarchicalStateMachineTest extends TestCase { class S1 extends HierarchicalState { @Override protected boolean processMessage(Message message) { transitionTo(mS2); - return true; + return HANDLED; } @Override protected void exit() { sendMessage(TEST_CMD_2); @@ -1216,7 +1228,7 @@ public class HierarchicalStateMachineTest extends TestCase { if (mMsgCount == 2) { transitionToHaltingState(); } - return true; + return HANDLED; } @Override protected void exit() { @@ -1300,7 +1312,7 @@ public class HierarchicalStateMachineTest extends TestCase { if (message.what == TEST_CMD_2) { transitionToHaltingState(); } - return false; + return NOT_HANDLED; } } @@ -1369,7 +1381,7 @@ public class HierarchicalStateMachineTest extends TestCase { if (message.what == TEST_CMD_4) { transitionToHaltingState(); } - return true; + return HANDLED; } } @@ -1563,10 +1575,10 @@ class Hsm1 extends HierarchicalStateMachine { if (message.what == CMD_1) { // Transition to ourself to show that enter/exit is called transitionTo(mS1); - return true; + return HANDLED; } else { // Let parent process all other messages - return false; + return NOT_HANDLED; } } @Override protected void exit() { @@ -1618,7 +1630,7 @@ class Hsm1 extends HierarchicalStateMachine { transitionToHaltingState(); break; } - return true; + return HANDLED; } @Override protected void exit() { Log.d(TAG, "P2.exit"); diff --git a/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java b/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java index 004a197352d93c50c6d5a67347a8cf1fbd182404..2de0464d503967ffb3bafbf232ad6da60341d674 100644 --- a/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java +++ b/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java @@ -275,6 +275,16 @@ public class VCardExporterTests extends VCardTestsBase { testPhoneBasicCommon(V30); } + public void testPhoneRefrainFormatting() { + mVerifier.initForExportTest(V21 | VCardConfig.FLAG_REFRAIN_PHONE_NUMBER_FORMATTING); + mVerifier.addInputEntry().addContentValues(Phone.CONTENT_ITEM_TYPE) + .put(Phone.NUMBER, "1234567890(abcdefghijklmnopqrstuvwxyz)") + .put(Phone.TYPE, Phone.TYPE_HOME); + mVerifier.addPropertyNodesVerifierElemWithEmptyName() + .addExpectedNode("TEL", "1234567890(abcdefghijklmnopqrstuvwxyz)", + new TypeSet("HOME")); + } + /** * Tests that vCard composer emits corresponding type param which we expect. */ diff --git a/core/tests/coretests/src/android/view/VelocityTest.java b/core/tests/coretests/src/android/view/VelocityTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fb28e1e30f0aa8e5bb9449cb716255787aa1ce56 --- /dev/null +++ b/core/tests/coretests/src/android/view/VelocityTest.java @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2010 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. + */ + +package com.android.frameworktest.view; + +import junit.framework.Assert; + +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; + +/** + * Exercises {@link android.view.VelocityTracker} to compute correct velocity.
+ * To launch this test, use :
+ * ./development/testrunner/runtest.py framework -c com.android.frameworktest.view.VelocityTest + */ +public class VelocityTest extends InstrumentationTestCase { + + @MediumTest + public void testInitialCondiditions() { + VelocityTracker vt = VelocityTracker.obtain(); + assertNotNull(vt); + vt.recycle(); + } + + /** + * Test that {@link android.view.VelocityTracker}.clear() clears + * the previous values after a call to computeCurrentVelocity() + */ + @MediumTest + public void testClear() { + long t = System.currentTimeMillis(); + VelocityTracker vt = VelocityTracker.obtain(); + drag(vt, 100, 200, 100, 200, 10, t, 300); + vt.computeCurrentVelocity(1); + assertFalse("Velocity should not be null", vt.getXVelocity() == 0.0f); + assertFalse("Velocity should not be null", vt.getYVelocity() == 0.0f); + vt.clear(); + vt.computeCurrentVelocity(1); + assertEquals(0.0f, vt.getXVelocity()); + assertEquals(0.0f, vt.getYVelocity()); + vt.recycle(); + } + + @MediumTest + public void testDragAcceleration () { + long t = System.currentTimeMillis(); + VelocityTracker vt = VelocityTracker.obtain(); + drag(vt, 100, 200, 100, 200, 15, t, 400, new AccelerateInterpolator()); + vt.computeCurrentVelocity(1000); + assertGreater(250.0f, vt.getXVelocity()); + assertGreater(250.0f, vt.getYVelocity()); + vt.recycle(); + } + + @MediumTest + public void testDragDeceleration () { + long t = System.currentTimeMillis(); + VelocityTracker vt = VelocityTracker.obtain(); + drag(vt, 100, 200, 100, 200, 15, t, 400, new DecelerateInterpolator()); + vt.computeCurrentVelocity(1000); + assertLower(250.0f, vt.getXVelocity()); + assertLower(250.0f, vt.getYVelocity()); + vt.recycle(); + } + + @MediumTest + public void testDragLinearHorizontal() { + long t = System.currentTimeMillis(); + VelocityTracker vt = VelocityTracker.obtain(); + // 100px in 400ms => 250px/s + drag(vt, 100, 200, 200, 200, 15, t, 400); + vt.computeCurrentVelocity(1000); + assertEquals(0.0f, vt.getYVelocity()); + assertEqualFuzzy(250.0f, vt.getXVelocity(), 4f); + vt.recycle(); + } + + @MediumTest + public void testDragLinearVertical() { + long t = System.currentTimeMillis(); + VelocityTracker vt = VelocityTracker.obtain(); + // 100px in 400ms => 250px/s + drag(vt, 200, 200, 100, 200, 15, t, 400); + vt.computeCurrentVelocity(1000); + assertEquals(0.0f, vt.getXVelocity()); + assertEqualFuzzy(250.0f, vt.getYVelocity(), 4f); + vt.recycle(); + } + + /** + * Test dragging with two points only + * (velocity must be an exact value) + */ + @MediumTest + public void testDragWith2Points () { + long t = System.currentTimeMillis(); + VelocityTracker vt = VelocityTracker.obtain(); + // 100px, 2 steps, 100ms => 1000px/s + drag(vt, 100, 200, 100, 200, 2, t, 100); + vt.computeCurrentVelocity(1000); + assertEquals(1000.0f, vt.getXVelocity()); + assertEquals(1000.0f, vt.getYVelocity()); + vt.recycle(); + } + + /** + * Velocity is independent of the number of points used during + * the same interval + */ + @MediumTest + public void testStabilityInNbPoints () { + long t = System.currentTimeMillis(); + VelocityTracker vt = VelocityTracker.obtain(); + drag(vt, 100, 200, 100, 200, 10, t, 400); // 10 steps over 400ms + vt.computeCurrentVelocity(1); + float firstX = vt.getXVelocity(); + float firstY = vt.getYVelocity(); + vt.clear(); + drag(vt, 100, 200, 100, 200, 20, t, 400); // 20 steps over 400ms + vt.computeCurrentVelocity(1); + float secondX = vt.getXVelocity(); + float secondY = vt.getYVelocity(); + assertEqualFuzzy(firstX, secondX, 0.1f); + assertEqualFuzzy(firstY, secondY, 0.1f); + vt.recycle(); + } + + /** + * Velocity is independent of the time when the events occurs, + * it only depends on delays between the events. + */ + @MediumTest + public void testStabilityInTime () { + long t = System.currentTimeMillis(); + VelocityTracker vt = VelocityTracker.obtain(); + drag(vt, 100, 200, 100, 200, 10, t, 400); + vt.computeCurrentVelocity(1); + float firstX = vt.getXVelocity(); + float firstY = vt.getYVelocity(); + vt.clear(); + drag(vt, 100, 200, 100, 200, 10, t + 3600*1000, 400); // on hour later + vt.computeCurrentVelocity(1); + float secondX = vt.getXVelocity(); + float secondY = vt.getYVelocity(); + assertEqualFuzzy(firstX, secondX, 0.1f); + assertEqualFuzzy(firstY, secondY, 0.1f); + vt.recycle(); + } + + /** + * Velocity is independent of the position of the events, + * it only depends on their relative distance. + */ + @MediumTest + public void testStabilityInSpace () { + long t = System.currentTimeMillis(); + VelocityTracker vt = VelocityTracker.obtain(); + drag(vt, 100, 200, 100, 200, 10, t, 400); + vt.computeCurrentVelocity(1); + float firstX = vt.getXVelocity(); + float firstY = vt.getYVelocity(); + vt.clear(); + drag(vt, 200, 300, 200, 300, 10, t, 400); // 100px further + vt.computeCurrentVelocity(1); + float secondX = vt.getXVelocity(); + float secondY = vt.getYVelocity(); + assertEqualFuzzy(firstX, secondX, 0.1f); + assertEqualFuzzy(firstY, secondY, 0.1f); + vt.recycle(); + } + + /** + * Test that calls to {@link android.view.VelocityTracker}.computeCurrentVelocity() + * will output same values when using the same data. + */ + @MediumTest + public void testStabilityOfComputation() { + long t = System.currentTimeMillis(); + VelocityTracker vt = VelocityTracker.obtain(); + drag(vt, 100, 200, 100, 200, 10, t, 300); + vt.computeCurrentVelocity(1); + float firstX = vt.getXVelocity(); + float firstY = vt.getYVelocity(); + vt.computeCurrentVelocity(1); + float secondX = vt.getXVelocity(); + float secondY = vt.getYVelocity(); + assertEquals(firstX, secondX); + assertEquals(firstY, secondY); + vt.recycle(); + } + + /** + * Test the units parameter of {@link android.view.VelocityTracker}.computeCurrentVelocity() + */ + @MediumTest + public void testStabilityOfUnits() { + long t = System.currentTimeMillis(); + VelocityTracker vt = VelocityTracker.obtain(); + drag(vt, 100, 200, 100, 200, 10, t, 300); + vt.computeCurrentVelocity(1); + float firstX = vt.getXVelocity(); + float firstY = vt.getYVelocity(); + vt.computeCurrentVelocity(1000); + float secondX = vt.getXVelocity(); + float secondY = vt.getYVelocity(); + assertEqualFuzzy(firstX, secondX / 1000.0f, 0.1f); + assertEqualFuzzy(firstY, secondY / 1000.0f, 0.1f); + vt.recycle(); + } + + /** + * Simulate a drag by giving directly MotionEvents to + * the VelocityTracker using a linear interpolator + */ + private void drag(VelocityTracker vt, int startX, int endX, int startY, int endY, int steps, + long startime, int duration) { + drag(vt, startX, endX, startY, endY, steps, startime, duration, new LinearInterpolator()); + } + + /** + * Simulate a drag by giving directly MotionEvents to + * the VelocityTracker using a given interpolator + */ + private void drag(VelocityTracker vt, int startX, int endX, int startY, int endY, int steps, + long startime, int duration, Interpolator interpolator) { + addMotionEvent(vt, startX, startY, startime, MotionEvent.ACTION_DOWN); + float dt = duration / (float)steps; + int distX = endX - startX; + int distY = endY - startY; + for (int i=1; i 3) implies that tests + * accepts some approximated values. + */ + private void assertEqualFuzzy(float expected, float actual, float threshold) { + boolean fuzzyEqual = actual >= expected - threshold && actual <= expected + threshold; + Assert.assertTrue("Expected: <"+expected+"> but was: <"+actual+ + "> while accepting a variation of: <"+threshold+">", fuzzyEqual); + } + + private void assertGreater(float minExpected, float actual) { + Assert.assertTrue("Expected: minimum <"+minExpected+"> but was: <"+actual+">", + actual > minExpected); + } + + private void assertLower(float maxExpected, float actual) { + Assert.assertTrue("Expected: maximum <"+maxExpected+"> but was: <"+actual+">", + actual < maxExpected); + } +} diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java index 5cefaa3b72c688f3ca0c900038752d951069baba..a50693d2f1305d22eaafd5ec987315104834e8a7 100644 --- a/graphics/java/android/graphics/Color.java +++ b/graphics/java/android/graphics/Color.java @@ -30,7 +30,8 @@ import java.util.Locale; * (green << 8) | blue. Each component ranges between 0..255 with 0 * meaning no contribution for that component, and 255 meaning 100% * contribution. Thus opaque-black would be 0xFF000000 (100% opaque but - * no contributes from red, gree, blue, and opaque-white would be 0xFFFFFFFF + * no contributions from red, green, or blue), and opaque-white would be + * 0xFFFFFFFF */ public class Color { public static final int BLACK = 0xFF000000; diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp index d8e03936aa7b2cce5a5e4c3bc5e407ce2c26c2f6..45cc72e7e41bc764693dcfb4cdadb143324324e7 100644 --- a/graphics/jni/android_renderscript_RenderScript.cpp +++ b/graphics/jni/android_renderscript_RenderScript.cpp @@ -185,7 +185,7 @@ nContextSetSurface(JNIEnv *_env, jobject _this, jint width, jint height, jobject } else { jclass surface_class = _env->FindClass("android/view/Surface"); - jfieldID surfaceFieldID = _env->GetFieldID(surface_class, "mSurface", "I"); + jfieldID surfaceFieldID = _env->GetFieldID(surface_class, ANDROID_VIEW_SURFACE_JNI_ID, "I"); window = (Surface*)_env->GetIntField(wnd, surfaceFieldID); } diff --git a/include/binder/IInterface.h b/include/binder/IInterface.h index 273d92231fe2eff7854cf043353d4d206219a5c9..5f9f69c042bf9ff1bb69acb83bd4f140f28fcbd2 100644 --- a/include/binder/IInterface.h +++ b/include/binder/IInterface.h @@ -72,21 +72,24 @@ protected: // ---------------------------------------------------------------------- #define DECLARE_META_INTERFACE(INTERFACE) \ - static const String16 descriptor; \ - static sp asInterface(const sp& obj); \ - virtual const String16& getInterfaceDescriptor() const; \ + static const android::String16 descriptor; \ + static android::sp asInterface( \ + const android::sp& obj); \ + virtual const android::String16& getInterfaceDescriptor() const; \ I##INTERFACE(); \ virtual ~I##INTERFACE(); \ #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ - const String16 I##INTERFACE::descriptor(NAME); \ - const String16& I##INTERFACE::getInterfaceDescriptor() const { \ + const android::String16 I##INTERFACE::descriptor(NAME); \ + const android::String16& \ + I##INTERFACE::getInterfaceDescriptor() const { \ return I##INTERFACE::descriptor; \ } \ - sp I##INTERFACE::asInterface(const sp& obj) \ + android::sp I##INTERFACE::asInterface( \ + const android::sp& obj) \ { \ - sp intr; \ + android::sp intr; \ if (obj != NULL) { \ intr = static_cast( \ obj->queryLocalInterface( \ diff --git a/include/camera/Camera.h b/include/camera/Camera.h index ee2b30ca84a48fd559b226a91f61d78b7b02ee3e..1beac27151f15f68a93355ee586283921bbef401 100644 --- a/include/camera/Camera.h +++ b/include/camera/Camera.h @@ -113,7 +113,8 @@ class Camera : public BnCameraClient, public IBinder::DeathRecipient public: // construct a camera client from an existing remote static sp create(const sp& camera); - static sp connect(); + static int32_t getNumberOfCameras(); + static sp connect(int cameraId); ~Camera(); void init(); diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h index 5ea83a5a020fba8b9cd57a43e2a70c656d4a933b..2b7a86eb7a3ddfa8b3546505b80f244ec29ceb4f 100644 --- a/include/camera/CameraParameters.h +++ b/include/camera/CameraParameters.h @@ -65,13 +65,15 @@ public: // Supported preview frame sizes in pixels. // Example value: "800x600,480x320". Read only. static const char KEY_SUPPORTED_PREVIEW_SIZES[]; - // The image format for preview frames. + // The image format for preview frames. See CAMERA_MSG_PREVIEW_FRAME in + // frameworks/base/include/camera/Camera.h. // Example value: "yuv420sp" or PIXEL_FORMAT_XXX constants. Read/write. static const char KEY_PREVIEW_FORMAT[]; // Supported image formats for preview frames. // Example value: "yuv420sp,yuv422i-yuyv". Read only. static const char KEY_SUPPORTED_PREVIEW_FORMATS[]; - // Number of preview frames per second. + // Number of preview frames per second. This is the target frame rate. The + // actual frame rate depends on the driver. // Example value: "15". Read/write. static const char KEY_PREVIEW_FRAME_RATE[]; // Supported number of preview frames per second. @@ -83,7 +85,8 @@ public: // Supported dimensions for captured pictures in pixels. // Example value: "2048x1536,1024x768". Read only. static const char KEY_SUPPORTED_PICTURE_SIZES[]; - // The image format for captured pictures. + // The image format for captured pictures. See CAMERA_MSG_COMPRESSED_IMAGE + // in frameworks/base/include/camera/Camera.h. // Example value: "jpeg" or PIXEL_FORMAT_XXX constants. Read/write. static const char KEY_PICTURE_FORMAT[]; // Supported image formats for captured pictures. @@ -119,14 +122,17 @@ public: // should not set default value for this parameter. // Example value: "0" or "90" or "180" or "270". Write only. static const char KEY_ROTATION[]; - // GPS latitude coordinate. This will be stored in JPEG EXIF header. - // Example value: "25.032146". Write only. + // GPS latitude coordinate. GPSLatitude and GPSLatitudeRef will be stored in + // JPEG EXIF header. + // Example value: "25.032146" or "-33.462809". Write only. static const char KEY_GPS_LATITUDE[]; - // GPS longitude coordinate. This will be stored in JPEG EXIF header. - // Example value: "121.564448". Write only. + // GPS longitude coordinate. GPSLongitude and GPSLongitudeRef will be stored + // in JPEG EXIF header. + // Example value: "121.564448" or "-70.660286". Write only. static const char KEY_GPS_LONGITUDE[]; - // GPS altitude. This will be stored in JPEG EXIF header. - // Example value: "21.0". Write only. + // GPS altitude. GPSAltitude and GPSAltitudeRef will be stored in JPEG EXIF + // header. + // Example value: "21.0" or "-5". Write only. static const char KEY_GPS_ALTITUDE[]; // GPS timestamp (UTC in seconds since January 1, 1970). This should be // stored in JPEG EXIF header. @@ -221,9 +227,35 @@ public: // Example value: "true". Read only. static const char KEY_SMOOTH_ZOOM_SUPPORTED[]; + // The distances (in meters) from the camera to where an object appears to + // be in focus. The object is sharpest at the optimal focus distance. The + // depth of field is the far focus distance minus near focus distance. + // + // Applications can read this parameter anytime to get the latest focus + // distances. If the focus mode is FOCUS_MODE_EDOF, the values may be all + // 0, which means focus distance is not applicable. If the focus mode is + // FOCUS_MODE_CONTINUOUS and autofocus has started, focus distances may + // change from time to time. + // + // Far focus distance > optimal focus distance > near focus distance. If + // the far focus distance is infinity, the value should be "Infinity" (case + // sensitive). The format is three float values separated by commas. The + // first is near focus distance. The second is optimal focus distance. The + // third is far focus distance. + // Example value: "0.95,1.9,Infinity" or "0.049,0.05,0.051". Read only. + static const char KEY_FOCUS_DISTANCES[]; + + // The image format for video frames. See CAMERA_MSG_VIDEO_FRAME in + // frameworks/base/include/camera/Camera.h. + // Example value: "yuv420sp" or PIXEL_FORMAT_XXX constants. Read only. + static const char KEY_VIDEO_FRAME_FORMAT[]; + // Value for KEY_ZOOM_SUPPORTED or KEY_SMOOTH_ZOOM_SUPPORTED. static const char TRUE[]; + // Value for KEY_FOCUS_DISTANCES. + static const char FOCUS_DISTANCE_INFINITY[]; + // Values for white balance settings. static const char WHITE_BALANCE_AUTO[]; static const char WHITE_BALANCE_INCANDESCENT[]; @@ -309,6 +341,12 @@ public: // continuously. Applications should not call // CameraHardwareInterface.autoFocus in this mode. static const char FOCUS_MODE_EDOF[]; + // Continuous focus mode. The camera continuously tries to focus. This is + // ideal for shooting video or shooting photo of moving object. Continuous + // focus starts when CameraHardwareInterface.autoFocus is called. Focus + // callback will be only called once as soon as the picture is in focus. + static const char FOCUS_MODE_CONTINUOUS[]; + private: DefaultKeyedVector mMap; diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h index 82b1283a803dccb2b969170433e60aa6d06462cc..dcd434f52f6032aa77d63466c806917d48410b50 100644 --- a/include/camera/ICameraService.h +++ b/include/camera/ICameraService.h @@ -30,13 +30,16 @@ class ICameraService : public IInterface { public: enum { - CONNECT = IBinder::FIRST_CALL_TRANSACTION, + GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION, + CONNECT }; public: DECLARE_META_INTERFACE(CameraService); - virtual sp connect(const sp& cameraClient) = 0; + virtual int32_t getNumberOfCameras() = 0; + virtual sp connect(const sp& cameraClient, + int cameraId) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/media/AudioCommon.h b/include/media/AudioCommon.h new file mode 100644 index 0000000000000000000000000000000000000000..245d7606557b53f34a9c67e6d9723a9708728876 --- /dev/null +++ b/include/media/AudioCommon.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010 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 ANDROID_AUDIOCOMMON_H_ +#define ANDROID_AUDIOCOMMON_H_ + +#if __cplusplus +extern "C" { +#endif + +///////////////////////////////////////////////// +// Common definitions for PCM audio +///////////////////////////////////////////////// + + +// PCM Sample format +enum audio_format_e { + PCM_FORMAT_S15 = 1, // PCM signed 16 bits, must be 1 for backward compatibility + PCM_FORMAT_U8 = 2, // PCM unsigned 8 bits, must be 2 for backward compatibility + PCM_FORMAT_S7_24 // signed 7.24 fixed point representation +}; + +// Channel mask definitions +enum audio_channels_e { + CHANNEL_FRONT_LEFT = 0x4, // front left channel + CHANNEL_FRONT_RIGHT = 0x8, // front right channel + CHANNEL_FRONT_CENTER = 0x10, // front center channel + CHANNEL_LOW_FREQUENCY = 0x20, // low frequency channel + CHANNEL_BACK_LEFT = 0x40, // back left channel + CHANNEL_BACK_RIGHT = 0x80, // back right channel + CHANNEL_FRONT_LEFT_OF_CENTER = 0x100, // front left of center channel + CHANNEL_FRONT_RIGHT_OF_CENTER = 0x200, // front right of center channel + CHANNEL_BACK_CENTER = 0x400, // back center channel + CHANNEL_MONO = CHANNEL_FRONT_LEFT, + CHANNEL_STEREO = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT), + CHANNEL_QUAD = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT), + CHANNEL_SURROUND = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER), + CHANNEL_5POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT), + CHANNEL_7POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT | + CHANNEL_FRONT_LEFT_OF_CENTER | CHANNEL_FRONT_RIGHT_OF_CENTER), +}; + +// Render device definitions +enum audio_device_e { + DEVICE_EARPIECE = 0x1, // earpiece + DEVICE_SPEAKER = 0x2, // speaker + DEVICE_WIRED_HEADSET = 0x4, // wired headset, with microphone + DEVICE_WIRED_HEADPHONE = 0x8, // wired headphone, without microphone + DEVICE_BLUETOOTH_SCO = 0x10, // generic bluetooth SCO + DEVICE_BLUETOOTH_SCO_HEADSET = 0x20, // bluetooth SCO headset + DEVICE_BLUETOOTH_SCO_CARKIT = 0x40, // bluetooth SCO car kit + DEVICE_BLUETOOTH_A2DP = 0x80, // generic bluetooth A2DP + DEVICE_BLUETOOTH_A2DP_HEADPHONES = 0x100, // bluetooth A2DP headphones + DEVICE_BLUETOOTH_A2DP_SPEAKER = 0x200, // bluetooth A2DP speakers + DEVICE_AUX_DIGITAL = 0x400 // digital output +}; + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_AUDIOCOMMON_H_*/ diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index d0ccc5059f4f96a4df3c6da0811e6836a709b73d..9caef8ff95dc5c80e372af5f597f83c3794f8b34 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -20,6 +20,7 @@ #include #include #include +#include namespace android { @@ -50,8 +51,8 @@ public: // Audio sub formats (see AudioSystem::audio_format). enum pcm_sub_format { - PCM_SUB_16_BIT = 0x1, // must be 1 for backward compatibility - PCM_SUB_8_BIT = 0x2, // must be 2 for backward compatibility + PCM_SUB_16_BIT = PCM_FORMAT_S15, // must be 1 for backward compatibility + PCM_SUB_8_BIT = PCM_FORMAT_U8, // must be 2 for backward compatibility }; // MP3 sub format field definition : can use 11 LSBs in the same way as MP3 frame header to specify @@ -103,26 +104,21 @@ public: // Channel mask definitions must be kept in sync with JAVA values in /media/java/android/media/AudioFormat.java enum audio_channels { // output channels - CHANNEL_OUT_FRONT_LEFT = 0x4, - CHANNEL_OUT_FRONT_RIGHT = 0x8, - CHANNEL_OUT_FRONT_CENTER = 0x10, - CHANNEL_OUT_LOW_FREQUENCY = 0x20, - CHANNEL_OUT_BACK_LEFT = 0x40, - CHANNEL_OUT_BACK_RIGHT = 0x80, - CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x100, - CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x200, - CHANNEL_OUT_BACK_CENTER = 0x400, - CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT, - CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT), - CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | - CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT), - CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | - CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER), - CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | - CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT), - CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | - CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT | - CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER), + CHANNEL_OUT_FRONT_LEFT = CHANNEL_FRONT_LEFT, + CHANNEL_OUT_FRONT_RIGHT = CHANNEL_FRONT_RIGHT, + CHANNEL_OUT_FRONT_CENTER = CHANNEL_FRONT_CENTER, + CHANNEL_OUT_LOW_FREQUENCY = CHANNEL_LOW_FREQUENCY, + CHANNEL_OUT_BACK_LEFT = CHANNEL_BACK_LEFT, + CHANNEL_OUT_BACK_RIGHT = CHANNEL_BACK_RIGHT, + CHANNEL_OUT_FRONT_LEFT_OF_CENTER = CHANNEL_FRONT_LEFT_OF_CENTER, + CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = CHANNEL_FRONT_RIGHT_OF_CENTER, + CHANNEL_OUT_BACK_CENTER = CHANNEL_BACK_CENTER, + CHANNEL_OUT_MONO = CHANNEL_MONO, + CHANNEL_OUT_STEREO = CHANNEL_STEREO, + CHANNEL_OUT_QUAD = CHANNEL_QUAD, + CHANNEL_OUT_SURROUND = CHANNEL_SURROUND, + CHANNEL_OUT_5POINT1 = CHANNEL_5POINT1, + CHANNEL_OUT_7POINT1 = CHANNEL_7POINT1, CHANNEL_OUT_ALL = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT | CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | CHANNEL_OUT_BACK_CENTER), @@ -240,17 +236,17 @@ public: enum audio_devices { // output devices - DEVICE_OUT_EARPIECE = 0x1, - DEVICE_OUT_SPEAKER = 0x2, - DEVICE_OUT_WIRED_HEADSET = 0x4, - DEVICE_OUT_WIRED_HEADPHONE = 0x8, - DEVICE_OUT_BLUETOOTH_SCO = 0x10, - DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20, - DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40, - DEVICE_OUT_BLUETOOTH_A2DP = 0x80, - DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100, - DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200, - DEVICE_OUT_AUX_DIGITAL = 0x400, + DEVICE_OUT_EARPIECE = DEVICE_EARPIECE, + DEVICE_OUT_SPEAKER = DEVICE_SPEAKER, + DEVICE_OUT_WIRED_HEADSET = DEVICE_WIRED_HEADSET, + DEVICE_OUT_WIRED_HEADPHONE = DEVICE_WIRED_HEADPHONE, + DEVICE_OUT_BLUETOOTH_SCO = DEVICE_BLUETOOTH_SCO, + DEVICE_OUT_BLUETOOTH_SCO_HEADSET = DEVICE_BLUETOOTH_SCO_HEADSET, + DEVICE_OUT_BLUETOOTH_SCO_CARKIT = DEVICE_BLUETOOTH_SCO_CARKIT, + DEVICE_OUT_BLUETOOTH_A2DP = DEVICE_BLUETOOTH_A2DP, + DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = DEVICE_BLUETOOTH_A2DP_HEADPHONES, + DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = DEVICE_BLUETOOTH_A2DP_SPEAKER, + DEVICE_OUT_AUX_DIGITAL = DEVICE_AUX_DIGITAL, DEVICE_OUT_DEFAULT = 0x8000, DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET | DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET | diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index 14b30ae9cba40856f9f62d878018cbeb39468d6f..cc4ab74377ba51f3667d3bc254f5d606e3cefe34 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -398,7 +398,8 @@ private: int frameCount, uint32_t flags, const sp& sharedBuffer, - audio_io_handle_t output); + audio_io_handle_t output, + bool enforceFrameCount); sp mAudioTrack; sp mCblkMemory; @@ -420,7 +421,8 @@ private: callback_t mCbf; void* mUserData; - uint32_t mNotificationFrames; + uint32_t mNotificationFramesReq; // requested number of frames between each notification callback + uint32_t mNotificationFramesAct; // actual number of frames between each notification callback sp mSharedBuffer; int mLoopCount; uint32_t mRemainingFrames; diff --git a/include/media/EffectApi.h b/include/media/EffectApi.h new file mode 100644 index 0000000000000000000000000000000000000000..a1bc3b82d45fdfb51f63f0086274d7ee80fc8cc4 --- /dev/null +++ b/include/media/EffectApi.h @@ -0,0 +1,555 @@ +/* + * Copyright (C) 2010 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 ANDROID_EFFECTAPI_H_ +#define ANDROID_EFFECTAPI_H_ + +#include +#include +#include +#include + +#if __cplusplus +extern "C" { +#endif + +///////////////////////////////////////////////// +// Effect control interface +///////////////////////////////////////////////// + +// The effect control interface is exposed by each effect engine implementation. It consists of +// a set of functions controlling the configuration, activation and process of the engine. +// The functions are grouped in a structure of type effect_interface_s: +// struct effect_interface_s { +// effect_process_t process; +// effect_command_t command; +// }; + + +// effect_interface_t: Effect control interface handle. +// The effect_interface_t serves two purposes regarding the implementation of the effect engine: +// - 1 it is the address of a pointer to an effect_interface_s structure where the functions +// of the effect control API for a particular effect are located. +// - 2 it is the address of the context of a particular effect instance. +// A typical implementation in the effect library would define a structure as follows: +// struct effect_module_s { +// const struct effect_interface_s *itfe; +// effect_config_t config; +// effect_context_t context; +// } +// The implementation of EffectCreate() function would then allocate a structure of this +// type and return its address as effect_interface_t +typedef struct effect_interface_s **effect_interface_t; + + +// Effect API version 1.0 +#define EFFECT_API_VERSION 0x0100 // Format 0xMMmm MM: Major version, mm: minor version + +// Maximum length of character strings in structures defines by this API. +#define EFFECT_STRING_LEN_MAX 64 + +// +//--- Effect descriptor structure effect_descriptor_t +// + +// Unique effect ID (can be generated from the following site: http://www.itu.int/ITU-T/asn1/uuid.html) +// This format is used for both "type" and "uuid" fields of the effect descriptor structure. +// - When used for effect type and the engine is implementing and effect corresponding to a standard OpenSL ES +// interface, this ID must be the one defined in OpenSLES_IID.h for that interface. +// - When used as uuid, it should be a unique UUID for this particular implementation. +typedef struct effect_uuid_s { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint16_t clockSeq; + uint8_t node[6]; +} effect_uuid_t; + +// NULL UUID definition (matches SL_IID_NULL_) +#define EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } } +static const effect_uuid_t EFFECT_UUID_NULL_ = EFFECT_UUID_INITIALIZER; +const effect_uuid_t * const EFFECT_UUID_NULL = &EFFECT_UUID_NULL_; +const char * const EFFECT_UUID_NULL_STR = "ec7178ec-e5e1-4432-a3f4-4657e6795210"; + +// the effect descriptor contains necessary information to facilitate the enumeration of the effect +// engines present in a library. +typedef struct effect_descriptor_s { + effect_uuid_t type; // UUID corresponding to the OpenSL ES interface implemented by this effect + effect_uuid_t uuid; // UUID for this particular implementation + uint16_t apiVersion; // Version of the effect API implemented: must match current EFFECT_API_VERSION + uint32_t flags; // effect engine capabilities/requirements flags (see below) + char name[EFFECT_STRING_LEN_MAX] ; // human readable effect name + char implementor[EFFECT_STRING_LEN_MAX] ; // human readable effect implementor name +} effect_descriptor_t; + +// definitions for flags field of effect descriptor. +// +---------------------------+-----------+----------------------------------- +// | description | bits | values +// +---------------------------+-----------+----------------------------------- +// | connection mode | 0..1 | 0 insert: after track process +// | | | 1 auxiliary: connect to track auxiliary +// | | | output and use send level +// | | | 2 replace: replaces track process function; +// | | | must implement SRC, volume and mono to stereo. +// | | | 3 reserved +// +---------------------------+-----------+----------------------------------- +// | insertion preference | 2..4 | 0 none +// | | | 1 first of the chain +// | | | 2 last of the chain +// | | | 3 exclusive (only effect in the insert chain) +// | | | 4..7 reserved +// +---------------------------+-----------+----------------------------------- +// | Volume management | 5..6 | 0 none +// | | | 1 implements volume control +// | | | 2..3 reserved +// +---------------------------+-----------+----------------------------------- +// | Device management | 7..8 | 0 none +// | | | 1 requires device updates +// | | | 2..3 reserved +// +---------------------------+-----------+----------------------------------- +// | Sample input mode | 9..10 | 0 direct: process() function or EFFECT_CMD_CONFIGURE +// | | | command must specify a buffer descriptor +// | | | 1 provider: process() function uses the +// | | | bufferProvider indicated by the +// | | | EFFECT_CMD_CONFIGURE command to request input buffers. +// | | | 2 both: both input modes are supported +// | | | 3 reserved +// +---------------------------+-----------+----------------------------------- +// | Sample output mode | 11..12 | 0 direct: process() function or EFFECT_CMD_CONFIGURE +// | | | command must specify a buffer descriptor +// | | | 1 provider: process() function uses the +// | | | bufferProvider indicated by the +// | | | EFFECT_CMD_CONFIGURE command to request output buffers. +// | | | 2 both: both output modes are supported +// | | | 3 reserved +// +---------------------------+-----------+----------------------------------- + +// insert mode +#define EFFECT_FLAG_TYPE_MASK 0x00000003 +#define EFFECT_FLAG_TYPE_INSERT 0x00000000 +#define EFFECT_FLAG_TYPE_AUXILIARY 0x00000001 +#define EFFECT_FLAG_TYPE_REPLACE 0x00000002 + +// insert preference +#define EFFECT_FLAG_INSERT_MASK 0x0000001C +#define EFFECT_FLAG_INSERT_ANY 0x00000000 +#define EFFECT_FLAG_INSERT_FIRST 0x00000004 +#define EFFECT_FLAG_INSERT_LAST 0x00000008 +#define EFFECT_FLAG_INSERT_EXCLUSIVE 0x0000000C + + +// volume control +#define EFFECT_FLAG_VOLUME_MASK 0x00000060 +#define EFFECT_FLAG_VOLUME_CTRL 0x00000020 +#define EFFECT_FLAG_VOLUME_NONE 0x00000000 + +// device control +#define EFFECT_FLAG_DEVICE_MASK 0x00000180 +#define EFFECT_FLAG_DEVICE_IND 0x00000080 +#define EFFECT_FLAG_DEVICE_NONE 0x00000000 + +// sample input modes +#define EFFECT_FLAG_INPUT_MASK 0x00000600 +#define EFFECT_FLAG_INPUT_DIRECT 0x00000000 +#define EFFECT_FLAG_INPUT_PROVIDER 0x00000200 +#define EFFECT_FLAG_INPUT_BOTH 0x00000400 + +// sample output modes +#define EFFECT_FLAG_OUTPUT_MASK 0x00001800 +#define EFFECT_FLAG_OUTPUT_DIRECT 0x00000000 +#define EFFECT_FLAG_OUTPUT_PROVIDER 0x00000800 +#define EFFECT_FLAG_OUTPUT_BOTH 0x00001000 + +// forward definition of type audio_buffer_t +typedef struct audio_buffer_s audio_buffer_t; + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: process +// +// Description: Effect process function. Takes input samples as specified +// (count and location) in input buffer descriptor and output processed +// samples as specified in output buffer descriptor. If the buffer descriptor +// is not specified the function must use either the buffer or the +// buffer provider function installed by the EFFECT_CMD_CONFIGURE command. +// +// NOTE: the process() function implementation should be "real-time safe" that is +// it should not perform blocking calls: malloc/free, sleep, read/write/open/close, +// pthread_cond_wait/pthread_mutex_lock... +// +// Input: +// effect_interface_t: handle to the effect interface this function +// is called on. +// inBuffer: buffer descriptor indicating where to read samples to process. +// If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command. +// +// inBuffer: buffer descriptor indicating where to write processed samples. +// If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command. +// +// Output: +// returned value: 0 successful operation +// -EINVAL invalid interface handle or +// invalid input/output buffer description +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_process_t)(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: command +// +// Description: Send a command and receive a response to/from effect engine. +// +// Input: +// effect_interface_t: handle to the effect interface this function +// is called on. +// cmdCode: command code: the command can be a standardized command defined in +// effect_command_e (see below) or a proprietary command. +// cmdSize: size of command in bytes +// pCmdData: pointer to command data +// pReplyData: pointer to reply data +// +// Input/Output: +// replySize: maximum size of reply data as input +// actual size of reply data as output +// +// Output: +// returned value: 0 successful operation +// -EINVAL invalid interface handle or +// invalid command/reply size or format according to command code +// The return code should be restricted to indicate problems related to the this +// API specification. Status related to the execution of a particular command should be +// indicated as part of the reply field. +// +// *pReplyData updated with command response +// +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_command_t)(effect_interface_t self, int32_t cmdCode, int32_t cmdSize, void *pCmdData, int32_t *replySize, void *pReplyData); + + +// Effect control interface definition +struct effect_interface_s { + effect_process_t process; + effect_command_t command; +}; + + +//--- Standardized command codes for command function +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | description | command code | command format | reply format +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | Initialize effect engine: | EFFECT_CMD_INIT | size: 0 | size: sizeof(int) +// | All configurations return to | | data: N/A | data: status +// | default | | | +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | Apply new audio parameters | EFFECT_CMD_CONFIGURE | size: sizeof(effect_config_t) | size: sizeof(int) +// | configurations for input and | | data: effect_config_t | data: status +// | output buffers | | | +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | Reset effect engine: keep | EFFECT_CMD_RESET | size: 0 | size: 0 +// | configuration but reset state | | data: N/A | data: N/A +// | and buffer content. | | | +// | Called by the framework before | | | +// | enabling the effect | | | +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | Enable the process | EFFECT_CMD_ENABLE | size: 0 | size: sizeof(int) +// | Called by the framework before | | data: N/A | data: status +// | the first call to process() | | | +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | Disable the process | EFFECT_CMD_DISABLE | size: 0 | size: sizeof(int) +// | Called by the framework after | | data: N/A | data: status +// | the last call to process() | | | +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | Set a parameter and apply it | EFFECT_CMD_SET_PARAM | size: sizeof(effect_param_t) | size: sizeof(int) +// | immediately | | + size of param + value | data: status +// | | | data: effect_param_t | +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | Set a parameter but apply it | EFFECT_CMD_SET_PARAM_DEFERRED | size: sizeof(effect_param_t) | size: 0 +// | only when receiving command | | + size of param + value | data: N/A +// | EFFECT_CMD_SET_PARAM_COMMIT | | data: effect_param_t | +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | Apply all previously received | EFFECT_CMD_SET_PARAM_COMMIT | size: 0 | size: sizeof(int) +// | EFFECT_CMD_SET_PARAM_DEFERRED | | data: N/A | data: status +// | commands | | | +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | Get a parameter value | EFFECT_CMD_GET_PARAM | size: sizeof(effect_param_t) | size: sizeof(effect_param_t) +// | | | + size of param | + size of param + value +// | | | data: effect_param_t | data: effect_param_t +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | Set the rendering device the | EFFECT_CMD_SET_DEVICE | size: sizeof(uint32_t) | size: 0 +// | audio output path is connected | | data: audio_device_e | data: N/A +// | to. See audio_device_e in | | | +// | AudioCommon.h for device values| | | +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | Set and get volume. Used by | EFFECT_CMD_SET_VOLUME | size: n * sizeof(uint32_t) | size: n * sizeof(uint32_t) +// | audio framework to delegate | | data: volume for each channel | data: volume for each channel +// | volume control to effect engine| | defined in effect_config_t in | defined in effect_config_t in +// | The engine must return the | | 8.24 fixed point format | 8.24 fixed point format +// | volume that should be applied | | | +// | before the effect is processed | | | +// | The overall volume (the volume | | | +// | actually applied by the effect | | | +// | multiplied by the returned | | | +// | value) should match the | | | +// | requested value | | | +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- +// | All proprietary effect commands| EFFECT_CMD_FIRST_PROPRIETARY | | +// | must use command codes above | | | +// | this value. The size and format| | | +// | of command and response fields | | | +// | is free in this case. | | | +// +--------------------------------+-------------------------------+-------------------------------+-------------------------- + + +enum effect_command_e { + EFFECT_CMD_INIT, // initialize effect engine + EFFECT_CMD_CONFIGURE, // configure effect engine (see effect_config_t) + EFFECT_CMD_RESET, // reset effect engine + EFFECT_CMD_ENABLE, // enable effect process + EFFECT_CMD_DISABLE, // disable effect process + EFFECT_CMD_SET_PARAM, // set parameter immediately (see effect_param_t) + EFFECT_CMD_SET_PARAM_DEFERRED, // set parameter deferred + EFFECT_CMD_SET_PARAM_COMMIT, // commit previous set parameter deferred + EFFECT_CMD_GET_PARAM, // get parameter + EFFECT_CMD_SET_DEVICE, // set audio device (see audio_device_e in AudioCommon.h) + EFFECT_CMD_SET_VOLUME, // set volume + EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code +}; + +// Audio buffer descriptor used by process(), bufferProvider() functions and buffer_config_t structure +// Multi-channel audio is always interleaved. The channel order is from LSB to MSB with regard to the +// channel mask definition in audio_channels_e (AudioCommon.h) e.g : +// Stereo: left, right +// 5 point 1: front left, front right, front center, low frequency, back left, back right +// The buffer size is expressed in frame count, a frame being composed of samples for all +// channels at a given time +struct audio_buffer_s { + size_t frameCount; // number of frames in buffer + union { + void* raw; // raw pointer to start of buffer + int32_t* s32; // pointer to signed 32 bit data at start of buffer + int16_t* s16; // pointer to signed 16 bit data at start of buffer + uint8_t* u8; // pointer to unsigned 8 bit data at start of buffer + }; +}; + +// the buffer_provider_s structure contains functions that can be used +// by the effect engine process() function to query and release input +// or output audio buffer. +// The getBuffer() function is called to retrieve a buffer where data +// should read from or written to by process() function. +// The releaseBuffer() function MUST be called when the buffer retrieved +// with getBuffer() is not needed anymore. +// The process function should use the buffer provider mechanism to retrieve +// input or output buffer if the inBuffer or outBuffer passed as argument is NULL +// and the buffer configuration (buffer_config_t) given by the EFFECT_CMD_CONFIGURE +// command did not specify an audio buffer. + +typedef int32_t (* buffer_function_t)(void *cookie, audio_buffer_t *buffer); + +typedef struct buffer_provider_s { + buffer_function_t getBuffer; // retrieve next buffer + buffer_function_t releaseBuffer; // release used buffer + void *cookie; // for use by client of buffer provider functions +} buffer_provider_t; + +// The buffer_config_s structure specifies the input or output audio format +// to be used by the effect engine. It is part of the effect_config_t +// structure that defines both input and output buffer configurations and is +// passed by the EFFECT_CMD_CONFIGURE command. +typedef struct buffer_config_s { + audio_buffer_t buffer; // buffer for use by process() function is not passed explicitly + uint32_t samplingRate; // sampling rate + uint32_t channels; // channel mask (see audio_channels_e in AudioCommon.h) + buffer_provider_t bufferProvider; // buffer provider + uint8_t format; // PCM format (see audio_format_e in AudioCommon.h) + uint8_t accessMode; // read/write or accumulate in buffer (effect_buffer_access_e) + uint16_t mask; // indicates which of the above fields is valid +} buffer_config_t; + +// values for "accessMode" field of buffer_config_t: +// overwrite, read only, accumulate (read/modify/write) +enum effect_buffer_access_e { + EFFECT_BUFFER_ACCESS_WRITE, + EFFECT_BUFFER_ACCESS_READ, + EFFECT_BUFFER_ACCESS_ACCUMULATE + +}; + +// values for bit field "mask" in buffer_config_t. If a bit is set, the corresponding field +// in buffer_config_t must be taken into account when executing the EFFECT_CMD_CONFIGURE command +#define EFFECT_CONFIG_BUFFER 0x0001 // buffer field must be taken into account +#define EFFECT_CONFIG_SMP_RATE 0x0002 // samplingRate field must be taken into account +#define EFFECT_CONFIG_CHANNELS 0x0004 // channels field must be taken into account +#define EFFECT_CONFIG_FORMAT 0x0008 // format field must be taken into account +#define EFFECT_CONFIG_ACC_MODE 0x0010 // accessMode field must be taken into account +#define EFFECT_CONFIG_PROVIDER 0x0020 // bufferProvider field must be taken into account +#define EFFECT_CONFIG_ALL (EFFECT_CONFIG_BUFFER | EFFECT_CONFIG_SMP_RATE | \ + EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT | \ + EFFECT_CONFIG_ACC_MODE | EFFECT_CONFIG_PROVIDER) + +// effect_config_s structure describes the format of the pCmdData argument of EFFECT_CMD_CONFIGURE command +// to configure audio parameters and buffers for effect engine input and output. +typedef struct effect_config_s { + buffer_config_t inputCfg; + buffer_config_t outputCfg;; +} effect_config_t; + +// effect_param_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_PARAM +// command and pCmdData and pReplyData of EFFECT_CMD_GET_PARAM command. +// psize and vsize represent the actual size of parameter and value. +// +// NOTE: the start of value field inside the data field is always on a 32 bit boundary: +// +// +-----------+ +// | status | sizeof(int) +// +-----------+ +// | psize | sizeof(int) +// +-----------+ +// | vsize | sizeof(int) +// +-----------+ +// | | | | +// ~ parameter ~ > psize | +// | | | > ((psize - 1)/sizeof(int) + 1) * sizeof(int) +// +-----------+ | +// | padding | | +// +-----------+ +// | | | +// ~ value ~ > vsize +// | | | +// +-----------+ + +typedef struct effect_param_s { + int32_t status; // Transaction status (unused for command, used for reply) + uint32_t psize; // Parameter size + uint32_t vsize; // Value size + char data[]; // Start of Parameter + Value data +} effect_param_t; + + +///////////////////////////////////////////////// +// Effect library interface +///////////////////////////////////////////////// + +// An effect library is required to implement and expose the following functions +// to enable effect enumeration and instantiation. The name of these functions must be as +// specified here as the effect framework will get the function address with dlsym(): +// +// - effect_QueryNumberEffects_t EffectQueryNumberEffects; +// - effect_QueryNextEffect_t EffectQueryNext; +// - effect_CreateEffect_t EffectCreate; +// - effect_ReleaseEffect_t EffectRelease; + + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectQueryNumberEffects +// +// Description: Returns the number of different effect exposed by the +// library. Each effect must have a unique effect uuid (see +// effect_descriptor_t). This function together with EffectQueryNext() +// is used to enumerate all effects present in the library. +// Each time EffectQueryNumberEffects() is called, the library must +// reset the index of the effect descriptor returned by next call to +// EffectQueryNext() to restart enumeration from the beginning. +// +// Input/Output: +// pNumEffects: address where the number of effects should be returned. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV library failed to initialize +// -EINVAL invalid pNumEffects +// *pNumEffects: updated with number of effects in library +// +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_QueryNumberEffects_t)(int32_t *pNumEffects); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectQueryNext +// +// Description: Returns a descriptor of the next available effect. +// See effect_descriptor_t for details on effect descriptors. +// This function together with EffectQueryNext() is used to enumerate all +// effects present in the library. The enumeration sequence is: +// EffectQueryNumberEffects(&num_effects); +// while (num_effects--) +// EffectQueryNext(); +// +// Input/Output: +// pDescriptor: address where to return the effect descriptor. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV library failed to initialize +// -EINVAL invalid pDescriptor +// -ENOENT no more effect available +// *pDescriptor: updated with the effect descriptor. +// +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_QueryNextEffect_t)(effect_descriptor_t *pDescriptor); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectCreate +// +// Description: Creates an effect engine of the specified type and returns an +// effect control interface on this engine. The function will allocate the +// resources for an instance of the requested effect engine and return +// a handle on the effect control interface. +// +// Input: +// pEffectUuid: pointer to the effect uuid. +// +// Input/Output: +// pInterface: address where to return the effect interface. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV library failed to initialize +// -EINVAL invalid pEffectUuid or pInterface +// -ENOENT No effect with this uuid found +// *pInterface: updated with the effect interface handle. +// +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_CreateEffect_t)(effect_uuid_t *uuid, effect_interface_t *pInterface); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectRelease +// +// Description: Releases the effect engine whose handle is given as argument. +// All resources allocated to this particular instance of the effect are +// released. +// +// Input: +// interface: handle on the effect interface to be released. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV library failed to initialize +// -EINVAL invalid interface handle +// +//////////////////////////////////////////////////////////////////////////////// +typedef int32_t (*effect_ReleaseEffect_t)(effect_interface_t interface); + + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTAPI_H_*/ diff --git a/include/media/EffectEqualizerApi.h b/include/media/EffectEqualizerApi.h new file mode 100644 index 0000000000000000000000000000000000000000..e3069d51e53bf2bdbb2341e7cfe30ce9d73bf3e9 --- /dev/null +++ b/include/media/EffectEqualizerApi.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 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 ANDROID_EFFECTEQUALIZERAPI_H_ +#define ANDROID_EFFECTEQUALIZERAPI_H_ + +#include + +#if __cplusplus +extern "C" { +#endif + +//TODO replace by openSL ES include when available +static const effect_uuid_t SL_IID_EQUALIZER_ = { 0x0bed4300, 0xddd6, 0x11db, 0x8f34, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const effect_uuid_t * const SL_IID_EQUALIZER = &SL_IID_EQUALIZER_; + +/* enumerated parameters for Equalizer effect */ +typedef enum +{ + EQ_PARAM_NUM_BANDS, // Gets the number of frequency bands that the equalizer supports. + EQ_PARAM_LEVEL_RANGE, // Returns the minimum and maximum band levels supported. + EQ_PARAM_BAND_LEVEL, // Gets/Sets the gain set for the given equalizer band. + EQ_PARAM_CENTER_FREQ, // Gets the center frequency of the given band. + EQ_PARAM_BAND_FREQ_RANGE, // Gets the frequency range of the given frequency band. + EQ_PARAM_GET_BAND, // Gets the band that has the most effect on the given frequency. + EQ_PARAM_CUR_PRESET, // Gets/Sets the current preset. + EQ_PARAM_GET_NUM_OF_PRESETS, // Gets the total number of presets the equalizer supports. + EQ_PARAM_GET_PRESET_NAME // Gets the preset name based on the index. +} t_equalizer_params; + + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTEQUALIZERAPI_H_*/ diff --git a/include/media/EffectFactoryApi.h b/include/media/EffectFactoryApi.h new file mode 100644 index 0000000000000000000000000000000000000000..8179c234d339c90009d50755299a281664f93a07 --- /dev/null +++ b/include/media/EffectFactoryApi.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2010 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 ANDROID_EFFECTFACTORYAPI_H_ +#define ANDROID_EFFECTFACTORYAPI_H_ + +#include +#include +#include +#include + +#if __cplusplus +extern "C" { +#endif + +///////////////////////////////////////////////// +// Effect factory interface +///////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectQueryNumberEffects +// +// Description: Returns the number of different effect in all loaded libraries. +// Each effect must have a different effect uuid (see +// effect_descriptor_t). This function together with EffectQueryNext() +// is used to enumerate all effects present in all loaded libraries. +// Each time EffectQueryNumberEffects() is called, the factory must +// reset the index of the effect descriptor returned by next call to +// EffectQueryNext() to restart enumeration from the beginning. +// +// Input/Output: +// pNumEffects: address where the number of effects should be returned. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV factory failed to initialize +// -EINVAL invalid pNumEffects +// *pNumEffects: updated with number of effects in factory +// +//////////////////////////////////////////////////////////////////////////////// +int EffectQueryNumberEffects(int *pNumEffects); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectQueryNext +// +// Description: Returns a descriptor of the next available effect. +// See effect_descriptor_t for a details on effect descriptor. +// This function together with EffectQueryNext() is used to enumerate all +// effects present in all loaded libraries. The enumeration sequence is: +// EffectQueryNumberEffects(&num_effects); +// while (num_effects--) +// EffectQueryNext(); +// +// Input/Output: +// pDescriptor: address where to return the effect descriptor. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV factory failed to initialize +// -EINVAL invalid pDescriptor +// -ENOENT no more effect available +// *pDescriptor: updated with the effect descriptor. +// +//////////////////////////////////////////////////////////////////////////////// +int EffectQueryNext(effect_descriptor_t *pDescriptor); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectCreate +// +// Description: Creates an effect engine of the specified type and returns an +// effect control interface on this engine. The function will allocate the +// resources for an instance of the requested effect engine and return +// a handler on the effect control interface. +// +// Input: +// pEffectUuid: pointer to the effect uuid. +// +// Input/Output: +// pInterface: address where to return the effect interface. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV factory failed to initialize +// -EINVAL invalid pEffectUuid or pInterface +// -ENOENT No effect with this uuid found +// *pInterface: updated with the effect interface. +// +//////////////////////////////////////////////////////////////////////////////// +int EffectCreate(effect_uuid_t *pEffectUuid, effect_interface_t *pInterface); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectRelease +// +// Description: Releases the effect engine whose handler is given as argument. +// All resources allocated to this particular instance of the effect are +// released. +// +// Input: +// interface: handler on the effect interface to be released. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV factory failed to initialize +// -EINVAL invalid interface handler +// +//////////////////////////////////////////////////////////////////////////////// +int EffectRelease(effect_interface_t interface); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectLoadLibrary +// +// Description: Loads the effect library which path is given as first argument. +// This must be the full path of a dynamic library (.so) implementing one or +// more effect engines and exposing the effect library interface described in +// EffectApi.h. The function returns a handle on the library for used by +// further call to EffectUnloadLibrary() to unload the library. +// +// Input: +// libPath: full path of the dynamic library file in the file system. +// +// handle: address where to return the library handle +// +// Output: +// returned value: 0 successful operation. +// -ENODEV Effect factory not initialized or +// library could not be loaded or +// library does not implement required functions +// -EINVAL invalid libPath string or handle +// +//////////////////////////////////////////////////////////////////////////////// +int EffectLoadLibrary(const char *libPath, int *handle); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectUnloadLibrary +// +// Description: Unloads the effect library which handle is given as argument. +// +// Input: +// handle: library handle +// +// Output: +// returned value: 0 successful operation. +// -ENODEV Effect factory not initialized +// -ENOENT invalid handle +// +//////////////////////////////////////////////////////////////////////////////// +int EffectUnloadLibrary(int handle); + + + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectGetDescriptor +// +// Description: Returns the descriptor of the effect which uuid is pointed +// to by first argument. +// +// Input: +// pEffectUuid: pointer to the effect uuid. +// +// Input/Output: +// pDescriptor: address where to return the effect descriptor. +// +// Output: +// returned value: 0 successful operation. +// -ENODEV factory failed to initialize +// -EINVAL invalid pEffectUuid or pDescriptor +// -ENOENT No effect with this uuid found +// *pDescriptor: updated with the effect descriptor. +// +//////////////////////////////////////////////////////////////////////////////// +int EffectGetDescriptor(effect_uuid_t *pEffectUuid, effect_descriptor_t *pDescriptor); + +//////////////////////////////////////////////////////////////////////////////// +// +// Function: EffectIsNullUuid +// +// Description: Helper function to compare effect uuid to EFFECT_UUID_NULL +// +// Input: +// pEffectUuid: pointer to effect uuid to compare to EFFECT_UUID_NULL. +// +// Output: +// returned value: 0 if uuid is different from EFFECT_UUID_NULL. +// 1 if uuid is equal to EFFECT_UUID_NULL. +// +//////////////////////////////////////////////////////////////////////////////// +int EffectIsNullUuid(effect_uuid_t *pEffectUuid); + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTFACTORYAPI_H_*/ diff --git a/include/media/EffectReverbApi.h b/include/media/EffectReverbApi.h new file mode 100644 index 0000000000000000000000000000000000000000..6371adba1c26ebb10fd813a24be1e8226fdbc6ed --- /dev/null +++ b/include/media/EffectReverbApi.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2010 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 ANDROID_EFFECTREVERBAPI_H_ +#define ANDROID_EFFECTREVERBAPI_H_ + +#include + +#if __cplusplus +extern "C" { +#endif + +// TODO: include OpenSLES_IID.h instead +static const effect_uuid_t SL_IID_ENVIRONMENTALREVERB_ = { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, { 0x4e, 0x23, 0x4d, 0x6, 0x83, 0x9e } }; +const effect_uuid_t * const SL_IID_ENVIRONMENTALREVERB = &SL_IID_ENVIRONMENTALREVERB_; + +static const effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_; + +/* enumerated parameter settings for Reverb effect */ +typedef enum +{ + REVERB_PARAM_BYPASS, + REVERB_PARAM_PRESET, + // Parameters below are as defined in OpenSL ES specification for environmental reverb interface + REVERB_PARAM_ROOM_LEVEL, // in millibels, range -6000 to 0 + REVERB_PARAM_ROOM_HF_LEVEL, // in millibels, range -4000 to 0 + REVERB_PARAM_DECAY_TIME, // in milliseconds, range 100 to 20000 + REVERB_PARAM_DECAY_HF_RATIO, // in permilles, range 100 to 1000 + REVERB_PARAM_REFLECTIONS_LEVEL, // in millibels, range -6000 to 0 + REVERB_PARAM_REFLECTIONS_DELAY, // in milliseconds, range 0 to 65 + REVERB_PARAM_REVERB_LEVEL, // in millibels, range -6000 to 0 + REVERB_PARAM_REVERB_DELAY, // in milliseconds, range 0 to 65 + REVERB_PARAM_DIFFUSION, // in permilles, range 0 to 1000 + REVERB_PARAM_DENSITY, // in permilles, range 0 to 1000 + REVERB_PARAM_PROPERTIES +} t_reverb_params; + + +typedef enum +{ + REVERB_PRESET_LARGE_HALL, + REVERB_PRESET_HALL, + REVERB_PRESET_CHAMBER, + REVERB_PRESET_ROOM, +} t_reverb_presets; + +//t_reverb_properties is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification. +typedef struct s_reverb_properties { + int16_t roomLevel; + int16_t roomHFLevel; + int32_t decayTime; + int16_t decayHFRatio; + int16_t reflectionsLevel; + int32_t reflectionsDelay; + int32_t reverbDelay; + int16_t reverbLevel; + int16_t diffusion; + int16_t density; + int16_t padding; +} t_reverb_properties; + + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTREVERBAPI_H_*/ diff --git a/include/media/IEffect.h b/include/media/IEffect.h new file mode 100644 index 0000000000000000000000000000000000000000..6dad393b35c0abc8b8b9e8cd7552747993727792 --- /dev/null +++ b/include/media/IEffect.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 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 ANDROID_IEFFECT_H +#define ANDROID_IEFFECT_H + +#include +#include +#include +#include + +namespace android { + +class IEffect: public IInterface +{ +public: + DECLARE_META_INTERFACE(Effect); + + virtual status_t enable() = 0; + + virtual status_t disable() = 0; + + virtual status_t command(int cmdCode, int cmdSize, void *pCmdData, int *pReplySize, void *pReplyData) = 0; + + virtual void disconnect() = 0; + + virtual sp getCblk() const = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnEffect: public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IEFFECT_H diff --git a/include/media/IEffectClient.h b/include/media/IEffectClient.h new file mode 100644 index 0000000000000000000000000000000000000000..d22daf81e7f8e634204bd09a84db2919d2b66053 --- /dev/null +++ b/include/media/IEffectClient.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 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 ANDROID_IEFFECTCLIENT_H +#define ANDROID_IEFFECTCLIENT_H + +#include +#include +#include +#include + +namespace android { + +class IEffectClient: public IInterface +{ +public: + DECLARE_META_INTERFACE(EffectClient); + + virtual void controlStatusChanged(bool controlGranted) = 0; + virtual void enableStatusChanged(bool enabled) = 0; + virtual void commandExecuted(int cmdCode, int cmdSize, void *pCmdData, int replySize, void *pReplyData) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnEffectClient: public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IEFFECTCLIENT_H diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index 9ea6c7bb4560dbeb85c25fe2d6ba07558f40a254..eead1663753eb6556c74aa79144a9965928c5b8e 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -135,7 +135,8 @@ enum media_recorder_error_type { enum media_recorder_info_type { MEDIA_RECORDER_INFO_UNKNOWN = 1, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800, - MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801 + MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801, + MEDIA_RECORDER_INFO_STOP_PREMATURELY = 802 }; // ---------------------------------------------------------------------------- diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h index 372909a0bfbbd709dd9ba28bb5a854b2883bbad8..dd1180948d77ddb0eedc2f2d7d4e3a0ff333d6d8 100644 --- a/include/media/stagefright/AMRWriter.h +++ b/include/media/stagefright/AMRWriter.h @@ -42,18 +42,20 @@ protected: virtual ~AMRWriter(); private: - Mutex mLock; - FILE *mFile; status_t mInitCheck; sp mSource; bool mStarted; volatile bool mDone; - bool mReachedEOS; + volatile bool mReachedEOS; pthread_t mThread; + int64_t mEstimatedSizeBytes; + int64_t mEstimatedDurationUs; static void *ThreadWrapper(void *); void threadFunc(); + bool exceedsFileSizeLimit(); + bool exceedsFileDurationLimit(); AMRWriter(const AMRWriter &); AMRWriter &operator=(const AMRWriter &); diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h index eb0014092ddd0133ae871c10c2535d183f247e50..251937993f1d6ff957d2e387133ae6e7cbf3918a 100644 --- a/include/media/stagefright/AudioSource.h +++ b/include/media/stagefright/AudioSource.h @@ -46,7 +46,7 @@ protected: virtual ~AudioSource(); private: - enum { kMaxBufferSize = 8192 }; + enum { kMaxBufferSize = 2048 }; AudioRecord *mRecord; status_t mInitCheck; diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h index ea435de82719ee31f27471acb0b79a5ff4881ff8..0c7bf6fe4f10f1652bcd535eec0d59b8654b64a0 100644 --- a/include/media/stagefright/CameraSource.h +++ b/include/media/stagefright/CameraSource.h @@ -28,18 +28,15 @@ namespace android { class ICamera; class IMemory; -class ISurface; class Camera; -class CameraSource : public MediaSource { +class CameraSource : public MediaSource, public MediaBufferObserver { public: static CameraSource *Create(); - static CameraSource *CreateFromICamera(const sp &icamera); + static CameraSource *CreateFromCamera(const sp &camera); virtual ~CameraSource(); - void setPreviewSurface(const sp &surface); - virtual status_t start(MetaData *params = NULL); virtual status_t stop(); @@ -48,25 +45,34 @@ public: virtual status_t read( MediaBuffer **buffer, const ReadOptions *options = NULL); + virtual void signalBufferReturned(MediaBuffer* buffer); + private: friend class CameraSourceListener; sp mCamera; - sp mPreviewSurface; Mutex mLock; Condition mFrameAvailableCondition; - List > mFrames; + Condition mFrameCompleteCondition; + List > mFramesReceived; + List > mFramesBeingEncoded; List mFrameTimes; int mWidth, mHeight; int64_t mFirstFrameTimeUs; - int32_t mNumFrames; + int64_t mLastFrameTimestampUs; + int32_t mNumFramesReceived; + int32_t mNumFramesEncoded; + int32_t mNumFramesDropped; bool mStarted; CameraSource(const sp &camera); - void dataCallback(int32_t msgType, const sp &data); + void dataCallbackTimestamp( + int64_t timestampUs, int32_t msgType, const sp &data); + + void releaseQueuedFrames(); CameraSource(const CameraSource &); CameraSource &operator=(const CameraSource &); diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h index 6b93f197c768413373819e8c7f0c0def5822d250..3c85eca08364a2ae796e67ccf3a78ba837c95b42 100644 --- a/include/media/stagefright/MPEG4Writer.h +++ b/include/media/stagefright/MPEG4Writer.h @@ -49,6 +49,8 @@ public: void writeFourcc(const char *fourcc); void write(const void *data, size_t size); void endBox(); + uint32_t interleaveDuration() const { return mInterleaveDurationUs; } + status_t setInterleaveDuration(uint32_t duration); protected: virtual ~MPEG4Writer(); @@ -59,14 +61,33 @@ private: FILE *mFile; off_t mOffset; off_t mMdatOffset; + uint8_t *mMoovBoxBuffer; + off_t mMoovBoxBufferOffset; + bool mWriteMoovBoxToMemory; + off_t mFreeBoxOffset; + bool mStreamableFile; + off_t mEstimatedMoovBoxSize; + uint32_t mInterleaveDurationUs; + int64_t mStartTimestampUs; Mutex mLock; List mTracks; List mBoxes; - off_t addSample(MediaBuffer *buffer); - off_t addLengthPrefixedSample(MediaBuffer *buffer); + void setStartTimestamp(int64_t timeUs); + int64_t getStartTimestamp(); // Not const + + void lock(); + void unlock(); + + // Acquire lock before calling these methods + off_t addSample_l(MediaBuffer *buffer); + off_t addLengthPrefixedSample_l(MediaBuffer *buffer); + + inline size_t write(const void *ptr, size_t size, size_t nmemb, FILE* stream); + bool exceedsFileSizeLimit(); + bool exceedsFileDurationLimit(); MPEG4Writer(const MPEG4Writer &); MPEG4Writer &operator=(const MPEG4Writer &); diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h index 207195a4d6886f0cb6a786f2e052f256454b759b..a9a0d55bd06d2e9f0fb182eeca29d169fd7010f7 100644 --- a/include/media/stagefright/MediaDefs.h +++ b/include/media/stagefright/MediaDefs.h @@ -22,6 +22,7 @@ namespace android { extern const char *MEDIA_MIMETYPE_IMAGE_JPEG; +extern const char *MEDIA_MIMETYPE_VIDEO_VPX; extern const char *MEDIA_MIMETYPE_VIDEO_AVC; extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4; extern const char *MEDIA_MIMETYPE_VIDEO_H263; @@ -38,6 +39,7 @@ extern const char *MEDIA_MIMETYPE_AUDIO_RAW; extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4; extern const char *MEDIA_MIMETYPE_CONTAINER_WAV; extern const char *MEDIA_MIMETYPE_CONTAINER_OGG; +extern const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA; } // namespace android diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h index b8232c66986273ba22b74b1733dedc7232dccea5..b15f69cf9e782d10f1125a4f2c58779084b887a7 100644 --- a/include/media/stagefright/MediaWriter.h +++ b/include/media/stagefright/MediaWriter.h @@ -19,6 +19,7 @@ #define MEDIA_WRITER_H_ #include +#include namespace android { @@ -31,10 +32,23 @@ struct MediaWriter : public RefBase { virtual bool reachedEOS() = 0; virtual status_t start() = 0; virtual void stop() = 0; + virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; } + virtual void setMaxFileDuration(int64_t durationUs) { mMaxFileDurationLimitUs = durationUs; } + virtual void setListener(const sp& listener) { + mListener = listener; + } protected: virtual ~MediaWriter() {} - + int64_t mMaxFileSizeLimitBytes; + int64_t mMaxFileDurationLimitUs; + sp mListener; + + void notify(int msg, int ext1, int ext2) { + if (mListener != NULL) { + mListener->notify(msg, ext1, ext2); + } + } private: MediaWriter(const MediaWriter &); MediaWriter &operator=(const MediaWriter &); diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index 1d76a1ad0185e0005926ebc4ff4e1df1796484bb..f836c55929d360349171dd1f15a78cae39787e35 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -156,8 +156,8 @@ private: void setComponentRole(); - void setAMRFormat(bool isWAMR); - void setAACFormat(int32_t numChannels, int32_t sampleRate); + void setAMRFormat(bool isWAMR, int32_t bitRate); + void setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate); status_t setVideoPortFormatType( OMX_U32 portIndex, diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index 8e2db20c95e856b4711e3479718d97a2ba5a7c7b..cd47fdfb50d8a792ece8cf45bb7530a633d10e0e 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -32,6 +32,18 @@ namespace android { #define MAX_RUN_TIMEOUT_MS 1000 #define WAIT_PERIOD_MS 10 +#define CBLK_UNDERRUN_MSK 0x0001 +#define CBLK_UNDERRUN_ON 0x0001 // underrun (out) or overrrun (in) indication +#define CBLK_UNDERRUN_OFF 0x0000 // no underrun +#define CBLK_DIRECTION_MSK 0x0002 +#define CBLK_DIRECTION_OUT 0x0002 // this cblk is for an AudioTrack +#define CBLK_DIRECTION_IN 0x0000 // this cblk is for an AudioRecord +#define CBLK_FORCEREADY_MSK 0x0004 +#define CBLK_FORCEREADY_ON 0x0004 // track is considered ready immediately by AudioFlinger +#define CBLK_FORCEREADY_OFF 0x0000 // track is ready when buffer full +#define CBLK_INVALID_MSK 0x0008 +#define CBLK_INVALID_ON 0x0008 // track buffer is invalidated by AudioFlinger: must be re-created +#define CBLK_INVALID_OFF 0x0000 struct audio_track_cblk_t { @@ -44,12 +56,12 @@ struct audio_track_cblk_t volatile uint32_t server; uint32_t userBase; uint32_t serverBase; - void* buffers; - uint32_t frameCount; - // Cache line boundary - uint32_t loopStart; - uint32_t loopEnd; - int loopCount; + void* buffers; + uint32_t frameCount; + // Cache line boundary + uint32_t loopStart; + uint32_t loopEnd; + int loopCount; volatile union { uint16_t volume[2]; uint32_t volumeLR; @@ -58,15 +70,16 @@ struct audio_track_cblk_t // NOTE: audio_track_cblk_t::frameSize is not equal to AudioTrack::frameSize() for // 8 bit PCM data: in this case, mCblk->frameSize is based on a sample size of // 16 bit because data is converted to 16 bit before being stored in buffer - uint32_t frameSize; - uint8_t channels; - uint8_t flowControlFlag; // underrun (out) or overrrun (in) indication - uint8_t out; // out equals 1 for AudioTrack and 0 for AudioRecord - uint8_t forceReady; + + uint8_t frameSize; + uint8_t channelCount; + uint16_t flags; + uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger uint16_t waitTimeMs; // Cumulated wait time - // Cache line boundary (32 bytes) + uint32_t reserved; + // Cache line boundary (32 bytes) audio_track_cblk_t(); uint32_t stepUser(uint32_t frameCount); bool stepServer(uint32_t frameCount); diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h index 9b5a1e0f53a47a61eef58a2d73637cd1bb1b19f2..dcce25e92329be4c4f32aea87877b39fa0d9b2ec 100644 --- a/include/private/surfaceflinger/SharedBufferStack.h +++ b/include/private/surfaceflinger/SharedBufferStack.h @@ -55,12 +55,6 @@ namespace android { * */ -// When changing these values, the COMPILE_TIME_ASSERT at the end of this -// file need to be updated. -const unsigned int NUM_LAYERS_MAX = 31; -const unsigned int NUM_BUFFER_MAX = 4; -const unsigned int NUM_DISPLAY_MAX = 4; - // ---------------------------------------------------------------------------- class Region; @@ -69,7 +63,11 @@ class SharedClient; // ---------------------------------------------------------------------------- -// should be 128 bytes (32 longs) +// 4 * (11 + 7 + (1 + 2*NUM_RECT_MAX) * NUM_BUFFER_MAX) * NUM_LAYERS_MAX +// 4 * (11 + 7 + (1 + 2*7)*16) * 31 +// 1032 * 31 +// = ~27 KiB (31992) + class SharedBufferStack { friend class SharedClient; @@ -78,21 +76,38 @@ class SharedBufferStack friend class SharedBufferServer; public: - struct FlatRegion { // 12 bytes - static const unsigned int NUM_RECT_MAX = 1; - uint32_t count; - uint16_t rects[4*NUM_RECT_MAX]; - }; - + // When changing these values, the COMPILE_TIME_ASSERT at the end of this + // file need to be updated. + static const unsigned int NUM_LAYERS_MAX = 31; + static const unsigned int NUM_BUFFER_MAX = 16; + static const unsigned int NUM_BUFFER_MIN = 2; + static const unsigned int NUM_DISPLAY_MAX = 4; + struct Statistics { // 4 longs typedef int32_t usecs_t; usecs_t totalTime; usecs_t reserved[3]; }; + + struct SmallRect { + uint16_t l, t, r, b; + }; + + struct FlatRegion { // 52 bytes = 4 * (1 + 2*N) + static const unsigned int NUM_RECT_MAX = 6; + uint32_t count; + SmallRect rects[NUM_RECT_MAX]; + }; + + struct BufferData { + FlatRegion dirtyRegion; + SmallRect crop; + }; SharedBufferStack(); void init(int32_t identity); status_t setDirtyRegion(int buffer, const Region& reg); + status_t setCrop(int buffer, const Rect& reg); Region getDirtyRegion(int buffer) const; // these attributes are part of the conditions/updates @@ -104,24 +119,24 @@ public: // not part of the conditions volatile int32_t reallocMask; + volatile int8_t index[NUM_BUFFER_MAX]; int32_t identity; // surface's identity (const) - int32_t reserved32[9]; + int32_t reserved32[2]; Statistics stats; - FlatRegion dirtyRegion[NUM_BUFFER_MAX]; // 12*4=48 bytes + int32_t reserved; + BufferData buffers[NUM_BUFFER_MAX]; // 960 bytes }; // ---------------------------------------------------------------------------- -// 4 KB max +// 32 KB max class SharedClient { public: SharedClient(); ~SharedClient(); - status_t validate(size_t token) const; - uint32_t getIdentity(size_t token) const; private: friend class SharedBufferBase; @@ -131,7 +146,7 @@ private: // FIXME: this should be replaced by a lock-less primitive Mutex lock; Condition cv; - SharedBufferStack surfaces[ NUM_LAYERS_MAX ]; + SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ]; }; // ============================================================================ @@ -139,18 +154,17 @@ private: class SharedBufferBase { public: - SharedBufferBase(SharedClient* sharedClient, int surface, int num, + SharedBufferBase(SharedClient* sharedClient, int surface, int32_t identity); ~SharedBufferBase(); - uint32_t getIdentity(); status_t getStatus() const; + int32_t getIdentity() const; size_t getFrontBuffer() const; String8 dump(char const* prefix) const; protected: SharedClient* const mSharedClient; SharedBufferStack* const mSharedStack; - const int mNumBuffers; const int mIdentity; friend struct Update; @@ -160,60 +174,21 @@ protected: SharedBufferStack& stack; inline ConditionBase(SharedBufferBase* sbc) : stack(*sbc->mSharedStack) { } + virtual ~ConditionBase() { }; + virtual bool operator()() const = 0; + virtual const char* name() const = 0; }; + status_t waitForCondition(const ConditionBase& condition); struct UpdateBase { SharedBufferStack& stack; inline UpdateBase(SharedBufferBase* sbb) : stack(*sbb->mSharedStack) { } }; - - template - status_t waitForCondition(T condition); - template status_t updateCondition(T update); }; -template -status_t SharedBufferBase::waitForCondition(T condition) -{ - const SharedBufferStack& stack( *mSharedStack ); - SharedClient& client( *mSharedClient ); - const nsecs_t TIMEOUT = s2ns(1); - Mutex::Autolock _l(client.lock); - while ((condition()==false) && - (stack.identity == mIdentity) && - (stack.status == NO_ERROR)) - { - status_t err = client.cv.waitRelative(client.lock, TIMEOUT); - - // handle errors and timeouts - if (CC_UNLIKELY(err != NO_ERROR)) { - if (err == TIMED_OUT) { - if (condition()) { - LOGE("waitForCondition(%s) timed out (identity=%d), " - "but condition is true! We recovered but it " - "shouldn't happen." , T::name(), - stack.identity); - break; - } else { - LOGW("waitForCondition(%s) timed out " - "(identity=%d, status=%d). " - "CPU may be pegged. trying again.", T::name(), - stack.identity, stack.status); - } - } else { - LOGE("waitForCondition(%s) error (%s) ", - T::name(), strerror(-err)); - return err; - } - } - } - return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status; -} - - template status_t SharedBufferBase::updateCondition(T update) { SharedClient& client( *mSharedClient ); @@ -238,13 +213,21 @@ public: status_t queue(int buf); bool needNewBuffer(int buffer) const; status_t setDirtyRegion(int buffer, const Region& reg); + status_t setCrop(int buffer, const Rect& reg); + + class SetBufferCountCallback { + friend class SharedBufferClient; + virtual status_t operator()(int bufferCount) const = 0; + protected: + virtual ~SetBufferCountCallback() { } + }; + status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc); + private: friend struct Condition; friend struct DequeueCondition; friend struct LockCondition; - - int32_t computeTail() const; struct QueueUpdate : public UpdateBase { inline QueueUpdate(SharedBufferBase* sbb); @@ -260,20 +243,27 @@ private: struct DequeueCondition : public ConditionBase { inline DequeueCondition(SharedBufferClient* sbc); - inline bool operator()(); - static inline const char* name() { return "DequeueCondition"; } + inline bool operator()() const; + inline const char* name() const { return "DequeueCondition"; } }; struct LockCondition : public ConditionBase { int buf; inline LockCondition(SharedBufferClient* sbc, int buf); - inline bool operator()(); - static inline const char* name() { return "LockCondition"; } + inline bool operator()() const; + inline const char* name() const { return "LockCondition"; } }; + int32_t computeTail() const; + + mutable RWLock mLock; + int mNumBuffers; + int32_t tail; + int32_t undoDequeueTail; + int32_t queued_head; // statistics... - nsecs_t mDequeueTime[NUM_BUFFER_MAX]; + nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX]; }; // ---------------------------------------------------------------------------- @@ -287,16 +277,71 @@ public: ssize_t retireAndLock(); status_t unlock(int buffer); void setStatus(status_t status); - status_t reallocate(); + status_t reallocateAll(); + status_t reallocateAllExcept(int buffer); status_t assertReallocate(int buffer); int32_t getQueuedCount() const; - Region getDirtyRegion(int buffer) const; + status_t resize(int newNumBuffers); + SharedBufferStack::Statistics getStats() const; private: + /* + * BufferList is basically a fixed-capacity sorted-vector of + * unsigned 5-bits ints using a 32-bits int as storage. + * it has efficient iterators to find items in the list and not in the list. + */ + class BufferList { + size_t mCapacity; + uint32_t mList; + public: + BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX) + : mCapacity(c), mList(0) { } + status_t add(int value); + status_t remove(int value); + uint32_t getMask() const { return mList; } + + class const_iterator { + friend class BufferList; + uint32_t mask, curr; + const_iterator(uint32_t mask) : + mask(mask), curr(__builtin_clz(mask)) { + } + public: + inline bool operator == (const const_iterator& rhs) const { + return mask == rhs.mask; + } + inline bool operator != (const const_iterator& rhs) const { + return mask != rhs.mask; + } + inline int operator *() const { return curr; } + inline const const_iterator& operator ++() { + mask &= ~(1<<(31-curr)); + curr = __builtin_clz(mask); + return *this; + } + }; + + inline const_iterator begin() const { + return const_iterator(mList); + } + inline const_iterator end() const { + return const_iterator(0); + } + inline const_iterator free_begin() const { + uint32_t mask = (1 << (32-mCapacity)) - 1; + return const_iterator( ~(mList | mask) ); + } + }; + + // this protects mNumBuffers and mBufferList + mutable RWLock mLock; + int mNumBuffers; + BufferList mBufferList; + struct UnlockUpdate : public UpdateBase { const int lockedBuffer; inline UnlockUpdate(SharedBufferBase* sbb, int lockedBuffer); @@ -318,8 +363,8 @@ private: struct ReallocateCondition : public ConditionBase { int buf; inline ReallocateCondition(SharedBufferBase* sbb, int buf); - inline bool operator()(); - static inline const char* name() { return "ReallocateCondition"; } + inline bool operator()() const; + inline const char* name() const { return "ReallocateCondition"; } }; }; @@ -344,13 +389,12 @@ struct surface_flinger_cblk_t // 4KB max uint8_t connected; uint8_t reserved[3]; uint32_t pad[7]; - display_cblk_t displays[NUM_DISPLAY_MAX]; + display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX]; }; // --------------------------------------------------------------------------- -COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 4096) -COMPILE_TIME_ASSERT(sizeof(SharedBufferStack) == 128) +COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 32768) COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096) // --------------------------------------------------------------------------- diff --git a/include/surfaceflinger/ISurface.h b/include/surfaceflinger/ISurface.h index 472f759237fe5381a0dcc99812a6f3e6ad8a82ac..ddbe03dbccf0c145c539608a63fb50a88a20cd92 100644 --- a/include/surfaceflinger/ISurface.h +++ b/include/surfaceflinger/ISurface.h @@ -47,13 +47,30 @@ protected: POST_BUFFER, // one-way transaction CREATE_OVERLAY, REQUEST_BUFFER, + SET_BUFFER_COUNT, }; public: DECLARE_META_INTERFACE(Surface); - virtual sp requestBuffer(int bufferIdx, int usage) = 0; + /* + * requests a new buffer for the given index. If w, h, or format are + * null the buffer is created with the parameters assigned to the + * surface it is bound to. Otherwise the buffer's parameters are + * set to those specified. + */ + virtual sp requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0; + + /* + * sets the number of buffers dequeuable for this surface. + */ + virtual status_t setBufferCount(int bufferCount) = 0; + // ------------------------------------------------------------------------ + // Deprecated... + // ------------------------------------------------------------------------ + class BufferHeap { public: enum { diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index d1e7785ccd60746ddb3a23632e6c3b3446b7d39f..3271cfd4753acd0d9e828cb031687f52476f9107 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -27,7 +27,7 @@ #include -#include +#include namespace android { // ---------------------------------------------------------------------------- @@ -86,7 +86,7 @@ public: * ACCESS_SURFACE_FLINGER permission */ - virtual sp createConnection() = 0; + virtual sp createConnection() = 0; /* retrieve the control block */ virtual sp getCblk() const = 0; diff --git a/include/surfaceflinger/ISurfaceFlingerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h similarity index 81% rename from include/surfaceflinger/ISurfaceFlingerClient.h rename to include/surfaceflinger/ISurfaceComposerClient.h index d257645b65e97c0c44b4c4a6951c2068de590c9d..b2a4766bc40dfa060ad928890aaad36bbdf17752 100644 --- a/include/surfaceflinger/ISurfaceFlingerClient.h +++ b/include/surfaceflinger/ISurfaceComposerClient.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ANDROID_SF_ISURFACE_FLINGER_CLIENT_H -#define ANDROID_SF_ISURFACE_FLINGER_CLIENT_H +#ifndef ANDROID_SF_ISURFACE_COMPOSER_CLIENT_H +#define ANDROID_SF_ISURFACE_COMPOSER_CLIENT_H #include #include @@ -26,7 +26,7 @@ #include #include - + #include namespace android { @@ -42,10 +42,10 @@ typedef int32_t DisplayID; class layer_state_t; -class ISurfaceFlingerClient : public IInterface +class ISurfaceComposerClient : public IInterface { -public: - DECLARE_META_INTERFACE(SurfaceFlingerClient); +public: + DECLARE_META_INTERFACE(SurfaceComposerClient); struct surface_data_t { int32_t token; @@ -56,26 +56,35 @@ public: status_t readFromParcel(const Parcel& parcel); status_t writeToParcel(Parcel* parcel) const; }; - + virtual sp getControlBlock() const = 0; + /* + * Requires ACCESS_SURFACE_FLINGER permission + */ virtual sp createSurface( surface_data_t* data, - int pid, + int pid, const String8& name, DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) = 0; - + + /* + * Requires ACCESS_SURFACE_FLINGER permission + */ virtual status_t destroySurface(SurfaceID sid) = 0; + /* + * Requires ACCESS_SURFACE_FLINGER permission + */ virtual status_t setState(int32_t count, const layer_state_t* states) = 0; }; // ---------------------------------------------------------------------------- -class BnSurfaceFlingerClient : public BnInterface +class BnSurfaceComposerClient : public BnInterface { public: virtual status_t onTransact( uint32_t code, @@ -88,4 +97,4 @@ public: }; // namespace android -#endif // ANDROID_SF_ISURFACE_FLINGER_CLIENT_H +#endif // ANDROID_SF_ISURFACE_COMPOSER_CLIENT_H diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index 0279d84b64fe3de4f237cf3163d8e463acf3abc4..295797066f80ee83da85e4c8bf5638da7f064465 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -28,12 +28,15 @@ #include #include -#include +#include + +#define ANDROID_VIEW_SURFACE_JNI_ID "mNativeSurface" namespace android { // --------------------------------------------------------------------------- +class GraphicBuffer; class GraphicBufferMapper; class IOMX; class Rect; @@ -41,6 +44,7 @@ class Surface; class SurfaceComposerClient; class SharedClient; class SharedBufferClient; +class SurfaceClient; // --------------------------------------------------------------------------- @@ -104,7 +108,7 @@ private: SurfaceControl( const sp& client, const sp& surface, - const ISurfaceFlingerClient::surface_data_t& data, + const ISurfaceComposerClient::surface_data_t& data, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); ~SurfaceControl(); @@ -163,38 +167,36 @@ public: // setSwapRectangle() is intended to be used by GL ES clients void setSwapRectangle(const Rect& r); -private: - // can't be copied - Surface& operator = (Surface& rhs); - Surface(const Surface& rhs); - - Surface(const sp& control); - void init(); - ~Surface(); - - friend class SurfaceComposerClient; - friend class SurfaceControl; - +private: + /* + * Android frameworks friends + * (eventually this should go away and be replaced by proper APIs) + */ // camera and camcorder need access to the ISurface binder interface for preview friend class Camera; friend class MediaRecorder; - // mediaplayer needs access to ISurface for display + // MediaPlayer needs access to ISurface for display friend class MediaPlayer; friend class IOMX; // this is just to be able to write some unit tests friend class Test; - sp getClient() const; - sp getISurface() const; +private: + friend class SurfaceComposerClient; + friend class SurfaceControl; - status_t getBufferLocked(int index, int usage); - - status_t validate() const; + // can't be copied + Surface& operator = (Surface& rhs); + Surface(const Surface& rhs); - inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; } - inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; } - + Surface(const sp& control); + ~Surface(); + + + /* + * android_native_window_t hooks + */ static int setSwapInterval(android_native_window_t* window, int interval); static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer); static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); @@ -208,21 +210,61 @@ private: int query(int what, int* value); int perform(int operation, va_list args); - status_t dequeueBuffer(sp* buffer); - void dispatch_setUsage(va_list args); int dispatch_connect(va_list args); int dispatch_disconnect(va_list args); + int dispatch_crop(va_list args); + int dispatch_set_buffer_count(va_list args); + int dispatch_set_buffers_geometry(va_list args); void setUsage(uint32_t reqUsage); int connect(int api); int disconnect(int api); + int crop(Rect const* rect); + int setBufferCount(int bufferCount); + int setBuffersGeometry(int w, int h, int format); - uint32_t getUsage() const; - int getConnectedApi() const; + /* + * private stuff... + */ + void init(); + status_t validate() const; + status_t initCheck() const; + sp getISurface() const; + + inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; } + inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; } + + status_t getBufferLocked(int index, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage); + int getBufferIndex(const sp& buffer) const; + + int getConnectedApi() const; + bool needNewBuffer(int bufIdx, + uint32_t *pWidth, uint32_t *pHeight, + uint32_t *pFormat, uint32_t *pUsage) const; + + class BufferInfo { + uint32_t mWidth; + uint32_t mHeight; + uint32_t mFormat; + uint32_t mUsage; + mutable uint32_t mDirty; + enum { + GEOMETRY = 0x01 + }; + public: + BufferInfo(); + void set(uint32_t w, uint32_t h, uint32_t format); + void set(uint32_t usage); + void get(uint32_t *pWidth, uint32_t *pHeight, + uint32_t *pFormat, uint32_t *pUsage) const; + bool validateBuffer(const sp& buffer) const; + }; + // constants - sp mClient; + sp mClient; sp mSurface; SurfaceID mToken; uint32_t mIdentity; @@ -230,22 +272,26 @@ private: uint32_t mFlags; GraphicBufferMapper& mBufferMapper; SharedBufferClient* mSharedBufferClient; + status_t mInitCheck; // protected by mSurfaceLock Rect mSwapRectangle; - uint32_t mUsage; int mConnected; + Rect mNextBufferCrop; + BufferInfo mBufferInfo; // protected by mSurfaceLock. These are also used from lock/unlock // but in that case, they must be called form the same thread. - sp mBuffers[2]; mutable Region mDirtyRegion; // must be used from the lock/unlock thread sp mLockedBuffer; sp mPostedBuffer; mutable Region mOldDirtyRegion; - bool mNeedFullUpdate; + bool mReserved; + + // only used from dequeueBuffer() + Vector< sp > mBuffers; // query() must be called from dequeueBuffer() thread uint32_t mWidth; diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h index 9d0f0cbeb85d6cabb7a464a30bed79ca12b12037..8e28a815bf133b6e2effd29766f05524cbbfe7e2 100644 --- a/include/surfaceflinger/SurfaceComposerClient.h +++ b/include/surfaceflinger/SurfaceComposerClient.h @@ -40,7 +40,9 @@ class SharedClient; class ISurfaceComposer; class DisplayInfo; -class SurfaceComposerClient : virtual public RefBase +// --------------------------------------------------------------------------- + +class SurfaceComposerClient : public RefBase { public: SurfaceComposerClient(); @@ -52,10 +54,6 @@ public: // Return the connection of this client sp connection() const; - // Retrieve a client for an existing connection. - static sp - clientForConnection(const sp& conn); - // Forcibly remove connection before all references have gone away. void dispose(); @@ -123,13 +121,6 @@ public: status_t linkToComposerDeath(const sp& recipient, void* cookie = NULL, uint32_t flags = 0); -private: - friend class Surface; - friend class SurfaceControl; - - SurfaceComposerClient(const sp& sm, - const sp& conn); - status_t hide(SurfaceID id); status_t show(SurfaceID id, int32_t layer = -1); status_t freeze(SurfaceID id); @@ -142,32 +133,45 @@ private: status_t setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy); status_t setPosition(SurfaceID id, int32_t x, int32_t y); status_t setSize(SurfaceID id, uint32_t w, uint32_t h); - - void signalServer(); - status_t destroySurface(SurfaceID sid); - void _init(const sp& sm, - const sp& conn); - - inline layer_state_t* _get_state_l(SurfaceID id); - layer_state_t* _lockLayerState(SurfaceID id); - inline void _unlockLayerState(); +private: + virtual void onFirstRef(); + inline layer_state_t* get_state_l(SurfaceID id); + layer_state_t* lockLayerState(SurfaceID id); + inline void unlockLayerState(); mutable Mutex mLock; - layer_state_t* mPrebuiltLayerState; SortedVector mStates; int32_t mTransactionOpen; + layer_state_t* mPrebuiltLayerState; // these don't need to be protected because they never change // after assignment status_t mStatus; - SharedClient* mControl; - sp mControlMemory; - sp mClient; - sp mSignalServer; + sp mClient; }; +// --------------------------------------------------------------------------- + +class SurfaceClient : public RefBase +{ + // all these attributes are constants + status_t mStatus; + SharedClient* mControl; + sp mControlMemory; + sp mConnection; + sp mComposerService; + void init(const sp& conn); +public: + explicit SurfaceClient(const sp& conn); + explicit SurfaceClient(const sp& client); + status_t initCheck() const; + SharedClient* getSharedClient() const; + void signalServer() const; +}; + +// --------------------------------------------------------------------------- }; // namespace android #endif // ANDROID_SF_SURFACE_COMPOSER_CLIENT_H diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h index 741d7635618910c184cb51cd3509cc79272cd1d7..54b8236e2a727466c19e98cf595295fbfb33b590 100644 --- a/include/ui/GraphicBufferAllocator.h +++ b/include/ui/GraphicBufferAllocator.h @@ -73,9 +73,9 @@ private: struct alloc_rec_t { uint32_t w; uint32_t h; + uint32_t s; PixelFormat format; uint32_t usage; - void* vaddr; size_t size; }; diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h old mode 100644 new mode 100755 index 571e47b22d8675100dd5bb5dced3b4c0f3500b35..e81d0f9064dc805083de2fc71492b66cf4bc1618 --- a/include/ui/KeycodeLabels.h +++ b/include/ui/KeycodeLabels.h @@ -114,6 +114,10 @@ static const KeycodeLabel KEYCODES[] = { { "MEDIA_REWIND", 89 }, { "MEDIA_FAST_FORWARD", 90 }, { "MUTE", 91 }, + { "PAGE_UP", 92 }, + { "PAGE_DOWN", 93 }, + { "PICTSYMBOLS", 94 }, + { "SWITCH_CHARSET", 95 }, // NOTE: If you add a new keycode here you must also add it to: // (enum KeyCode, in this file) @@ -218,7 +222,11 @@ typedef enum KeyCode { kKeyCodePreviousSong = 88, kKeyCodeRewind = 89, kKeyCodeForward = 90, - kKeyCodeMute = 91 + kKeyCodeMute = 91, + kKeyCodePageUp = 92, + kKeyCodePageDown = 93, + kKeyCodePictSymbols = 94, + kKeyCodeSwitchCharset = 95 } KeyCode; static const KeycodeLabel FLAGS[] = { diff --git a/include/ui/android_native_buffer.h b/include/ui/android_native_buffer.h index 9c92af8845f8f5f638edba501f8e9019c4c35223..402843e20565ef3921e8e0728dd396c94e87ff50 100644 --- a/include/ui/android_native_buffer.h +++ b/include/ui/android_native_buffer.h @@ -33,6 +33,15 @@ typedef struct android_native_buffer_t common.version = sizeof(android_native_buffer_t); memset(common.reserved, 0, sizeof(common.reserved)); } + + // Implement the methods that sp expects so that it + // can be used to automatically refcount android_native_buffer_t's. + void incStrong(const void* id) const { + common.incRef(const_cast(&common)); + } + void decStrong(const void* id) const { + common.decRef(const_cast(&common)); + } #endif struct android_native_base_t common; diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h index 773fd9301f638bf5c51cc3af6a7b79b7ccb0d25c..171f3df3a17983bae4c255549470a30e6f9eef73 100644 --- a/include/ui/egl/android_natives.h +++ b/include/ui/egl/android_natives.h @@ -41,6 +41,14 @@ extern "C" { struct android_native_buffer_t; +typedef struct android_native_rect_t +{ + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; +} android_native_rect_t; + // --------------------------------------------------------------------------- typedef struct android_native_base_t @@ -63,15 +71,18 @@ typedef struct android_native_base_t /* attributes queriable with query() */ enum { NATIVE_WINDOW_WIDTH = 0, - NATIVE_WINDOW_HEIGHT = 1, - NATIVE_WINDOW_FORMAT = 2, + NATIVE_WINDOW_HEIGHT, + NATIVE_WINDOW_FORMAT, }; /* valid operations for the (*perform)() hook */ enum { NATIVE_WINDOW_SET_USAGE = 0, - NATIVE_WINDOW_CONNECT = 1, - NATIVE_WINDOW_DISCONNECT = 2 + NATIVE_WINDOW_CONNECT, + NATIVE_WINDOW_DISCONNECT, + NATIVE_WINDOW_SET_CROP, + NATIVE_WINDOW_SET_BUFFER_COUNT, + NATIVE_WINDOW_SET_BUFFERS_GEOMETRY, }; /* parameter for NATIVE_WINDOW_[DIS]CONNECT */ @@ -89,6 +100,15 @@ typedef struct android_native_window_t common.version = sizeof(android_native_window_t); memset(common.reserved, 0, sizeof(common.reserved)); } + + // Implement the methods that sp expects so that it + // can be used to automatically refcount android_native_window_t's. + void incStrong(const void* id) const { + common.incRef(const_cast(&common)); + } + void decStrong(const void* id) const { + common.decRef(const_cast(&common)); + } #endif struct android_native_base_t common; @@ -125,7 +145,7 @@ typedef struct android_native_window_t * * Returns 0 on success or -errno on error. */ - int (*dequeueBuffer)(struct android_native_window_t* window, + int (*dequeueBuffer)(struct android_native_window_t* window, struct android_native_buffer_t** buffer); /* @@ -171,6 +191,9 @@ typedef struct android_native_window_t * NATIVE_WINDOW_SET_USAGE * NATIVE_WINDOW_CONNECT * NATIVE_WINDOW_DISCONNECT + * NATIVE_WINDOW_SET_CROP + * NATIVE_WINDOW_SET_BUFFER_COUNT + * NATIVE_WINDOW_SET_BUFFERS_GEOMETRY * */ @@ -182,8 +205,9 @@ typedef struct android_native_window_t /* - * native_window_set_usage() sets the intended usage flags for the next - * buffers acquired with (*lockBuffer)() and on. + * native_window_set_usage(..., usage) + * Sets the intended usage flags for the next buffers + * acquired with (*lockBuffer)() and on. * By default (if this function is never called), a usage of * GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE * is assumed. @@ -198,8 +222,8 @@ static inline int native_window_set_usage( } /* - * native_window_connect(..., NATIVE_WINDOW_API_EGL) must be called - * by EGL when the window is made current. + * native_window_connect(..., NATIVE_WINDOW_API_EGL) + * Must be called by EGL when the window is made current. * Returns -EINVAL if for some reason the window cannot be connected, which * can happen if it's connected to some other API. */ @@ -210,8 +234,8 @@ static inline int native_window_connect( } /* - * native_window_disconnect(..., NATIVE_WINDOW_API_EGL) must be called - * by EGL when the window is made not current. + * native_window_disconnect(..., NATIVE_WINDOW_API_EGL) + * Must be called by EGL when the window is made not current. * An error is returned if for instance the window wasn't connected in the * first place. */ @@ -221,6 +245,54 @@ static inline int native_window_disconnect( return window->perform(window, NATIVE_WINDOW_DISCONNECT, api); } +/* + * native_window_set_crop(..., crop) + * Sets which region of the next queued buffers needs to be considered. + * A buffer's crop region is scaled to match the surface's size. + * + * The specified crop region applies to all buffers queued after it is called. + * + * if 'crop' is NULL, subsequently queued buffers won't be cropped. + * + * An error is returned if for instance the crop region is invalid, + * out of the buffer's bound or if the window is invalid. + */ +static inline int native_window_set_crop( + android_native_window_t* window, + android_native_rect_t const * crop) +{ + return window->perform(window, NATIVE_WINDOW_SET_CROP, crop); +} + +/* + * native_window_set_buffer_count(..., count) + * Sets the number of buffers associated with this native window. + */ +static inline int native_window_set_buffer_count( + android_native_window_t* window, + size_t bufferCount) +{ + return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount); +} + +/* + * native_window_set_buffers_geometry(..., int w, int h, int format) + * All buffers dequeued after this call will have the geometry specified. + * In particular, all buffers will have a fixed-size, independent form the + * native-window size. They will be appropriately scaled to the window-size + * upon composition. + * + * If all parameters are 0, the normal behavior is restored. That is, + * dequeued buffers following this call will be sized to the window's size. + * + */ +static inline int native_window_set_buffers_geometry( + android_native_window_t* window, + int w, int h, int format) +{ + return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY, + w, h, format); +} // --------------------------------------------------------------------------- @@ -263,6 +335,15 @@ namespace android { template class EGLNativeBase : public NATIVE_TYPE, public REF { +public: + // Disambiguate between the incStrong in REF and NATIVE_TYPE + void incStrong(const void* id) const { + REF::incStrong(id); + } + void decStrong(const void* id) const { + REF::decStrong(id); + } + protected: typedef EGLNativeBase BASE; EGLNativeBase() : NATIVE_TYPE(), REF() { diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h index b701ce74d627d52a968dae96f3c10ffbc26ac153..c7d9ff1dd67894193cfb5498298c4db69f4b7f6c 100644 --- a/include/utils/ResourceTypes.h +++ b/include/utils/ResourceTypes.h @@ -933,6 +933,7 @@ struct ResTable_config SCREENSIZE_SMALL = 0x01, SCREENSIZE_NORMAL = 0x02, SCREENSIZE_LARGE = 0x03, + SCREENSIZE_XLARGE = 0x04, // screenLayout bits for wide/long screen variation. MASK_SCREENLONG = 0x30, @@ -1208,7 +1209,28 @@ struct ResTable_config if (screenLayout || o.screenLayout) { if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0 && (requested->screenLayout & MASK_SCREENSIZE)) { - return (screenLayout & MASK_SCREENSIZE); + // A little backwards compatibility here: undefined is + // considered equivalent to normal. But only if the + // requested size is at least normal; otherwise, small + // is better than the default. + int mySL = (screenLayout & MASK_SCREENSIZE); + int oSL = (o.screenLayout & MASK_SCREENSIZE); + int fixedMySL = mySL; + int fixedOSL = oSL; + if ((requested->screenLayout & MASK_SCREENSIZE) >= SCREENSIZE_NORMAL) { + if (fixedMySL == 0) fixedMySL = SCREENSIZE_NORMAL; + if (fixedOSL == 0) fixedOSL = SCREENSIZE_NORMAL; + } + // For screen size, the best match is the one that is + // closest to the requested screen size, but not over + // (the not over part is dealt with in match() below). + if (fixedMySL == fixedOSL) { + // If the two are the same, but 'this' is actually + // undefined, then the other is really a better match. + if (mySL == 0) return false; + return true; + } + return fixedMySL >= fixedOSL; } if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0 && (requested->screenLayout & MASK_SCREENLONG)) { @@ -1370,8 +1392,11 @@ struct ResTable_config if (screenConfig != 0) { const int screenSize = screenLayout&MASK_SCREENSIZE; const int setScreenSize = settings.screenLayout&MASK_SCREENSIZE; - if (setScreenSize != 0 && screenSize != 0 - && screenSize != setScreenSize) { + // Any screen sizes for larger screens than the setting do not + // match. + if ((setScreenSize != 0 && screenSize != 0 + && screenSize > setScreenSize) || + (setScreenSize == 0 && screenSize != 0)) { return false; } diff --git a/include/utils/Singleton.h b/include/utils/Singleton.h index bc7626a8213981fa5da50f452d4f609362bb3668..3b975b4c4448318e65d892ab607a60ca2c7ffe25 100644 --- a/include/utils/Singleton.h +++ b/include/utils/Singleton.h @@ -54,11 +54,13 @@ private: * (eg: .cpp) to create the static instance of Singleton<>'s attributes, * and avoid to have a copy of them in each compilation units Singleton * is used. + * NOTE: we use a version of Mutex ctor that takes a parameter, because + * for some unknown reason using the default ctor doesn't emit the variable! */ -#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) \ - template class Singleton< TYPE >; \ - template< class TYPE > Mutex Singleton< TYPE >::sLock; \ +#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) \ + template class Singleton< TYPE >; \ + template<> Mutex Singleton< TYPE >::sLock(Mutex::PRIVATE); \ template<> TYPE* Singleton< TYPE >::sInstance(0); diff --git a/include/utils/ZipFileCRO.h b/include/utils/ZipFileCRO.h index 30e00368e9713d595a5e2945196f01e1fb34005f..e38bf669d7bf76d602a66d6aeb2e0680174f8b56 100644 --- a/include/utils/ZipFileCRO.h +++ b/include/utils/ZipFileCRO.h @@ -47,8 +47,8 @@ extern ZipEntryCRO ZipFileCRO_findEntryByName(ZipFileCRO zip, const char* fileName); extern bool ZipFileCRO_getEntryInfo(ZipFileCRO zip, ZipEntryCRO entry, - int* pMethod, long* pUncompLen, - long* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32); + int* pMethod, size_t* pUncompLen, + size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32); extern bool ZipFileCRO_uncompressEntry(ZipFileCRO zip, ZipEntryCRO entry, int fd); diff --git a/include/utils/ZipFileRO.h b/include/utils/ZipFileRO.h index 51c4f2fb6a778354f24fb23f2fead1be2a33d938..97d31f4db4f33b82e92445545d39c3c6e83c91f0 100644 --- a/include/utils/ZipFileRO.h +++ b/include/utils/ZipFileRO.h @@ -58,14 +58,19 @@ typedef void* ZipEntryRO; class ZipFileRO { public: ZipFileRO() - : mFd(-1), mFileMap(NULL), mHashTableSize(-1), mHashTable(NULL) + : mFd(-1), mFileName(NULL), mFileLength(-1), + mDirectoryMap(NULL), + mNumEntries(-1), mDirectoryOffset(-1), + mHashTableSize(-1), mHashTable(NULL) {} ~ZipFileRO() { free(mHashTable); - if (mFileMap) - mFileMap->release(); + if (mDirectoryMap) + mDirectoryMap->release(); if (mFd >= 0) close(mFd); + if (mFileName) + free(mFileName); } /* @@ -118,8 +123,8 @@ public: * Returns "false" if "entry" is bogus or if the data in the Zip file * appears to be bad. */ - bool getEntryInfo(ZipEntryRO entry, int* pMethod, long* pUncompLen, - long* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) const; + bool getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, + size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) const; /* * Create a new FileMap object that maps a subset of the archive. For @@ -155,13 +160,13 @@ public: * Utility function: uncompress deflated data, buffer to buffer. */ static bool inflateBuffer(void* outBuf, const void* inBuf, - long uncompLen, long compLen); + size_t uncompLen, size_t compLen); /* * Utility function: uncompress deflated data, buffer to fd. */ static bool inflateBuffer(int fd, const void* inBuf, - long uncompLen, long compLen); + size_t uncompLen, size_t compLen); /* * Some basic functions for raw data manipulation. "LE" means @@ -179,6 +184,9 @@ private: ZipFileRO(const ZipFileRO& src); ZipFileRO& operator=(const ZipFileRO& src); + /* locate and parse the central directory */ + bool mapCentralDirectory(void); + /* parse the archive, prepping internal structures */ bool parseZipArchive(void); @@ -203,12 +211,21 @@ private: /* open Zip archive */ int mFd; + /* zip file name */ + char* mFileName; + + /* length of file */ + size_t mFileLength; + /* mapped file */ - FileMap* mFileMap; + FileMap* mDirectoryMap; /* number of entries in the Zip archive */ int mNumEntries; + /* CD directory offset in the Zip archive */ + off_t mDirectoryOffset; + /* * We know how many entries are in the Zip archive, so we have a * fixed-size hash table. We probe for an empty slot. diff --git a/include/utils/threads.h b/include/utils/threads.h index 5ac0c5ee198d8d42b6726ec9a3c00f83f9d24d47..1bcfaede67aaebd09d9204bb88c16f1bc2f76c7c 100644 --- a/include/utils/threads.h +++ b/include/utils/threads.h @@ -295,6 +295,96 @@ typedef Mutex::Autolock AutoMutex; /*****************************************************************************/ +#if defined(HAVE_PTHREADS) + +/* + * Simple mutex class. The implementation is system-dependent. + * + * The mutex must be unlocked by the thread that locked it. They are not + * recursive, i.e. the same thread can't lock it multiple times. + */ +class RWLock { +public: + enum { + PRIVATE = 0, + SHARED = 1 + }; + + RWLock(); + RWLock(const char* name); + RWLock(int type, const char* name = NULL); + ~RWLock(); + + status_t readLock(); + status_t tryReadLock(); + status_t writeLock(); + status_t tryWriteLock(); + void unlock(); + + class AutoRLock { + public: + inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); } + inline ~AutoRLock() { mLock.unlock(); } + private: + RWLock& mLock; + }; + + class AutoWLock { + public: + inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); } + inline ~AutoWLock() { mLock.unlock(); } + private: + RWLock& mLock; + }; + +private: + // A RWLock cannot be copied + RWLock(const RWLock&); + RWLock& operator = (const RWLock&); + + pthread_rwlock_t mRWLock; +}; + +inline RWLock::RWLock() { + pthread_rwlock_init(&mRWLock, NULL); +} +inline RWLock::RWLock(const char* name) { + pthread_rwlock_init(&mRWLock, NULL); +} +inline RWLock::RWLock(int type, const char* name) { + if (type == SHARED) { + pthread_rwlockattr_t attr; + pthread_rwlockattr_init(&attr); + pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + pthread_rwlock_init(&mRWLock, &attr); + pthread_rwlockattr_destroy(&attr); + } else { + pthread_rwlock_init(&mRWLock, NULL); + } +} +inline RWLock::~RWLock() { + pthread_rwlock_destroy(&mRWLock); +} +inline status_t RWLock::readLock() { + return -pthread_rwlock_rdlock(&mRWLock); +} +inline status_t RWLock::tryReadLock() { + return -pthread_rwlock_tryrdlock(&mRWLock); +} +inline status_t RWLock::writeLock() { + return -pthread_rwlock_wrlock(&mRWLock); +} +inline status_t RWLock::tryWriteLock() { + return -pthread_rwlock_trywrlock(&mRWLock); +} +inline void RWLock::unlock() { + pthread_rwlock_unlock(&mRWLock); +} + +#endif // HAVE_PTHREADS + +/*****************************************************************************/ + /* * Condition variable class. The implementation is system-dependent. * diff --git a/libs/audioflinger/AudioDumpInterface.cpp b/libs/audioflinger/AudioDumpInterface.cpp index a018b4c2259812e40bf6434eda372c2fe0e0df50..6c111148a979b44fbda5e9a193b80408fdf21ca9 100644 --- a/libs/audioflinger/AudioDumpInterface.cpp +++ b/libs/audioflinger/AudioDumpInterface.cpp @@ -32,7 +32,7 @@ namespace android { // ---------------------------------------------------------------------------- AudioDumpInterface::AudioDumpInterface(AudioHardwareInterface* hw) - : mFirstHwOutput(true), mPolicyCommands(String8("")), mFileName(String8("")) + : mPolicyCommands(String8("")), mFileName(String8("")) { if(hw == 0) { LOGE("Dump construct hw = 0"); @@ -47,6 +47,11 @@ AudioDumpInterface::~AudioDumpInterface() for (size_t i = 0; i < mOutputs.size(); i++) { closeOutputStream((AudioStreamOut *)mOutputs[i]); } + + for (size_t i = 0; i < mInputs.size(); i++) { + closeInputStream((AudioStreamIn *)mInputs[i]); + } + if(mFinalInterface) delete mFinalInterface; } @@ -60,31 +65,32 @@ AudioStreamOut* AudioDumpInterface::openOutputStream( uint32_t lRate = 44100; - if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices) || mFirstHwOutput) { - outFinal = mFinalInterface->openOutputStream(devices, format, channels, sampleRate, status); - if (outFinal != 0) { - lFormat = outFinal->format(); - lChannels = outFinal->channels(); - lRate = outFinal->sampleRate(); - if (!AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices)) { - mFirstHwOutput = false; - } - } + outFinal = mFinalInterface->openOutputStream(devices, format, channels, sampleRate, status); + if (outFinal != 0) { + lFormat = outFinal->format(); + lChannels = outFinal->channels(); + lRate = outFinal->sampleRate(); } else { - if (format != 0 && *format != 0) { - lFormat = *format; - } else { - lFormat = AudioSystem::PCM_16_BIT; + if (format != 0) { + if (*format != 0) { + lFormat = *format; + } else { + *format = lFormat; + } } - if (channels != 0 && *channels != 0) { - lChannels = *channels; - } else { - lChannels = AudioSystem::CHANNEL_OUT_STEREO; + if (channels != 0) { + if (*channels != 0) { + lChannels = *channels; + } else { + *channels = lChannels; + } } - if (sampleRate != 0 && *sampleRate != 0) { - lRate = *sampleRate; - } else { - lRate = 44100; + if (sampleRate != 0) { + if (*sampleRate != 0) { + lRate = *sampleRate; + } else { + *sampleRate = lRate; + } } if (status) *status = NO_ERROR; } @@ -111,7 +117,6 @@ void AudioDumpInterface::closeOutputStream(AudioStreamOut* out) dumpOut->standby(); if (dumpOut->finalStream() != NULL) { mFinalInterface->closeOutputStream(dumpOut->finalStream()); - mFirstHwOutput = true; } mOutputs.remove(dumpOut); @@ -126,18 +131,33 @@ AudioStreamIn* AudioDumpInterface::openInputStream(uint32_t devices, int *format uint32_t lChannels = AudioSystem::CHANNEL_IN_MONO; uint32_t lRate = 8000; - - if (mInputs.size() == 0) { - inFinal = mFinalInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics); - if (inFinal == 0) return 0; - + inFinal = mFinalInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics); + if (inFinal != 0) { lFormat = inFinal->format(); lChannels = inFinal->channels(); lRate = inFinal->sampleRate(); } else { - if (format != 0 && *format != 0) lFormat = *format; - if (channels != 0 && *channels != 0) lChannels = *channels; - if (sampleRate != 0 && *sampleRate != 0) lRate = *sampleRate; + if (format != 0) { + if (*format != 0) { + lFormat = *format; + } else { + *format = lFormat; + } + } + if (channels != 0) { + if (*channels != 0) { + lChannels = *channels; + } else { + *channels = lChannels; + } + } + if (sampleRate != 0) { + if (*sampleRate != 0) { + lRate = *sampleRate; + } else { + *sampleRate = lRate; + } + } if (status) *status = NO_ERROR; } LOGV("openInputStream(), inFinal %p", inFinal); @@ -223,6 +243,15 @@ String8 AudioDumpInterface::getParameters(const String8& keys) return keyValuePairs; } +status_t AudioDumpInterface::setMode(int mode) +{ + return mFinalInterface->setMode(mode); +} + +size_t AudioDumpInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) +{ + return mFinalInterface->getInputBufferSize(sampleRate, format, channelCount); +} // ---------------------------------------------------------------------------- @@ -235,7 +264,7 @@ AudioStreamOutDump::AudioStreamOutDump(AudioDumpInterface *interface, uint32_t sampleRate) : mInterface(interface), mId(id), mSampleRate(sampleRate), mFormat(format), mChannels(channels), mLatency(0), mDevice(devices), - mBufferSize(1024), mFinalStream(finalStream), mOutFile(0), mFileCount(0) + mBufferSize(1024), mFinalStream(finalStream), mFile(0), mFileCount(0) { LOGV("AudioStreamOutDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream); } @@ -254,26 +283,26 @@ ssize_t AudioStreamOutDump::write(const void* buffer, size_t bytes) if (mFinalStream) { ret = mFinalStream->write(buffer, bytes); } else { - usleep((bytes * 1000000) / frameSize() / sampleRate()); + usleep((((bytes * 1000) / frameSize()) / sampleRate()) * 1000); ret = bytes; } - if(!mOutFile) { + if(!mFile) { if (mInterface->fileName() != "") { char name[255]; - sprintf(name, "%s_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount); - mOutFile = fopen(name, "wb"); - LOGV("Opening dump file %s, fh %p", name, mOutFile); + sprintf(name, "%s_out_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount); + mFile = fopen(name, "wb"); + LOGV("Opening dump file %s, fh %p", name, mFile); } } - if (mOutFile) { - fwrite(buffer, bytes, 1, mOutFile); + if (mFile) { + fwrite(buffer, bytes, 1, mFile); } return ret; } status_t AudioStreamOutDump::standby() { - LOGV("AudioStreamOutDump standby(), mOutFile %p, mFinalStream %p", mOutFile, mFinalStream); + LOGV("AudioStreamOutDump standby(), mFile %p, mFinalStream %p", mFile, mFinalStream); Close(); if (mFinalStream != 0 ) return mFinalStream->standby(); @@ -330,7 +359,7 @@ status_t AudioStreamOutDump::setParameters(const String8& keyValuePairs) } if (param.getInt(String8("format"), valueInt) == NO_ERROR) { - if (mOutFile == 0) { + if (mFile == 0) { mFormat = valueInt; } else { status = INVALID_OPERATION; @@ -345,7 +374,7 @@ status_t AudioStreamOutDump::setParameters(const String8& keyValuePairs) } if (param.getInt(String8("sampling_rate"), valueInt) == NO_ERROR) { if (valueInt > 0 && valueInt <= 48000) { - if (mOutFile == 0) { + if (mFile == 0) { mSampleRate = valueInt; } else { status = INVALID_OPERATION; @@ -373,9 +402,9 @@ status_t AudioStreamOutDump::dump(int fd, const Vector& args) void AudioStreamOutDump::Close() { - if(mOutFile) { - fclose(mOutFile); - mOutFile = 0; + if(mFile) { + fclose(mFile); + mFile = 0; } } @@ -396,7 +425,7 @@ AudioStreamInDump::AudioStreamInDump(AudioDumpInterface *interface, uint32_t sampleRate) : mInterface(interface), mId(id), mSampleRate(sampleRate), mFormat(format), mChannels(channels), mDevice(devices), - mBufferSize(1024), mFinalStream(finalStream), mInFile(0) + mBufferSize(1024), mFinalStream(finalStream), mFile(0), mFileCount(0) { LOGV("AudioStreamInDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream); } @@ -409,55 +438,68 @@ AudioStreamInDump::~AudioStreamInDump() ssize_t AudioStreamInDump::read(void* buffer, ssize_t bytes) { - if (mFinalStream) { - return mFinalStream->read(buffer, bytes); - } - - usleep((bytes * 1000000) / frameSize() / sampleRate()); + ssize_t ret; - if(!mInFile) { - char name[255]; - strcpy(name, "/sdcard/music/sine440"); - if (channels() == AudioSystem::CHANNEL_IN_MONO) { - strcat(name, "_mo"); - } else { - strcat(name, "_st"); + if (mFinalStream) { + ret = mFinalStream->read(buffer, bytes); + if(!mFile) { + if (mInterface->fileName() != "") { + char name[255]; + sprintf(name, "%s_in_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount); + mFile = fopen(name, "wb"); + LOGV("Opening input dump file %s, fh %p", name, mFile); + } } - if (format() == AudioSystem::PCM_16_BIT) { - strcat(name, "_16b"); - } else { - strcat(name, "_8b"); + if (mFile) { + fwrite(buffer, bytes, 1, mFile); } - if (sampleRate() < 16000) { - strcat(name, "_8k"); - } else if (sampleRate() < 32000) { - strcat(name, "_22k"); - } else if (sampleRate() < 48000) { - strcat(name, "_44k"); - } else { - strcat(name, "_48k"); - } - strcat(name, ".wav"); - mInFile = fopen(name, "rb"); - LOGV("Opening dump file %s, fh %p", name, mInFile); - if (mInFile) { - fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET); + } else { + usleep((((bytes * 1000) / frameSize()) / sampleRate()) * 1000); + ret = bytes; + if(!mFile) { + char name[255]; + strcpy(name, "/sdcard/music/sine440"); + if (channels() == AudioSystem::CHANNEL_IN_MONO) { + strcat(name, "_mo"); + } else { + strcat(name, "_st"); + } + if (format() == AudioSystem::PCM_16_BIT) { + strcat(name, "_16b"); + } else { + strcat(name, "_8b"); + } + if (sampleRate() < 16000) { + strcat(name, "_8k"); + } else if (sampleRate() < 32000) { + strcat(name, "_22k"); + } else if (sampleRate() < 48000) { + strcat(name, "_44k"); + } else { + strcat(name, "_48k"); + } + strcat(name, ".wav"); + mFile = fopen(name, "rb"); + LOGV("Opening input read file %s, fh %p", name, mFile); + if (mFile) { + fseek(mFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET); + } } - - } - if (mInFile) { - ssize_t bytesRead = fread(buffer, bytes, 1, mInFile); - if (bytesRead != bytes) { - fseek(mInFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET); - fread((uint8_t *)buffer+bytesRead, bytes-bytesRead, 1, mInFile); + if (mFile) { + ssize_t bytesRead = fread(buffer, bytes, 1, mFile); + if (bytesRead >=0 && bytesRead < bytes) { + fseek(mFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET); + fread((uint8_t *)buffer+bytesRead, bytes-bytesRead, 1, mFile); + } } } - return bytes; + + return ret; } status_t AudioStreamInDump::standby() { - LOGV("AudioStreamInDump standby(), mInFile %p, mFinalStream %p", mInFile, mFinalStream); + LOGV("AudioStreamInDump standby(), mFile %p, mFinalStream %p", mFile, mFinalStream); Close(); if (mFinalStream != 0 ) return mFinalStream->standby(); @@ -523,9 +565,9 @@ status_t AudioStreamInDump::dump(int fd, const Vector& args) void AudioStreamInDump::Close() { - if(mInFile) { - fclose(mInFile); - mInFile = 0; + if(mFile) { + fclose(mFile); + mFile = 0; } } }; // namespace android diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h index 4c62b3ed78da35b2adcd6b0f08c7e75227b08055..814ce5f717703572068baf4df4e1e26816a64962 100644 --- a/libs/audioflinger/AudioDumpInterface.h +++ b/libs/audioflinger/AudioDumpInterface.h @@ -69,7 +69,7 @@ private: uint32_t mDevice; // current device this output is routed to size_t mBufferSize; AudioStreamOut *mFinalStream; - FILE *mOutFile; // output file + FILE *mFile; // output file int mFileCount; }; @@ -109,7 +109,8 @@ private: uint32_t mDevice; // current device this output is routed to size_t mBufferSize; AudioStreamIn *mFinalStream; - FILE *mInFile; // output file + FILE *mFile; // output file + int mFileCount; }; class AudioDumpInterface : public AudioHardwareBase @@ -134,6 +135,8 @@ public: virtual status_t setMasterVolume(float volume) {return mFinalInterface->setMasterVolume(volume);} + virtual status_t setMode(int mode); + // mic mute virtual status_t setMicMute(bool state) {return mFinalInterface->setMicMute(state);} @@ -143,6 +146,8 @@ public: virtual status_t setParameters(const String8& keyValuePairs); virtual String8 getParameters(const String8& keys); + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount); + virtual AudioStreamIn* openInputStream(uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics); virtual void closeInputStream(AudioStreamIn* in); @@ -153,8 +158,7 @@ public: protected: AudioHardwareInterface *mFinalInterface; - SortedVector mOutputs; - bool mFirstHwOutput; + SortedVector mOutputs; SortedVector mInputs; Mutex mLock; String8 mPolicyCommands; diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index 2414e8dc5e039fa03c50813ac1c0ea5525fe2b61..3b38d838481188c44e3ed9a26042a397808a352e 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -142,6 +142,7 @@ AudioFlinger::AudioFlinger() } #ifdef LVMX LifeVibes::init(); + mLifeVibesClientPid = -1; #endif } @@ -596,8 +597,10 @@ status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs) int musicEnabled = -1; if (NO_ERROR == param.get(key, value)) { if (value == LifevibesEnable) { + mLifeVibesClientPid = IPCThreadState::self()->getCallingPid(); musicEnabled = 1; } else if (value == LifevibesDisable) { + mLifeVibesClientPid = -1; musicEnabled = 0; } } @@ -609,7 +612,7 @@ status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs) mHardwareStatus = AUDIO_SET_PARAMETER; result = mAudioHardware->setParameters(keyValuePairs); #ifdef LVMX - if ((NO_ERROR == result) && (musicEnabled != -1)) { + if (musicEnabled != -1) { LifeVibes::enableMusic((bool) musicEnabled); } #endif @@ -713,51 +716,57 @@ status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrame void AudioFlinger::registerClient(const sp& client) { - LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid()); Mutex::Autolock _l(mLock); - sp binder = client->asBinder(); - if (mNotificationClients.indexOf(binder) < 0) { - LOGV("Adding notification client %p", binder.get()); - binder->linkToDeath(this); - mNotificationClients.add(binder); - } + int pid = IPCThreadState::self()->getCallingPid(); + if (mNotificationClients.indexOfKey(pid) < 0) { + sp notificationClient = new NotificationClient(this, + client, + pid); + LOGV("registerClient() client %p, pid %d", notificationClient.get(), pid); - // the config change is always sent from playback or record threads to avoid deadlock - // with AudioSystem::gLock - for (size_t i = 0; i < mPlaybackThreads.size(); i++) { - mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED); - } + mNotificationClients.add(pid, notificationClient); + + sp binder = client->asBinder(); + binder->linkToDeath(notificationClient); + + // the config change is always sent from playback or record threads to avoid deadlock + // with AudioSystem::gLock + for (size_t i = 0; i < mPlaybackThreads.size(); i++) { + mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED); + } - for (size_t i = 0; i < mRecordThreads.size(); i++) { - mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED); + for (size_t i = 0; i < mRecordThreads.size(); i++) { + mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED); + } } } -void AudioFlinger::binderDied(const wp& who) { - - LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid()); +void AudioFlinger::removeNotificationClient(pid_t pid) +{ Mutex::Autolock _l(mLock); - IBinder *binder = who.unsafe_get(); - - if (binder != NULL) { - int index = mNotificationClients.indexOf(binder); - if (index >= 0) { - LOGV("Removing notification client %p", binder); - mNotificationClients.removeAt(index); + int index = mNotificationClients.indexOfKey(pid); + if (index >= 0) { + sp client = mNotificationClients.valueFor(pid); + LOGV("removeNotificationClient() %p, pid %d", client.get(), pid); +#ifdef LVMX + if (pid == mLifeVibesClientPid) { + LOGV("Disabling lifevibes"); + LifeVibes::enableMusic(false); + mLifeVibesClientPid = -1; } +#endif + mNotificationClients.removeItem(pid); } } // audioConfigChanged_l() must be called with AudioFlinger::mLock held -void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2) { +void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2) +{ size_t size = mNotificationClients.size(); for (size_t i = 0; i < size; i++) { - sp binder = mNotificationClients.itemAt(i); - LOGV("audioConfigChanged_l() Notifying change to client %p", binder.get()); - sp client = interface_cast (binder); - client->ioConfigChanged(event, ioHandle, param2); + mNotificationClients.valueAt(i)->client()->ioConfigChanged(event, ioHandle, param2); } } @@ -768,12 +777,13 @@ void AudioFlinger::removeClient_l(pid_t pid) mClients.removeItem(pid); } + // ---------------------------------------------------------------------------- AudioFlinger::ThreadBase::ThreadBase(const sp& audioFlinger, int id) : Thread(false), mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0), - mFormat(0), mFrameSize(1), mStandby(false), mId(id), mExiting(false) + mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false) { } @@ -806,7 +816,7 @@ uint32_t AudioFlinger::ThreadBase::sampleRate() const int AudioFlinger::ThreadBase::channelCount() const { - return mChannelCount; + return (int)mChannelCount; } int AudioFlinger::ThreadBase::format() const @@ -863,11 +873,12 @@ void AudioFlinger::ThreadBase::processConfigEvents() LOGV("processConfigEvents() remaining events %d", mConfigEvents.size()); ConfigEvent *configEvent = mConfigEvents[0]; mConfigEvents.removeAt(0); - // release mLock because audioConfigChanged() will lock AudioFlinger mLock - // before calling Audioflinger::audioConfigChanged_l() thus creating - // potential cross deadlock between AudioFlinger::mLock and mLock + // release mLock before locking AudioFlinger mLock: lock order is always + // AudioFlinger then ThreadBase to avoid cross deadlock mLock.unlock(); - audioConfigChanged(configEvent->mEvent, configEvent->mParam); + mAudioFlinger->mLock.lock(); + audioConfigChanged_l(configEvent->mEvent, configEvent->mParam); + mAudioFlinger->mLock.unlock(); delete configEvent; mLock.lock(); } @@ -943,8 +954,6 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp& audioFlinge mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream); mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream); } - // notify client processes that a new input has been opened - sendConfigEvent(AudioSystem::OUTPUT_OPENED); } AudioFlinger::PlaybackThread::~PlaybackThread() @@ -1054,7 +1063,7 @@ sp AudioFlinger::PlaybackThread::createTra status_t lStatus; if (mType == DIRECT) { - if (sampleRate != mSampleRate || format != mFormat || channelCount != mChannelCount) { + if (sampleRate != mSampleRate || format != mFormat || channelCount != (int)mChannelCount) { LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelCount %d for output %p", sampleRate, format, channelCount, mOutput); lStatus = BAD_VALUE; @@ -1224,16 +1233,17 @@ String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys) return mOutput->getParameters(keys); } -void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) { +// destroyTrack_l() must be called with AudioFlinger::mLock held +void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { AudioSystem::OutputDescriptor desc; void *param2 = 0; - LOGV("PlaybackThread::audioConfigChanged, thread %p, event %d, param %d", this, event, param); + LOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param); switch (event) { case AudioSystem::OUTPUT_OPENED: case AudioSystem::OUTPUT_CONFIG_CHANGED: - desc.channels = mChannelCount; + desc.channels = mChannels; desc.samplingRate = mSampleRate; desc.format = mFormat; desc.frameCount = mFrameCount; @@ -1247,17 +1257,16 @@ void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) { default: break; } - Mutex::Autolock _l(mAudioFlinger->mLock); mAudioFlinger->audioConfigChanged_l(event, mId, param2); } void AudioFlinger::PlaybackThread::readOutputParameters() { mSampleRate = mOutput->sampleRate(); - mChannelCount = AudioSystem::popCount(mOutput->channels()); - + mChannels = mOutput->channels(); + mChannelCount = (uint16_t)AudioSystem::popCount(mChannels); mFormat = mOutput->format(); - mFrameSize = mOutput->frameSize(); + mFrameSize = (uint16_t)mOutput->frameSize(); mFrameCount = mOutput->bufferSize() / mFrameSize; // FIXME - Current mixer implementation only supports stereo output: Always @@ -1604,66 +1613,22 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp >& tracks, - SortedVector < wp >& activeTracks, - int streamType) +void AudioFlinger::MixerThread::invalidateTracks(int streamType) { - LOGV ("MixerThread::getTracks() mixer %p, mTracks.size %d, mActiveTracks.size %d", this, mTracks.size(), mActiveTracks.size()); + LOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d", this, streamType, mTracks.size()); Mutex::Autolock _l(mLock); size_t size = mTracks.size(); for (size_t i = 0; i < size; i++) { sp t = mTracks[i]; if (t->type() == streamType) { - tracks.add(t); - int j = mActiveTracks.indexOf(t); - if (j >= 0) { - t = mActiveTracks[j].promote(); - if (t != NULL) { - activeTracks.add(t); + t->mCblk->lock.lock(); + t->mCblk->flags |= CBLK_INVALID_ON; + t->mCblk->cv.signal(); + t->mCblk->lock.unlock(); } } } - } - - size = activeTracks.size(); - for (size_t i = 0; i < size; i++) { - mActiveTracks.remove(activeTracks[i]); - } - - size = tracks.size(); - for (size_t i = 0; i < size; i++) { - sp t = tracks[i]; - mTracks.remove(t); - deleteTrackName_l(t->name()); - } -} - -void AudioFlinger::MixerThread::putTracks( - SortedVector < sp >& tracks, - SortedVector < wp >& activeTracks) -{ - LOGV ("MixerThread::putTracks() mixer %p, tracks.size %d, activeTracks.size %d", this, tracks.size(), activeTracks.size()); - Mutex::Autolock _l(mLock); - size_t size = tracks.size(); - for (size_t i = 0; i < size ; i++) { - sp t = tracks[i]; - int name = getTrackName_l(); - - if (name < 0) return; - - t->mName = name; - t->mThread = this; - mTracks.add(t); - int j = activeTracks.indexOf(t); - if (j >= 0) { - mActiveTracks.add(t); - // force buffer refilling and no ramp volume when the track is mixed for the first time - t->mFillingUpStatus = Track::FS_FILLING; - } - } -} // getTrackName_l() must be called with ThreadBase::mLock held int AudioFlinger::MixerThread::getTrackName_l() @@ -2332,13 +2297,13 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( // clear all buffers mCblk->frameCount = frameCount; mCblk->sampleRate = sampleRate; - mCblk->channels = (uint8_t)channelCount; + mCblk->channelCount = (uint8_t)channelCount; if (sharedBuffer == 0) { mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); // Force underrun condition to avoid false underrun callback until first data is // written to buffer - mCblk->flowControlFlag = 1; + mCblk->flags = CBLK_UNDERRUN_ON; } else { mBuffer = sharedBuffer->pointer(); } @@ -2356,12 +2321,12 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( // clear all buffers mCblk->frameCount = frameCount; mCblk->sampleRate = sampleRate; - mCblk->channels = (uint8_t)channelCount; + mCblk->channelCount = (uint8_t)channelCount; mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); // Force underrun condition to avoid false underrun callback until first data is // written to buffer - mCblk->flowControlFlag = 1; + mCblk->flags = CBLK_UNDERRUN_ON; mBufferEnd = (uint8_t *)mBuffer + bufferSize; } } @@ -2423,7 +2388,7 @@ int AudioFlinger::ThreadBase::TrackBase::sampleRate() const { } int AudioFlinger::ThreadBase::TrackBase::channelCount() const { - return (int)mCblk->channels; + return (int)mCblk->channelCount; } void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const { @@ -2435,9 +2400,9 @@ void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t f if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd || ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) { LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \ - server %d, serverBase %d, user %d, userBase %d, channels %d", + server %d, serverBase %d, user %d, userBase %d, channelCount %d", bufferStart, bufferEnd, mBuffer, mBufferEnd, - cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channels); + cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channelCount); return 0; } @@ -2522,7 +2487,7 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) (mClient == NULL) ? getpid() : mClient->pid(), mStreamType, mFormat, - mCblk->channels, + mCblk->channelCount, mFrameCount, mState, mMute, @@ -2579,9 +2544,9 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const { if (mFillingUpStatus != FS_FILLING) return true; if (mCblk->framesReady() >= mCblk->frameCount || - mCblk->forceReady) { + (mCblk->flags & CBLK_FORCEREADY_MSK)) { mFillingUpStatus = FS_FILLED; - mCblk->forceReady = 0; + mCblk->flags &= ~CBLK_FORCEREADY_MSK; return true; } return false; @@ -2696,8 +2661,8 @@ void AudioFlinger::PlaybackThread::Track::reset() TrackBase::reset(); // Force underrun condition to avoid false underrun callback until first data is // written to buffer - mCblk->flowControlFlag = 1; - mCblk->forceReady = 0; + mCblk->flags |= CBLK_UNDERRUN_ON; + mCblk->flags &= ~CBLK_FORCEREADY_MSK; mFillingUpStatus = FS_FILLING; mResetDone = true; } @@ -2808,7 +2773,7 @@ void AudioFlinger::RecordThread::RecordTrack::stop() TrackBase::reset(); // Force overerrun condition to avoid false overrun callback until first data is // read from buffer - mCblk->flowControlFlag = 1; + mCblk->flags |= CBLK_UNDERRUN_ON; } } @@ -2817,7 +2782,7 @@ void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size) snprintf(buffer, size, " %05d %03u %03u %04u %01d %05u %08x %08x\n", (mClient == NULL) ? getpid() : mClient->pid(), mFormat, - mCblk->channels, + mCblk->channelCount, mFrameCount, mState, mCblk->sampleRate, @@ -2841,13 +2806,13 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get(); if (mCblk != NULL) { - mCblk->out = 1; + mCblk->flags |= CBLK_DIRECTION_OUT; mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); mCblk->volume[0] = mCblk->volume[1] = 0x1000; mOutBuffer.frameCount = 0; playbackThread->mTracks.add(this); - LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p", - mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd); + LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channelCount %d mBufferEnd %p", + mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channelCount, mBufferEnd); } else { LOGW("Error creating output track on thread %p", playbackThread); } @@ -2882,7 +2847,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr { Buffer *pInBuffer; Buffer inBuffer; - uint32_t channels = mCblk->channels; + uint32_t channelCount = mCblk->channelCount; bool outputBufferFull = false; inBuffer.frameCount = frames; inBuffer.i16 = data; @@ -2898,10 +2863,10 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr if (mBufferQueue.size() < kMaxOverFlowBuffers) { uint32_t startFrames = (mCblk->frameCount - frames); pInBuffer = new Buffer; - pInBuffer->mBuffer = new int16_t[startFrames * channels]; + pInBuffer->mBuffer = new int16_t[startFrames * channelCount]; pInBuffer->frameCount = startFrames; pInBuffer->i16 = pInBuffer->mBuffer; - memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t)); + memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t)); mBufferQueue.add(pInBuffer); } else { LOGW ("OutputTrack::write() %p no more buffers in queue", this); @@ -2939,12 +2904,12 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr } uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount; - memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t)); + memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t)); mCblk->stepUser(outFrames); pInBuffer->frameCount -= outFrames; - pInBuffer->i16 += outFrames * channels; + pInBuffer->i16 += outFrames * channelCount; mOutBuffer.frameCount -= outFrames; - mOutBuffer.i16 += outFrames * channels; + mOutBuffer.i16 += outFrames * channelCount; if (pInBuffer->frameCount == 0) { if (mBufferQueue.size()) { @@ -2964,10 +2929,10 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr if (thread != 0 && !thread->standby()) { if (mBufferQueue.size() < kMaxOverFlowBuffers) { pInBuffer = new Buffer; - pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels]; + pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount]; pInBuffer->frameCount = inBuffer.frameCount; pInBuffer->i16 = pInBuffer->mBuffer; - memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t)); + memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t)); mBufferQueue.add(pInBuffer); LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size()); } else { @@ -2983,10 +2948,10 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr if (mCblk->user < mCblk->frameCount) { frames = mCblk->frameCount - mCblk->user; pInBuffer = new Buffer; - pInBuffer->mBuffer = new int16_t[frames * channels]; + pInBuffer->mBuffer = new int16_t[frames * channelCount]; pInBuffer->frameCount = frames; pInBuffer->i16 = pInBuffer->mBuffer; - memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t)); + memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t)); mBufferQueue.add(pInBuffer); } else if (mActive) { stop(); @@ -3086,6 +3051,28 @@ const sp& AudioFlinger::Client::heap() const // ---------------------------------------------------------------------------- +AudioFlinger::NotificationClient::NotificationClient(const sp& audioFlinger, + const sp& client, + pid_t pid) + : mAudioFlinger(audioFlinger), mPid(pid), mClient(client) +{ +} + +AudioFlinger::NotificationClient::~NotificationClient() +{ + mClient.clear(); +} + +void AudioFlinger::NotificationClient::binderDied(const wp& who) +{ + sp keep(this); + { + mAudioFlinger->removeNotificationClient(mPid); + } +} + +// ---------------------------------------------------------------------------- + AudioFlinger::TrackHandle::TrackHandle(const sp& track) : BnAudioTrack(), mTrack(track) @@ -3242,7 +3229,6 @@ AudioFlinger::RecordThread::RecordThread(const sp& audioFlinger, A mReqChannelCount = AudioSystem::popCount(channels); mReqSampleRate = sampleRate; readInputParameters(); - sendConfigEvent(AudioSystem::INPUT_OPENED); } @@ -3339,7 +3325,7 @@ bool AudioFlinger::RecordThread::threadLoop() framesIn = framesOut; mRsmpInIndex += framesIn; framesOut -= framesIn; - if (mChannelCount == mReqChannelCount || + if ((int)mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT) { memcpy(dst, src, framesIn * mFrameSize); } else { @@ -3360,7 +3346,7 @@ bool AudioFlinger::RecordThread::threadLoop() } if (framesOut && mFrameCount == mRsmpInIndex) { if (framesOut == mFrameCount && - (mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) { + ((int)mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) { mBytesRead = mInput->read(buffer.raw, mInputBytes); framesOut = 0; } else { @@ -3657,14 +3643,14 @@ String8 AudioFlinger::RecordThread::getParameters(const String8& keys) return mInput->getParameters(keys); } -void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) { +void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) { AudioSystem::OutputDescriptor desc; void *param2 = 0; switch (event) { case AudioSystem::INPUT_OPENED: case AudioSystem::INPUT_CONFIG_CHANGED: - desc.channels = mChannelCount; + desc.channels = mChannels; desc.samplingRate = mSampleRate; desc.format = mFormat; desc.frameCount = mFrameCount; @@ -3676,7 +3662,6 @@ void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) { default: break; } - Mutex::Autolock _l(mAudioFlinger->mLock); mAudioFlinger->audioConfigChanged_l(event, mId, param2); } @@ -3688,9 +3673,10 @@ void AudioFlinger::RecordThread::readInputParameters() mResampler = 0; mSampleRate = mInput->sampleRate(); - mChannelCount = AudioSystem::popCount(mInput->channels()); + mChannels = mInput->channels(); + mChannelCount = (uint16_t)AudioSystem::popCount(mChannels); mFormat = mInput->format(); - mFrameSize = mInput->frameSize(); + mFrameSize = (uint16_t)mInput->frameSize(); mInputBytes = mInput->bufferSize(); mFrameCount = mInputBytes / mFrameSize; mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount]; @@ -3795,6 +3781,8 @@ int AudioFlinger::openOutput(uint32_t *pDevices, if (pChannels) *pChannels = channels; if (pLatencyMs) *pLatencyMs = thread->latency(); + // notify client processes of the new output creation + thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED); return mNextThreadId; } @@ -3816,6 +3804,8 @@ int AudioFlinger::openDuplicateOutput(int output1, int output2) DuplicatingThread *thread = new DuplicatingThread(this, thread1, ++mNextThreadId); thread->addOutputTrack(thread2); mPlaybackThreads.add(mNextThreadId, thread); + // notify client processes of the new output creation + thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED); return mNextThreadId; } @@ -3945,6 +3935,8 @@ int AudioFlinger::openInput(uint32_t *pDevices, input->standby(); + // notify client processes of the new input creation + thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED); return mNextThreadId; } @@ -3985,22 +3977,16 @@ status_t AudioFlinger::setStreamOutput(uint32_t stream, int output) } LOGV("setStreamOutput() stream %d to output %d", stream, output); + audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream); for (size_t i = 0; i < mPlaybackThreads.size(); i++) { PlaybackThread *thread = mPlaybackThreads.valueAt(i).get(); if (thread != dstThread && thread->type() != PlaybackThread::DIRECT) { MixerThread *srcThread = (MixerThread *)thread; - SortedVector < sp > tracks; - SortedVector < wp > activeTracks; - srcThread->getTracks(tracks, activeTracks, stream); - if (tracks.size()) { - dstThread->putTracks(tracks, activeTracks); + srcThread->invalidateTracks(stream); } } - } - - dstThread->sendConfigEvent(AudioSystem::STREAM_CONFIG_CHANGED, stream); return NO_ERROR; } diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index 739ec3331165bef3cc34cff1ca259e7a170e7fc6..f35f38bc4eafa9e40c44b24afa9ed2b2623ee72c 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -57,7 +57,7 @@ class AudioResampler; static const nsecs_t kStandbyTimeInNsecs = seconds(3); -class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient +class AudioFlinger : public BnAudioFlinger { public: static void instantiate(); @@ -139,9 +139,6 @@ public: virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output); - // IBinder::DeathRecipient - virtual void binderDied(const wp& who); - enum hardware_call_state { AUDIO_HW_IDLE = 0, AUDIO_HW_INIT, @@ -205,6 +202,27 @@ private: pid_t mPid; }; + // --- Notification Client --- + class NotificationClient : public IBinder::DeathRecipient { + public: + NotificationClient(const sp& audioFlinger, + const sp& client, + pid_t pid); + virtual ~NotificationClient(); + + sp client() { return mClient; } + + // IBinder::DeathRecipient + virtual void binderDied(const wp& who); + + private: + NotificationClient(const NotificationClient&); + NotificationClient& operator = (const NotificationClient&); + + sp mAudioFlinger; + pid_t mPid; + sp mClient; + }; class TrackHandle; class RecordHandle; @@ -324,7 +342,7 @@ private: virtual bool checkForNewParameters_l() = 0; virtual status_t setParameters(const String8& keyValuePairs); virtual String8 getParameters(const String8& keys) = 0; - virtual void audioConfigChanged(int event, int param = 0) = 0; + virtual void audioConfigChanged_l(int event, int param = 0) = 0; void sendConfigEvent(int event, int param = 0); void sendConfigEvent_l(int event, int param = 0); void processConfigEvents(); @@ -348,9 +366,10 @@ private: sp mAudioFlinger; uint32_t mSampleRate; size_t mFrameCount; - int mChannelCount; + uint32_t mChannels; + uint16_t mChannelCount; + uint16_t mFrameSize; int mFormat; - uint32_t mFrameSize; Condition mParamCond; Vector mNewParameters; status_t mParamStatus; @@ -528,7 +547,7 @@ private: void restore() { if (mSuspended) mSuspended--; } bool isSuspended() { return (mSuspended != 0); } virtual String8 getParameters(const String8& keys); - virtual void audioConfigChanged(int event, int param = 0); + virtual void audioConfigChanged_l(int event, int param = 0); virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames); struct stream_type_t { @@ -594,11 +613,7 @@ private: // Thread virtuals virtual bool threadLoop(); - void getTracks(SortedVector < sp >& tracks, - SortedVector < wp >& activeTracks, - int streamType); - void putTracks(SortedVector < sp >& tracks, - SortedVector < wp >& activeTracks); + void invalidateTracks(int streamType); virtual bool checkForNewParameters_l(); virtual status_t dumpInternals(int fd, const Vector& args); @@ -685,6 +700,7 @@ private: void removeClient_l(pid_t pid); + void removeNotificationClient(pid_t pid); // record thread @@ -744,7 +760,7 @@ private: virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); virtual bool checkForNewParameters_l(); virtual String8 getParameters(const String8& keys); - virtual void audioConfigChanged(int event, int param = 0); + virtual void audioConfigChanged_l(int event, int param = 0); void readInputParameters(); virtual unsigned int getInputFramesLost(); @@ -796,8 +812,11 @@ private: DefaultKeyedVector< int, sp > mRecordThreads; - SortedVector< sp > mNotificationClients; + DefaultKeyedVector< pid_t, sp > mNotificationClients; int mNextThreadId; +#ifdef LVMX + int mLifeVibesClientPid; +#endif }; // ---------------------------------------------------------------------------- diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp index c8b3f487a02c9bd966c4deaa58ecc451e578bcd7..381a95803b677606e7272b4e64da64e159b0e129 100644 --- a/libs/audioflinger/AudioPolicyManagerBase.cpp +++ b/libs/audioflinger/AudioPolicyManagerBase.cpp @@ -1249,6 +1249,17 @@ void AudioPolicyManagerBase::closeA2dpOutputs() LOGV("setDeviceConnectionState() closing A2DP and duplicated output!"); if (mDuplicatedOutput != 0) { + AudioOutputDescriptor *dupOutputDesc = mOutputs.valueFor(mDuplicatedOutput); + AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput); + // As all active tracks on duplicated output will be deleted, + // and as they were also referenced on hardware output, the reference + // count for their stream type must be adjusted accordingly on + // hardware output. + for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) { + int refCount = dupOutputDesc->mRefCount[i]; + hwOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount); + } + mpClientInterface->closeOutput(mDuplicatedOutput); delete mOutputs.valueFor(mDuplicatedOutput); mOutputs.removeItem(mDuplicatedOutput); @@ -1288,11 +1299,6 @@ void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy, u for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) { if (getStrategy((AudioSystem::stream_type)i) == strategy) { mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, mHardwareOutput); - int refCount = a2dpOutputDesc->mRefCount[i]; - // in the case of duplicated output, the ref count is first incremented - // and then decremented on hardware output tus keeping its value - hwOutputDesc->changeRefCount((AudioSystem::stream_type)i, refCount); - a2dpOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount); } } // do not change newDevice if it was already set before this call by a previous call to @@ -1318,11 +1324,6 @@ void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy, u for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) { if (getStrategy((AudioSystem::stream_type)i) == strategy) { mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, a2dpOutput); - int refCount = hwOutputDesc->mRefCount[i]; - // in the case of duplicated output, the ref count is first incremented - // and then decremented on hardware output tus keeping its value - a2dpOutputDesc->changeRefCount((AudioSystem::stream_type)i, refCount); - hwOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount); } } } diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp index f19c502d92ee6d0deba8a40eed776e7150c32396..2fbddd55c613a68e792761e696d5d6d082a4b516 100644 --- a/libs/camera/Camera.cpp +++ b/libs/camera/Camera.cpp @@ -92,16 +92,28 @@ void Camera::init() Camera::~Camera() { - disconnect(); + // We don't need to call disconnect() here because if the CameraService + // thinks we are the owner of the hardware, it will hold a (strong) + // reference to us, and we can't possibly be here. We also don't want to + // call disconnect() here if we are in the same process as mediaserver, + // because we may be invoked by CameraService::Client::connect() and will + // deadlock if we call any method of ICamera here. } -sp Camera::connect() +int32_t Camera::getNumberOfCameras() +{ + const sp& cs = getCameraService(); + if (cs == 0) return 0; + return cs->getNumberOfCameras(); +} + +sp Camera::connect(int cameraId) { LOGV("connect"); sp c = new Camera(); const sp& cs = getCameraService(); if (cs != 0) { - c->mCamera = cs->connect(c); + c->mCamera = cs->connect(c, cameraId); } if (c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp index 65fd7ac7b217b8518c257f76d50c81b6f54483df..e4d5bb3eba4f9f9f7351d7edab3818718ef88482 100644 --- a/libs/camera/CameraParameters.cpp +++ b/libs/camera/CameraParameters.cpp @@ -69,8 +69,11 @@ const char CameraParameters::KEY_MAX_ZOOM[] = "max-zoom"; const char CameraParameters::KEY_ZOOM_RATIOS[] = "zoom-ratios"; const char CameraParameters::KEY_ZOOM_SUPPORTED[] = "zoom-supported"; const char CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED[] = "smooth-zoom-supported"; +const char CameraParameters::KEY_FOCUS_DISTANCES[] = "focus-distances"; +const char CameraParameters::KEY_VIDEO_FRAME_FORMAT[] = "video-frame-format"; const char CameraParameters::TRUE[] = "true"; +const char CameraParameters::FOCUS_DISTANCE_INFINITY[] = "Infinity"; // Values for white balance settings. const char CameraParameters::WHITE_BALANCE_AUTO[] = "auto"; @@ -137,6 +140,7 @@ const char CameraParameters::FOCUS_MODE_INFINITY[] = "infinity"; const char CameraParameters::FOCUS_MODE_MACRO[] = "macro"; const char CameraParameters::FOCUS_MODE_FIXED[] = "fixed"; const char CameraParameters::FOCUS_MODE_EDOF[] = "edof"; +const char CameraParameters::FOCUS_MODE_CONTINUOUS[] = "continuous"; CameraParameters::CameraParameters() : mMap() diff --git a/libs/camera/ICameraService.cpp b/libs/camera/ICameraService.cpp index 46b54786a25b8b0b29cca4e1b7b40f206b5fd423..db1dca6bdde60577b153dfd6bdaf884c1c586755 100644 --- a/libs/camera/ICameraService.cpp +++ b/libs/camera/ICameraService.cpp @@ -34,12 +34,22 @@ public: { } + // get number of cameras available + virtual int32_t getNumberOfCameras() + { + Parcel data, reply; + data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); + remote()->transact(BnCameraService::GET_NUMBER_OF_CAMERAS, data, &reply); + return reply.readInt32(); + } + // connect to camera service - virtual sp connect(const sp& cameraClient) + virtual sp connect(const sp& cameraClient, int cameraId) { Parcel data, reply; data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); data.writeStrongBinder(cameraClient->asBinder()); + data.writeInt32(cameraId); remote()->transact(BnCameraService::CONNECT, data, &reply); return interface_cast(reply.readStrongBinder()); } @@ -53,10 +63,15 @@ status_t BnCameraService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { + case GET_NUMBER_OF_CAMERAS: { + CHECK_INTERFACE(ICameraService, data, reply); + reply->writeInt32(getNumberOfCameras()); + return NO_ERROR; + } break; case CONNECT: { CHECK_INTERFACE(ICameraService, data, reply); sp cameraClient = interface_cast(data.readStrongBinder()); - sp camera = connect(cameraClient); + sp camera = connect(cameraClient, data.readInt32()); reply->writeStrongBinder(camera->asBinder()); return NO_ERROR; } break; diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp index 478a6dcbcc210980579aed2ec6d9dea160befe71..70e2868bc3368ff5c3e303acc1ae3e3487c28d53 100644 --- a/libs/rs/rsProgram.cpp +++ b/libs/rs/rsProgram.cpp @@ -195,7 +195,7 @@ bool Program::loadShader(Context *rsc, uint32_t type) if (rsc->props.mLogShaders) { LOGV("Loading shader type %x, ID %i", type, mShaderID); - LOGV(mShader.string()); + LOGV("%s", mShader.string()); } if (mShaderID) { diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index 1f2377309a8fa3aa95edcad2debc2d340d6d8aab..f4d24516c08a086c414e0dd2ac76fea47ae83cfa 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -159,7 +159,7 @@ void ScriptCState::runCompiler(Context *rsc, ScriptC *s) ACCchar buf[4096]; ACCsizei len; accGetScriptInfoLog(s->mAccScript, sizeof(buf), &len, buf); - LOGE(buf); + LOGE("%s", buf); rsc->setError(RS_ERROR_BAD_SCRIPT, "Error compiling user script."); return; } @@ -345,7 +345,7 @@ void ScriptCState::appendTypes(const Context *rsc, String8 *str) s.append(e->getName()); s.append("\n\n"); if (rsc->props.mLogScripts) { - LOGV(s); + LOGV("%s", static_cast(s)); } str->append(s); } @@ -372,7 +372,7 @@ void ScriptCState::appendTypes(const Context *rsc, String8 *str) s.append(mSlotNames[ct]); s.append(";\n"); if (rsc->props.mLogScripts) { - LOGV(s); + LOGV("%s", static_cast(s)); } str->append(s); } diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index 86eb78d8dd9d346cd6af0b2956ecf92166af2ee2..b8a0630ac69189d2e2bb68b08d22ffcba8b045b2 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -13,6 +13,7 @@ LOCAL_SRC_FILES:= \ LayerDim.cpp \ MessageQueue.cpp \ SurfaceFlinger.cpp \ + TextureManager.cpp \ Tokenizer.cpp \ Transform.cpp diff --git a/libs/surfaceflinger/Barrier.h b/libs/surfaceflinger/Barrier.h index e2bcf6a049e550b7d01cbe66f57366cefce2d245..6f8507e241b062d3fe1a5fe664361593c63cb41d 100644 --- a/libs/surfaceflinger/Barrier.h +++ b/libs/surfaceflinger/Barrier.h @@ -29,10 +29,6 @@ public: inline Barrier() : state(CLOSED) { } inline ~Barrier() { } void open() { - // gcc memory barrier, this makes sure all memory writes - // have been issued by gcc. On an SMP system we'd need a real - // h/w barrier. - asm volatile ("":::"memory"); Mutex::Autolock _l(lock); state = OPENED; cv.broadcast(); diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index ea68352828f1fb5857ccc80e73e5cb692c4ed421..51de1da723ef7642444de6d9fdc1d119ff98773b 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -73,7 +73,7 @@ void checkEGLErrors(const char* token) DisplayHardware::DisplayHardware( const sp& flinger, uint32_t dpy) - : DisplayHardwareBase(flinger, dpy) + : DisplayHardwareBase(flinger, dpy), mFlags(0) { init(dpy); } @@ -125,7 +125,6 @@ void DisplayHardware::init(uint32_t dpy) EGLint numConfigs=0; EGLSurface surface; EGLContext context; - mFlags = CACHED_BUFFERS; // TODO: all the extensions below should be queried through // eglGetProcAddress(). @@ -253,22 +252,10 @@ void DisplayHardware::init(uint32_t dpy) LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize); LOGI("GL_MAX_VIEWPORT_DIMS = %d", mMaxViewportDims); -#if 0 - // for drivers that don't have proper support for flushing cached buffers - // on gralloc unlock, uncomment this block and test for the specific - // renderer substring - if (strstr(gl_renderer, "")) { - LOGD("Assuming uncached graphics buffers."); - mFlags &= ~CACHED_BUFFERS; - } -#endif if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) { mFlags |= NPOT_EXTENSION; } - if (strstr(gl_extensions, "GL_OES_draw_texture")) { - mFlags |= DRAW_TEXTURE_EXTENSION; - } #ifdef EGL_ANDROID_image_native_buffer if (strstr( gl_extensions, "GL_OES_EGL_image") && (strstr(egl_extensions, "EGL_KHR_image_base") || diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index df046af95aa7b3e2a84b241886ffec2da83e2ba9..ebd7c4271c048463abb88f226553b4c086b9e23c 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -46,12 +46,10 @@ public: DIRECT_TEXTURE = 0x00000002, COPY_BITS_EXTENSION = 0x00000008, NPOT_EXTENSION = 0x00000100, - DRAW_TEXTURE_EXTENSION = 0x00000200, BUFFER_PRESERVED = 0x00010000, PARTIAL_UPDATES = 0x00020000, // video driver feature SLOW_CONFIG = 0x00040000, // software SWAP_RECTANGLE = 0x00080000, - CACHED_BUFFERS = 0x00100000 }; DisplayHardware( diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index ce7e9aa3f9bc5a41710328dabbdd79585c114723..3fbb4d386fe8f4fefbfefdee1693e442a370553c 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -47,47 +47,42 @@ template inline T min(T a, T b) { // --------------------------------------------------------------------------- -const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4; -const char* const Layer::typeID = "Layer"; - -// --------------------------------------------------------------------------- - Layer::Layer(SurfaceFlinger* flinger, DisplayID display, - const sp& c, int32_t i) - : LayerBaseClient(flinger, display, c, i), + const sp& client, int32_t i) + : LayerBaseClient(flinger, display, client, i), + lcblk(NULL), mSecure(false), - mNoEGLImageForSwBuffers(false), mNeedsBlending(true), - mNeedsDithering(false) + mNeedsDithering(false), + mTextureManager(mFlags), + mBufferManager(mTextureManager), + mWidth(0), mHeight(0), mFixedSize(false) { // no OpenGL operation is possible here, since we might not be // in the OpenGL thread. - mFrontBufferIndex = lcblk->getFrontBuffer(); + lcblk = new SharedBufferServer( + client->ctrlblk, i, mBufferManager.getDefaultBufferCount(), + getIdentity()); + + mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() ); } Layer::~Layer() { - destroy(); + // FIXME: must be called from the main UI thread + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + mBufferManager.destroy(dpy); + // the actual buffers will be destroyed here + delete lcblk; } -void Layer::destroy() +// called with SurfaceFlinger::mStateLock as soon as the layer is entered +// in the purgatory list +void Layer::onRemoved() { - for (size_t i=0 ; igraphicPlane(0).getEGLDisplay()); - eglDestroyImageKHR(dpy, mTextures[i].image); - mTextures[i].image = EGL_NO_IMAGE_KHR; - } - Mutex::Autolock _l(mLock); - mBuffers[i].clear(); - mWidth = mHeight = 0; - } - mSurface.clear(); + // wake up the condition + lcblk->setStatus(NO_INIT); } sp Layer::createSurface() const @@ -97,9 +92,17 @@ sp Layer::createSurface() const status_t Layer::ditch() { + // NOTE: Called from the main UI thread + // the layer is not on screen anymore. free as much resources as possible mFreezeLock.clear(); - destroy(); + + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + mBufferManager.destroy(dpy); + mSurface.clear(); + + Mutex::Autolock _l(mLock); + mWidth = mHeight = 0; return NO_ERROR; } @@ -131,24 +134,19 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, mHeight = h; mSecure = (flags & ISurfaceComposer::eSecure) ? true : false; mNeedsBlending = (info.h_alpha - info.l_alpha) > 0; - mNoEGLImageForSwBuffers = !(hwFlags & DisplayHardware::CACHED_BUFFERS); // we use the red index int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED); int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED); mNeedsDithering = layerRedsize > displayRedSize; - for (size_t i=0 ; i buffer(getFrontBufferLocked()); + sp buffer(mBufferManager.getActiveBuffer()); if (buffer == NULL) { // this situation can happen if we ran out of memory for instance. // not much we can do. continue to use whatever texture was bound @@ -156,118 +154,24 @@ void Layer::reloadTexture(const Region& dirty) return; } - const int index = mFrontBufferIndex; - - // create the new texture name if needed - if (UNLIKELY(mTextures[index].name == -1U)) { - mTextures[index].name = createTexture(); - mTextures[index].width = 0; - mTextures[index].height = 0; - } - #ifdef EGL_ANDROID_image_native_buffer if (mFlags & DisplayHardware::DIRECT_TEXTURE) { - if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) { - if (mTextures[index].dirty) { - if (initializeEglImage(buffer, &mTextures[index]) != NO_ERROR) { - // not sure what we can do here... - mFlags &= ~DisplayHardware::DIRECT_TEXTURE; - goto slowpath; - } - } - } else { - if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width || - mHybridBuffer->height != buffer->height)) { - mHybridBuffer.clear(); - mHybridBuffer = new GraphicBuffer( - buffer->width, buffer->height, buffer->format, - GraphicBuffer::USAGE_SW_WRITE_OFTEN | - GraphicBuffer::USAGE_HW_TEXTURE); - if (initializeEglImage( - mHybridBuffer, &mTextures[0]) != NO_ERROR) { - // not sure what we can do here... - mFlags &= ~DisplayHardware::DIRECT_TEXTURE; - mHybridBuffer.clear(); - goto slowpath; - } - } - - GGLSurface t; - status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN); - LOGE_IF(res, "error %d (%s) locking buffer %p", - res, strerror(res), buffer.get()); - if (res == NO_ERROR) { - Texture* const texture(&mTextures[0]); - - glBindTexture(GL_TEXTURE_2D, texture->name); - - sp buf(mHybridBuffer); - void* vaddr; - res = buf->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &vaddr); - if (res == NO_ERROR) { - int bpp = 0; - switch (t.format) { - case HAL_PIXEL_FORMAT_RGB_565: - case HAL_PIXEL_FORMAT_RGBA_4444: - bpp = 2; - break; - case HAL_PIXEL_FORMAT_RGBA_8888: - case HAL_PIXEL_FORMAT_RGBX_8888: - bpp = 4; - break; - default: - if (isSupportedYuvFormat(t.format)) { - // just show the Y plane of YUV buffers - bpp = 1; - break; - } - // oops, we don't handle this format! - LOGE("layer %p, texture=%d, using format %d, which is not " - "supported by the GL", this, texture->name, t.format); - } - if (bpp) { - const Rect bounds(dirty.getBounds()); - size_t src_stride = t.stride; - size_t dst_stride = buf->stride; - if (src_stride == dst_stride && - bounds.width() == t.width && - bounds.height() == t.height) - { - memcpy(vaddr, t.data, t.height * t.stride * bpp); - } else { - GLubyte const * src = t.data + - (bounds.left + bounds.top * src_stride) * bpp; - GLubyte * dst = (GLubyte *)vaddr + - (bounds.left + bounds.top * dst_stride) * bpp; - const size_t length = bounds.width() * bpp; - size_t h = bounds.height(); - src_stride *= bpp; - dst_stride *= bpp; - while (h--) { - memcpy(dst, src, length); - dst += dst_stride; - src += src_stride; - } - } - } - buf->unlock(); - } - buffer->unlock(); - } + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) { + // not sure what we can do here... + mFlags &= ~DisplayHardware::DIRECT_TEXTURE; + goto slowpath; } } else #endif { slowpath: - for (size_t i=0 ; ilock(&t, GRALLOC_USAGE_SW_READ_OFTEN); LOGE_IF(res, "error %d (%s) locking buffer %p", res, strerror(res), buffer.get()); if (res == NO_ERROR) { - loadTexture(&mTextures[0], dirty, t); + mBufferManager.loadTexture(dirty, t); buffer->unlock(); } } @@ -275,11 +179,8 @@ slowpath: void Layer::onDraw(const Region& clip) const { - int index = mFrontBufferIndex; - if (mTextures[index].image == EGL_NO_IMAGE_KHR) - index = 0; - GLuint textureName = mTextures[index].name; - if (UNLIKELY(textureName == -1LU)) { + Texture tex(mBufferManager.getActiveTexture()); + if (tex.name == -1LU) { // the texture has not been created yet, this Layer has // in fact never been drawn into. This happens frequently with // SurfaceView because the WindowManager can't know when the client @@ -305,13 +206,53 @@ void Layer::onDraw(const Region& clip) const } return; } - drawWithOpenGL(clip, mTextures[index]); + drawWithOpenGL(clip, tex); +} + +bool Layer::needsFiltering() const +{ + if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { + // NOTE: there is a race here, because mFixedSize is updated in a + // binder transaction. however, it doesn't really matter since it is + // evaluated each time we draw. To be perfectly correct, this flag + // would have to be associated with a buffer. + if (mFixedSize) + return true; + } + return LayerBase::needsFiltering(); +} + + +status_t Layer::setBufferCount(int bufferCount) +{ + // Ensures our client doesn't go away while we're accessing + // the shared area. + sp ourClient(client.promote()); + if (ourClient == 0) { + // oops, the client is already gone + return DEAD_OBJECT; + } + + // NOTE: lcblk->resize() is protected by an internal lock + status_t err = lcblk->resize(bufferCount); + if (err == NO_ERROR) + mBufferManager.resize(bufferCount); + + return err; } -sp Layer::requestBuffer(int index, int usage) +sp Layer::requestBuffer(int index, + uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat, + uint32_t usage) { sp buffer; + if ((reqWidth | reqHeight | reqFormat) < 0) + return buffer; + + if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight)) + return buffer; + // this ensures our client doesn't go away while we're accessing // the shared area. sp ourClient(client.promote()); @@ -324,7 +265,7 @@ sp Layer::requestBuffer(int index, int usage) * This is called from the client's Surface::dequeue(). This can happen * at any time, especially while we're in the middle of using the * buffer 'index' as our front buffer. - * + * * Make sure the buffer we're resizing is not the front buffer and has been * dequeued. Once this condition is asserted, we are guaranteed that this * buffer cannot become the front buffer under our feet, since we're called @@ -337,31 +278,33 @@ sp Layer::requestBuffer(int index, int usage) return buffer; } - uint32_t w, h; + uint32_t w, h, f; { // scope for the lock Mutex::Autolock _l(mLock); - w = mWidth; - h = mHeight; - buffer = mBuffers[index]; - - // destroy() could have been called before we get here, we log it - // because it's uncommon, and the code below should handle it - LOGW_IF(buffer==0, - "mBuffers[%d] is null (mWidth=%d, mHeight=%d)", - index, w, h); - - mBuffers[index].clear(); + const bool fixedSizeChanged = mFixedSize != (reqWidth && reqHeight); + const bool formatChanged = mReqFormat != reqFormat; + mReqWidth = reqWidth; + mReqHeight = reqHeight; + mReqFormat = reqFormat; + mFixedSize = reqWidth && reqHeight; + w = reqWidth ? reqWidth : mWidth; + h = reqHeight ? reqHeight : mHeight; + f = reqFormat ? reqFormat : mFormat; + buffer = mBufferManager.detachBuffer(index); + if (fixedSizeChanged || formatChanged) { + lcblk->reallocateAllExcept(index); + } } const uint32_t effectiveUsage = getEffectiveUsage(usage); if (buffer!=0 && buffer->getStrongCount() == 1) { - err = buffer->reallocate(w, h, mFormat, effectiveUsage); + err = buffer->reallocate(w, h, f, effectiveUsage); } else { // here we have to reallocate a new buffer because we could have a // client in our process with a reference to it (eg: status bar), // and we can't release the handle under its feet. buffer.clear(); - buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage); + buffer = new GraphicBuffer(w, h, f, effectiveUsage); err = buffer->initCheck(); } @@ -377,15 +320,7 @@ sp Layer::requestBuffer(int index, int usage) if (err == NO_ERROR && buffer->handle != 0) { Mutex::Autolock _l(mLock); - if (mWidth && mHeight) { - // and we have new buffer - mBuffers[index] = buffer; - // texture is now dirty... - mTextures[index].dirty = true; - } else { - // oops we got killed while we were allocating the buffer - buffer.clear(); - } + mBufferManager.attachBuffer(index, buffer); } return buffer; } @@ -411,15 +346,8 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const } else { // it's allowed to modify the usage flags here, but generally // the requested flags should be honored. - if (mNoEGLImageForSwBuffers) { - if (usage & GraphicBuffer::USAGE_HW_MASK) { - // request EGLImage for h/w buffers only - usage |= GraphicBuffer::USAGE_HW_TEXTURE; - } - } else { - // request EGLImage for all buffers - usage |= GraphicBuffer::USAGE_HW_TEXTURE; - } + // request EGLImage for all buffers + usage |= GraphicBuffer::USAGE_HW_TEXTURE; } return usage; } @@ -429,42 +357,46 @@ uint32_t Layer::doTransaction(uint32_t flags) const Layer::State& front(drawingState()); const Layer::State& temp(currentState()); - if ((front.requested_w != temp.requested_w) || - (front.requested_h != temp.requested_h)) { + const bool sizeChanged = (front.requested_w != temp.requested_w) || + (front.requested_h != temp.requested_h); + + if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer LOGD_IF(DEBUG_RESIZE, - "resize (layer=%p), requested (%dx%d), " - "drawing (%d,%d), (%dx%d), (%dx%d)", - this, - int(temp.requested_w), int(temp.requested_h), - int(front.requested_w), int(front.requested_h), - int(mBuffers[0]->getWidth()), int(mBuffers[0]->getHeight()), - int(mBuffers[1]->getWidth()), int(mBuffers[1]->getHeight())); - - // we're being resized and there is a freeze display request, - // acquire a freeze lock, so that the screen stays put - // until we've redrawn at the new size; this is to avoid - // glitches upon orientation changes. - if (mFlinger->hasFreezeRequest()) { - // if the surface is hidden, don't try to acquire the - // freeze lock, since hidden surfaces may never redraw - if (!(front.flags & ISurfaceComposer::eLayerHidden)) { - mFreezeLock = mFlinger->getFreezeLock(); + "resize (layer=%p), requested (%dx%d), drawing (%d,%d)", + this, + int(temp.requested_w), int(temp.requested_h), + int(front.requested_w), int(front.requested_h)); + + if (!isFixedSize()) { + // we're being resized and there is a freeze display request, + // acquire a freeze lock, so that the screen stays put + // until we've redrawn at the new size; this is to avoid + // glitches upon orientation changes. + if (mFlinger->hasFreezeRequest()) { + // if the surface is hidden, don't try to acquire the + // freeze lock, since hidden surfaces may never redraw + if (!(front.flags & ISurfaceComposer::eLayerHidden)) { + mFreezeLock = mFlinger->getFreezeLock(); + } } - } - // this will make sure LayerBase::doTransaction doesn't update - // the drawing state's size - Layer::State& editDraw(mDrawingState); - editDraw.requested_w = temp.requested_w; - editDraw.requested_h = temp.requested_h; + // this will make sure LayerBase::doTransaction doesn't update + // the drawing state's size + Layer::State& editDraw(mDrawingState); + editDraw.requested_w = temp.requested_w; + editDraw.requested_h = temp.requested_h; - // record the new size, form this point on, when the client request a - // buffer, it'll get the new size. - setDrawingSize(temp.requested_w, temp.requested_h); + // record the new size, form this point on, when the client request + // a buffer, it'll get the new size. + setBufferSize(temp.requested_w, temp.requested_h); - // all buffers need reallocation - lcblk->reallocate(); + // all buffers need reallocation + lcblk->reallocateAll(); + } else { + // record the new size + setBufferSize(temp.requested_w, temp.requested_h); + } } if (temp.sequence != front.sequence) { @@ -478,12 +410,17 @@ uint32_t Layer::doTransaction(uint32_t flags) return LayerBase::doTransaction(flags); } -void Layer::setDrawingSize(uint32_t w, uint32_t h) { +void Layer::setBufferSize(uint32_t w, uint32_t h) { Mutex::Autolock _l(mLock); mWidth = w; mHeight = h; } +bool Layer::isFixedSize() const { + Mutex::Autolock _l(mLock); + return mFixedSize; +} + // ---------------------------------------------------------------------------- // pageflip handling... // ---------------------------------------------------------------------------- @@ -491,22 +428,25 @@ void Layer::setDrawingSize(uint32_t w, uint32_t h) { void Layer::lockPageFlip(bool& recomputeVisibleRegions) { ssize_t buf = lcblk->retireAndLock(); - if (buf < NO_ERROR) { - //LOGW("nothing to retire (%s)", strerror(-buf)); - // NOTE: here the buffer is locked because we will used + if (buf == NOT_ENOUGH_DATA) { + // NOTE: This is not an error, it simply means there is nothing to + // retire. The buffer is locked because we will use it // for composition later in the loop return; } - // ouch, this really should never happen - if (uint32_t(buf)>=NUM_BUFFERS) { + if (buf < NO_ERROR) { LOGE("retireAndLock() buffer index (%d) out of range", buf); mPostedDirtyRegion.clear(); return; } // we retired a buffer, which becomes the new front buffer - mFrontBufferIndex = buf; + if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) { + LOGE("retireAndLock() buffer index (%d) out of range", buf); + mPostedDirtyRegion.clear(); + return; + } // get the dirty region sp newFrontBuffer(getBuffer(buf)); @@ -559,9 +499,15 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) mFlinger->signalEvent(); } - if (!mPostedDirtyRegion.isEmpty()) { - reloadTexture( mPostedDirtyRegion ); - } + /* a buffer was posted, so we need to call reloadTexture(), which + * will update our internal data structures (eg: EGLImageKHR or + * texture names). we need to do this even if mPostedDirtyRegion is + * empty -- it's orthogonal to the fact that a new buffer was posted, + * for instance, a degenerate case could be that the user did an empty + * update but repainted the buffer with appropriate content (after a + * resize for instance). + */ + reloadTexture( mPostedDirtyRegion ); } void Layer::unlockPageFlip( @@ -585,17 +531,177 @@ void Layer::unlockPageFlip( } if (visibleRegionScreen.isEmpty()) { // an invisible layer should not hold a freeze-lock - // (because it may never be updated and thereore never release it) + // (because it may never be updated and therefore never release it) mFreezeLock.clear(); } } void Layer::finishPageFlip() { - status_t err = lcblk->unlock( mFrontBufferIndex ); - LOGE_IF(err!=NO_ERROR, - "layer %p, buffer=%d wasn't locked!", - this, mFrontBufferIndex); + int buf = mBufferManager.getActiveBufferIndex(); + status_t err = lcblk->unlock( buf ); + LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf); +} + + +void Layer::dump(String8& result, char* buffer, size_t SIZE) const +{ + LayerBaseClient::dump(result, buffer, SIZE); + + SharedBufferStack::Statistics stats = lcblk->getStats(); + result.append( lcblk->dump(" ") ); + sp buf0(getBuffer(0)); + sp buf1(getBuffer(1)); + uint32_t w0=0, h0=0, s0=0; + uint32_t w1=0, h1=0, s1=0; + if (buf0 != 0) { + w0 = buf0->getWidth(); + h0 = buf0->getHeight(); + s0 = buf0->getStride(); + } + if (buf1 != 0) { + w1 = buf1->getWidth(); + h1 = buf1->getHeight(); + s1 = buf1->getStride(); + } + snprintf(buffer, SIZE, + " " + "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u]," + " freezeLock=%p, dq-q-time=%u us\n", + pixelFormat(), + w0, h0, s0, w1, h1, s1, + getFreezeLock().get(), stats.totalTime); + + result.append(buffer); +} + +// --------------------------------------------------------------------------- + +Layer::BufferManager::BufferManager(TextureManager& tm) + : mNumBuffers(NUM_BUFFERS), mTextureManager(tm), + mActiveBuffer(0), mFailover(false) +{ +} + +Layer::BufferManager::~BufferManager() +{ +} + +status_t Layer::BufferManager::resize(size_t size) +{ + Mutex::Autolock _l(mLock); + mNumBuffers = size; + return NO_ERROR; +} + +// only for debugging +sp Layer::BufferManager::getBuffer(size_t index) const { + return mBufferData[index].buffer; +} + +status_t Layer::BufferManager::setActiveBufferIndex(size_t index) { + // TODO: need to validate 'index' + mActiveBuffer = index; + return NO_ERROR; +} + +size_t Layer::BufferManager::getActiveBufferIndex() const { + return mActiveBuffer; +} + +Texture Layer::BufferManager::getActiveTexture() const { + Texture res; + if (mFailover) { + res = mFailoverTexture; + } else { + static_cast(res) = mBufferData[mActiveBuffer].texture; + } + return res; +} + +sp Layer::BufferManager::getActiveBuffer() const { + const size_t activeBuffer = mActiveBuffer; + BufferData const * const buffers = mBufferData; + Mutex::Autolock _l(mLock); + return buffers[activeBuffer].buffer; +} + +sp Layer::BufferManager::detachBuffer(size_t index) +{ + BufferData* const buffers = mBufferData; + sp buffer; + Mutex::Autolock _l(mLock); + buffer = buffers[index].buffer; + buffers[index].buffer = 0; + return buffer; +} + +status_t Layer::BufferManager::attachBuffer(size_t index, + const sp& buffer) +{ + BufferData* const buffers = mBufferData; + Mutex::Autolock _l(mLock); + buffers[index].buffer = buffer; + buffers[index].texture.dirty = true; + return NO_ERROR; +} + +status_t Layer::BufferManager::destroy(EGLDisplay dpy) +{ + BufferData* const buffers = mBufferData; + size_t num; + { // scope for the lock + Mutex::Autolock _l(mLock); + num = mNumBuffers; + for (size_t i=0 ; i& buffer) +{ + size_t index = mActiveBuffer; + Image& texture(mBufferData[index].texture); + status_t err = mTextureManager.initEglImage(&texture, dpy, buffer); + // if EGLImage fails, we switch to regular texture mode, and we + // free all resources associated with using EGLImages. + if (err == NO_ERROR) { + mFailover = false; + destroyTexture(&mFailoverTexture, dpy); + } else { + mFailover = true; + const size_t num = mNumBuffers; + for (size_t i=0 ; iname != -1U) { + glDeleteTextures(1, &tex->name); + tex->name = -1U; + } + if (tex->image != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(dpy, tex->image); + tex->image = EGL_NO_IMAGE_KHR; + } + return NO_ERROR; } // --------------------------------------------------------------------------- @@ -610,20 +716,37 @@ Layer::SurfaceLayer::~SurfaceLayer() { } -sp Layer::SurfaceLayer::requestBuffer(int index, int usage) +sp Layer::SurfaceLayer::requestBuffer(int index, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { sp buffer; sp owner(getOwner()); if (owner != 0) { - LOGE_IF(uint32_t(index)>=NUM_BUFFERS, - "getBuffer() index (%d) out of range", index); - if (uint32_t(index) < NUM_BUFFERS) { - buffer = owner->requestBuffer(index, usage); - } + /* + * requestBuffer() cannot be called from the main thread + * as it could cause a dead-lock, since it may have to wait + * on conditions updated my the main thread. + */ + buffer = owner->requestBuffer(index, w, h, format, usage); } return buffer; } +status_t Layer::SurfaceLayer::setBufferCount(int bufferCount) +{ + status_t err = DEAD_OBJECT; + sp owner(getOwner()); + if (owner != 0) { + /* + * setBufferCount() cannot be called from the main thread + * as it could cause a dead-lock, since it may have to wait + * on conditions updated my the main thread. + */ + err = owner->setBufferCount(bufferCount); + } + return err; +} + // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h index 743afb4c47162f92df2d4045e7efcc453e48a205..59603a58723ea121c762f07f295407c4c53d9068 100644 --- a/libs/surfaceflinger/Layer.h +++ b/libs/surfaceflinger/Layer.h @@ -31,6 +31,7 @@ #include "LayerBase.h" #include "Transform.h" +#include "TextureManager.h" namespace android { @@ -41,16 +42,13 @@ class FreezeLock; // --------------------------------------------------------------------------- -const size_t NUM_BUFFERS = 2; - class Layer : public LayerBaseClient { -public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - +public: + // lcblk is (almost) only accessed from the main SF thread, in the places + // where it's not, a reference to Client must be held + SharedBufferServer* lcblk; + Layer(SurfaceFlinger* flinger, DisplayID display, const sp& client, int32_t i); @@ -59,7 +57,8 @@ public: status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags=0); - void setDrawingSize(uint32_t w, uint32_t h); + void setBufferSize(uint32_t w, uint32_t h); + bool isFixedSize() const; virtual void onDraw(const Region& clip) const; virtual uint32_t doTransaction(uint32_t transactionFlags); @@ -68,30 +67,32 @@ public: virtual void finishPageFlip(); virtual bool needsBlending() const { return mNeedsBlending; } virtual bool needsDithering() const { return mNeedsDithering; } + virtual bool needsFiltering() const; virtual bool isSecure() const { return mSecure; } virtual sp createSurface() const; virtual status_t ditch(); + virtual void onRemoved(); // only for debugging - inline sp getBuffer(int i) { return mBuffers[i]; } + inline sp getBuffer(int i) const { return mBufferManager.getBuffer(i); } // only for debugging inline const sp& getFreezeLock() const { return mFreezeLock; } // only for debugging inline PixelFormat pixelFormat() const { return mFormat; } - // only for debugging - inline int getFrontBufferIndex() const { return mFrontBufferIndex; } + + virtual const char* getTypeId() const { return "Layer"; } + +protected: + virtual void dump(String8& result, char* scratch, size_t size) const; private: - inline sp getFrontBufferLocked() { - return mBuffers[mFrontBufferIndex]; - } - void reloadTexture(const Region& dirty); uint32_t getEffectiveUsage(uint32_t usage) const; - sp requestBuffer(int index, int usage); - void destroy(); + sp requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage); + status_t setBufferCount(int bufferCount); class SurfaceLayer : public LayerBaseClient::Surface { public: @@ -99,7 +100,9 @@ private: SurfaceID id, const sp& owner); ~SurfaceLayer(); private: - virtual sp requestBuffer(int index, int usage); + virtual sp requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage); + virtual status_t setBufferCount(int bufferCount); sp getOwner() const { return static_cast(Surface::getOwner().get()); } @@ -109,22 +112,83 @@ private: sp mSurface; bool mSecure; - bool mNoEGLImageForSwBuffers; int32_t mFrontBufferIndex; bool mNeedsBlending; bool mNeedsDithering; Region mPostedDirtyRegion; sp mFreezeLock; PixelFormat mFormat; - - // protected by mLock - sp mBuffers[NUM_BUFFERS]; - Texture mTextures[NUM_BUFFERS]; - sp mHybridBuffer; - uint32_t mWidth; - uint32_t mHeight; - - mutable Mutex mLock; + + class BufferManager { + static const size_t NUM_BUFFERS = 2; + struct BufferData { + sp buffer; + Image texture; + }; + // this lock protect mBufferData[].buffer but since there + // is very little contention, we have only one like for + // the whole array, we also use it to protect mNumBuffers. + mutable Mutex mLock; + BufferData mBufferData[SharedBufferStack::NUM_BUFFER_MAX]; + size_t mNumBuffers; + Texture mFailoverTexture; + TextureManager& mTextureManager; + ssize_t mActiveBuffer; + bool mFailover; + static status_t destroyTexture(Image* tex, EGLDisplay dpy); + + public: + static size_t getDefaultBufferCount() { return NUM_BUFFERS; } + BufferManager(TextureManager& tm); + ~BufferManager(); + + // detach/attach buffer from/to given index + sp detachBuffer(size_t index); + status_t attachBuffer(size_t index, const sp& buffer); + + // resize the number of active buffers + status_t resize(size_t size); + + // ---------------------------------------------- + // must be called from GL thread + + // set/get active buffer index + status_t setActiveBufferIndex(size_t index); + size_t getActiveBufferIndex() const; + + // return the active buffer + sp getActiveBuffer() const; + + // return the active texture (or fail-over) + Texture getActiveTexture() const; + + // frees resources associated with all buffers + status_t destroy(EGLDisplay dpy); + + // load bitmap data into the active buffer + status_t loadTexture(const Region& dirty, const GGLSurface& t); + + // make active buffer an EGLImage if needed + status_t initEglImage(EGLDisplay dpy, + const sp& buffer); + + // ---------------------------------------------- + // only for debugging + sp getBuffer(size_t index) const; + }; + + TextureManager mTextureManager; + BufferManager mBufferManager; + + // this lock protects mWidth and mHeight which are accessed from + // the main thread and requestBuffer's binder transaction thread. + mutable Mutex mLock; + uint32_t mWidth; + uint32_t mHeight; + uint32_t mReqWidth; + uint32_t mReqHeight; + uint32_t mReqFormat; + bool mFixedSize; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index a8b735ef6a53109fb2ba9d9d5320c5458a10bca2..76733a9d8c354b855040182cc2c233ce464d1815 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -32,29 +32,21 @@ #include "LayerBase.h" #include "SurfaceFlinger.h" #include "DisplayHardware/DisplayHardware.h" +#include "TextureManager.h" namespace android { // --------------------------------------------------------------------------- -const uint32_t LayerBase::typeInfo = 1; -const char* const LayerBase::typeID = "LayerBase"; - -const uint32_t LayerBaseClient::typeInfo = LayerBase::typeInfo | 2; -const char* const LayerBaseClient::typeID = "LayerBaseClient"; - -// --------------------------------------------------------------------------- - LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) : dpy(display), contentDirty(false), mFlinger(flinger), - mTransformed(false), - mUseLinearFiltering(false), + mNeedsFiltering(false), mOrientation(0), mLeft(0), mTop(0), mTransactionFlags(0), - mPremultipliedAlpha(true), mDebug(false), + mPremultipliedAlpha(true), mName("unnamed"), mDebug(false), mInvalidate(0) { const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware()); @@ -221,13 +213,12 @@ uint32_t LayerBase::doTransaction(uint32_t flags) flags |= eVisibleRegion; this->contentDirty = true; - const bool linearFiltering = mUseLinearFiltering; - mUseLinearFiltering = false; + mNeedsFiltering = false; if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { // we may use linear filtering, if the matrix scales us const uint8_t type = temp.transform.getType(); if (!temp.transform.preserveRects() || (type >= Transform::SCALE)) { - mUseLinearFiltering = true; + mNeedsFiltering = true; } } } @@ -267,7 +258,6 @@ void LayerBase::validateVisibility(const Transform& planeTransform) // cache a few things... mOrientation = tr.getOrientation(); mTransformedBounds = tr.makeBounds(w, h); - mTransformed = transformed; mLeft = tr.tx(); mTop = tr.ty(); } @@ -348,25 +338,13 @@ void LayerBase::draw(const Region& inClip) const */ } -GLuint LayerBase::createTexture() const -{ - GLuint textureName = -1; - glGenTextures(1, &textureName); - glBindTexture(GL_TEXTURE_2D, textureName); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - return textureName; -} - -void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red, - GLclampx green, GLclampx blue, - GLclampx alpha) const +void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red, + GLclampf green, GLclampf blue, + GLclampf alpha) const { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t fbHeight = hw.getHeight(); - glColor4x(red,green,blue,alpha); + glColor4f(red,green,blue,alpha); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glDisable(GL_DITHER); @@ -374,7 +352,7 @@ void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red, Region::const_iterator it = clip.begin(); Region::const_iterator const end = clip.end(); glEnable(GL_SCISSOR_TEST); - glVertexPointer(2, GL_FIXED, 0, mVertices); + glVertexPointer(2, GL_FLOAT, 0, mVertices); while (it != end) { const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); @@ -418,14 +396,14 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const env = GL_REPLACE; src = GL_SRC_ALPHA; } - const GGLfixed alpha = (s.alpha << 16)/255; - glColor4x(alpha, alpha, alpha, alpha); + const GLfloat alpha = s.alpha * (1.0f/255.0f); + glColor4f(alpha, alpha, alpha, alpha); glEnable(GL_BLEND); glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env); } else { glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glColor4x(0x10000, 0x10000, 0x10000, 0x10000); + glColor4f(1, 1, 1, 1); if (needsBlending()) { GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; glEnable(GL_BLEND); @@ -437,13 +415,11 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const Region::const_iterator it = clip.begin(); Region::const_iterator const end = clip.end(); - - //StopWatch watch("GL transformed"); - const GLfixed texCoords[4][2] = { - { 0, 0 }, - { 0, 0x10000 }, - { 0x10000, 0x10000 }, - { 0x10000, 0 } + const GLfloat texCoords[4][2] = { + { 0, 0 }, + { 0, 1 }, + { 1, 1 }, + { 1, 0 } }; glMatrixMode(GL_TEXTURE); @@ -470,8 +446,8 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const } glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(2, GL_FIXED, 0, mVertices); - glTexCoordPointer(2, GL_FIXED, 0, texCoords); + glVertexPointer(2, GL_FLOAT, 0, mVertices); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); while (it != end) { const Rect& r = *it++; @@ -487,7 +463,7 @@ void LayerBase::validateTexture(GLint textureName) const glBindTexture(GL_TEXTURE_2D, textureName); // TODO: reload the texture if needed // this is currently done in loadTexture() below - if (mUseLinearFiltering) { + if (needsFiltering()) { glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } else { @@ -502,200 +478,32 @@ void LayerBase::validateTexture(GLint textureName) const } } -bool LayerBase::isSupportedYuvFormat(int format) const +void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const { - switch (format) { - case HAL_PIXEL_FORMAT_YCbCr_422_SP: - case HAL_PIXEL_FORMAT_YCbCr_420_SP: - case HAL_PIXEL_FORMAT_YCbCr_422_P: - case HAL_PIXEL_FORMAT_YCbCr_420_P: - case HAL_PIXEL_FORMAT_YCbCr_422_I: - case HAL_PIXEL_FORMAT_YCbCr_420_I: - case HAL_PIXEL_FORMAT_YCrCb_420_SP: - return true; - } - return false; -} - -void LayerBase::loadTexture(Texture* texture, - const Region& dirty, const GGLSurface& t) const -{ - if (texture->name == -1U) { - // uh? - return; - } - - glBindTexture(GL_TEXTURE_2D, texture->name); - - /* - * In OpenGL ES we can't specify a stride with glTexImage2D (however, - * GL_UNPACK_ALIGNMENT is a limited form of stride). - * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we - * need to do something reasonable (here creating a bigger texture). - * - * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT); - * - * This situation doesn't happen often, but some h/w have a limitation - * for their framebuffer (eg: must be multiple of 8 pixels), and - * we need to take that into account when using these buffers as - * textures. - * - * This should never be a problem with POT textures - */ - - int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format)); - unpack = 1 << ((unpack > 3) ? 3 : unpack); - glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); - - /* - * round to POT if needed - */ - if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { - texture->NPOTAdjust = true; - } - - if (texture->NPOTAdjust) { - // find the smallest power-of-two that will accommodate our surface - texture->potWidth = 1 << (31 - clz(t.width)); - texture->potHeight = 1 << (31 - clz(t.height)); - if (texture->potWidth < t.width) texture->potWidth <<= 1; - if (texture->potHeight < t.height) texture->potHeight <<= 1; - texture->wScale = float(t.width) / texture->potWidth; - texture->hScale = float(t.height) / texture->potHeight; - } else { - texture->potWidth = t.width; - texture->potHeight = t.height; - } - - Rect bounds(dirty.bounds()); - GLvoid* data = 0; - if (texture->width != t.width || texture->height != t.height) { - texture->width = t.width; - texture->height = t.height; - - // texture size changed, we need to create a new one - bounds.set(Rect(t.width, t.height)); - if (t.width == texture->potWidth && - t.height == texture->potHeight) { - // we can do it one pass - data = t.data; - } - - if (t.format == HAL_PIXEL_FORMAT_RGB_565) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGB, texture->potWidth, texture->potHeight, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); - } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture->potWidth, texture->potHeight, 0, - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); - } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 || - t.format == HAL_PIXEL_FORMAT_RGBX_8888) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture->potWidth, texture->potHeight, 0, - GL_RGBA, GL_UNSIGNED_BYTE, data); - } else if (isSupportedYuvFormat(t.format)) { - // just show the Y plane of YUV buffers - glTexImage2D(GL_TEXTURE_2D, 0, - GL_LUMINANCE, texture->potWidth, texture->potHeight, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); - } else { - // oops, we don't handle this format! - LOGE("layer %p, texture=%d, using format %d, which is not " - "supported by the GL", this, texture->name, t.format); - } - } - if (!data) { - if (t.format == HAL_PIXEL_FORMAT_RGB_565) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, - t.data + bounds.top*t.stride*2); - } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, - t.data + bounds.top*t.stride*2); - } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 || - t.format == HAL_PIXEL_FORMAT_RGBX_8888) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGBA, GL_UNSIGNED_BYTE, - t.data + bounds.top*t.stride*4); - } else if (isSupportedYuvFormat(t.format)) { - // just show the Y plane of YUV buffers - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_LUMINANCE, GL_UNSIGNED_BYTE, - t.data + bounds.top*t.stride); - } - } -} - -status_t LayerBase::initializeEglImage( - const sp& buffer, Texture* texture) -{ - status_t err = NO_ERROR; - - // we need to recreate the texture - EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); - - // free the previous image - if (texture->image != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(dpy, texture->image); - texture->image = EGL_NO_IMAGE_KHR; - } - - // construct an EGL_NATIVE_BUFFER_ANDROID - android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); - - // create the new EGLImageKHR - const EGLint attrs[] = { - EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, - EGL_NONE, EGL_NONE - }; - texture->image = eglCreateImageKHR( - dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, - (EGLClientBuffer)clientBuf, attrs); - - if (texture->image != EGL_NO_IMAGE_KHR) { - glBindTexture(GL_TEXTURE_2D, texture->name); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, - (GLeglImageOES)texture->image); - GLint error = glGetError(); - if (UNLIKELY(error != GL_NO_ERROR)) { - LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) " - "failed err=0x%04x", - this, texture->image, error); - err = INVALID_OPERATION; - } else { - // Everything went okay! - texture->NPOTAdjust = false; - texture->dirty = false; - texture->width = clientBuf->width; - texture->height = clientBuf->height; - } - } else { - LOGE("layer=%p, eglCreateImageKHR() failed. err=0x%4x", - this, eglGetError()); - err = INVALID_OPERATION; - } - return err; + const Layer::State& s(drawingState()); + snprintf(buffer, SIZE, + "+ %s %p\n" + " " + "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), " + "needsBlending=%1d, needsDithering=%1d, invalidate=%1d, " + "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", + getTypeId(), this, s.z, tx(), ty(), s.w, s.h, + needsBlending(), needsDithering(), contentDirty, + s.alpha, s.flags, + s.transform[0][0], s.transform[0][1], + s.transform[1][0], s.transform[1][1]); + result.append(buffer); } - // --------------------------------------------------------------------------- -int32_t LayerBaseClient::sIdentity = 0; +int32_t LayerBaseClient::sIdentity = 1; LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, const sp& client, int32_t i) - : LayerBase(flinger, display), lcblk(NULL), client(client), mIndex(i), + : LayerBase(flinger, display), client(client), mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity))) { - lcblk = new SharedBufferServer( - client->ctrlblk, i, NUM_BUFFERS, - mIdentity); } void LayerBaseClient::onFirstRef() @@ -712,16 +520,15 @@ LayerBaseClient::~LayerBaseClient() if (client != 0) { client->free(mIndex); } - delete lcblk; } -int32_t LayerBaseClient::serverIndex() const +ssize_t LayerBaseClient::serverIndex() const { sp client(this->client.promote()); if (client != 0) { return (client->cid<<16)|mIndex; } - return 0xFFFF0000 | mIndex; + return ssize_t(0xFFFF0000 | mIndex); } sp LayerBaseClient::getSurface() @@ -742,12 +549,19 @@ sp LayerBaseClient::createSurface() const const_cast(this)); } -// called with SurfaceFlinger::mStateLock as soon as the layer is entered -// in the purgatory list -void LayerBaseClient::onRemoved() +void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const { - // wake up the condition - lcblk->setStatus(NO_INIT); + LayerBase::dump(result, buffer, SIZE); + + sp client(this->client.promote()); + snprintf(buffer, SIZE, + " name=%s\n" + " id=0x%08x, client=0x%08x, identity=%u\n", + getName().string(), + clientIndex(), client.get() ? client->cid : 0, + getIdentity()); + + result.append(buffer); } // --------------------------------------------------------------------------- @@ -799,11 +613,17 @@ status_t LayerBaseClient::Surface::onTransact( return BnSurface::onTransact(code, data, reply, flags); } -sp LayerBaseClient::Surface::requestBuffer(int index, int usage) +sp LayerBaseClient::Surface::requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { return NULL; } +status_t LayerBaseClient::Surface::setBufferCount(int bufferCount) +{ + return INVALID_OPERATION; +} + status_t LayerBaseClient::Surface::registerBuffers( const ISurface::BufferHeap& buffers) { diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index 62ec8399ad28ddf3f8fa690ece3cac4b08b0a8fe..2e2f2df899b0a931fc317072ac7bec32b0a8911d 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include @@ -46,40 +46,15 @@ class Client; class GraphicBuffer; class GraphicPlane; class SurfaceFlinger; +class Texture; // --------------------------------------------------------------------------- class LayerBase : public RefBase { - // poor man's dynamic_cast below - template - struct getTypeInfoOfAnyType { - static uint32_t get() { return T::typeInfo; } - }; - - template - struct getTypeInfoOfAnyType { - static uint32_t get() { return getTypeInfoOfAnyType::get(); } - }; - public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - template - static T dynamicCast(LayerBase* base) { - uint32_t mostDerivedInfo = base->getTypeInfo(); - uint32_t castToInfo = getTypeInfoOfAnyType::get(); - if ((mostDerivedInfo & castToInfo) == castToInfo) - return static_cast(base); - return 0; - } + LayerBase(SurfaceFlinger* flinger, DisplayID display); - - LayerBase(SurfaceFlinger* flinger, DisplayID display); - DisplayID dpy; mutable bool contentDirty; Region visibleRegionScreen; @@ -125,6 +100,9 @@ public: void invalidate(); + virtual const char* getTypeId() const { return "LayerBase"; } + virtual ssize_t serverIndex() const { return -1; } + /** * draw - performs some global clipping optimizations * and calls onDraw(). @@ -199,9 +177,9 @@ public: virtual bool needsDithering() const { return false; } /** - * transformed -- true is this surface needs a to be transformed + * needsLinearFiltering - true if this surface needs filtering */ - virtual bool transformed() const { return mTransformed; } + virtual bool needsFiltering() const { return mNeedsFiltering; } /** * isSecure - true if this surface is secure, that is if it prevents @@ -217,7 +195,10 @@ public: * current list */ virtual void onRemoved() { }; - + /** always call base class first */ + virtual void dump(String8& result, char* scratch, size_t size) const; + + enum { // flags for doTransaction() eVisibleRegion = 0x00000002, }; @@ -241,44 +222,18 @@ protected: const GraphicPlane& graphicPlane(int dpy) const; GraphicPlane& graphicPlane(int dpy); - GLuint createTexture() const; - - struct Texture { - Texture() : name(-1U), width(0), height(0), - image(EGL_NO_IMAGE_KHR), transform(0), - NPOTAdjust(false), dirty(true) { } - GLuint name; - GLuint width; - GLuint height; - GLuint potWidth; - GLuint potHeight; - GLfloat wScale; - GLfloat hScale; - EGLImageKHR image; - uint32_t transform; - bool NPOTAdjust; - bool dirty; - }; - - void clearWithOpenGL(const Region& clip, GLclampx r, GLclampx g, - GLclampx b, GLclampx alpha) const; + void clearWithOpenGL(const Region& clip, GLclampf r, GLclampf g, + GLclampf b, GLclampf alpha) const; void clearWithOpenGL(const Region& clip) const; void drawWithOpenGL(const Region& clip, const Texture& texture) const; - void loadTexture(Texture* texture, - const Region& dirty, const GGLSurface& t) const; - status_t initializeEglImage( - const sp& buffer, Texture* texture); - - bool isSupportedYuvFormat(int format) const; sp mFlinger; uint32_t mFlags; // cached during validateVisibility() - bool mTransformed; - bool mUseLinearFiltering; + bool mNeedsFiltering; int32_t mOrientation; - GLfixed mVertices[4][2]; + GLfloat mVertices[4][2]; Rect mTransformedBounds; int mLeft; int mTop; @@ -313,14 +268,6 @@ class LayerBaseClient : public LayerBase { public: class Surface; - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - // lcblk is (almost) only accessed from the main SF thread, in the places - // where it's not, a reference to Client must be held - SharedBufferServer* lcblk; LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, const sp& client, int32_t i); @@ -331,14 +278,11 @@ public: inline uint32_t getIdentity() const { return mIdentity; } inline int32_t clientIndex() const { return mIndex; } - int32_t serverIndex() const; - sp getSurface(); virtual sp createSurface() const; - - virtual void onRemoved(); - + virtual ssize_t serverIndex() const; + virtual const char* getTypeId() const { return "LayerBaseClient"; } class Surface : public BnSurface { @@ -356,7 +300,10 @@ public: sp getOwner() const; private: - virtual sp requestBuffer(int index, int usage); + virtual sp requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage); + virtual status_t setBufferCount(int bufferCount); + virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); @@ -373,8 +320,11 @@ public: friend class Surface; +protected: + virtual void dump(String8& result, char* scratch, size_t size) const; + private: - int32_t mIndex; + int32_t mIndex; mutable Mutex mLock; mutable wp mClientSurface; // only read diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp index 5fd7904be6cf0854729180ab9177a5382ca1efee..09c90e8001a67047e2dc590c67b9a9d49290425b 100644 --- a/libs/surfaceflinger/LayerBlur.cpp +++ b/libs/surfaceflinger/LayerBlur.cpp @@ -33,11 +33,6 @@ namespace android { // --------------------------------------------------------------------------- -const uint32_t LayerBlur::typeInfo = LayerBaseClient::typeInfo | 8; -const char* const LayerBlur::typeID = "LayerBlur"; - -// --------------------------------------------------------------------------- - LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display, const sp& client, int32_t i) : LayerBaseClient(flinger, display, client, i), mCacheDirty(true), @@ -100,7 +95,9 @@ void LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirty mCacheDirty = false; } else { if (!mAutoRefreshPending) { - mFlinger->signalDelayedEvent(ms2ns(500)); + mFlinger->postMessageAsync( + new MessageBase(MessageQueue::INVALIDATE), + ms2ns(500)); mAutoRefreshPending = true; } } @@ -206,8 +203,8 @@ void LayerBlur::onDraw(const Region& clip) const const State& s = drawingState(); if (UNLIKELY(s.alpha < 0xFF)) { - const GGLfixed alpha = (s.alpha << 16)/255; - glColor4x(0, 0, 0, alpha); + const GLfloat alpha = s.alpha * (1.0f/255.0f); + glColor4f(0, 0, 0, alpha); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); @@ -225,38 +222,20 @@ void LayerBlur::onDraw(const Region& clip) const glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - if (UNLIKELY(transformed() - || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) { - // This is a very rare scenario. - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glScalef(mWidthScale, mHeightScale, 1); - glTranslatef(-x, mYOffset - y, 0); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(2, GL_FIXED, 0, mVertices); - glTexCoordPointer(2, GL_FIXED, 0, mVertices); - while (it != end) { - const Rect& r = *it++; - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } else { - // NOTE: this is marginally faster with the software gl, because - // glReadPixels() reads the fb bottom-to-top, however we'll - // skip all the jaccobian computations. - Rect r; - GLint crop[4] = { 0, 0, w, h }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - y = fbHeight - (y + h); - while (it != end) { - const Rect& r = *it++; - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawTexiOES(x, y, 0, w, h); - } + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(mWidthScale, mHeightScale, 1); + glTranslatef(-x, mYOffset - y, 0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, mVertices); + glTexCoordPointer(2, GL_FLOAT, 0, mVertices); + while (it != end) { + const Rect& r = *it++; + const GLint sy = fbHeight - (r.top + r.height()); + glScissor(r.left, sy, r.width(), r.height()); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h index 5b63dec2905ce8417c0e41460d6c0459939be8b1..380f587158c0419659098043a9fcbfc833acec6d 100644 --- a/libs/surfaceflinger/LayerBlur.h +++ b/libs/surfaceflinger/LayerBlur.h @@ -31,11 +31,6 @@ namespace android { class LayerBlur : public LayerBaseClient { public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - LayerBlur(SurfaceFlinger* flinger, DisplayID display, const sp& client, int32_t i); virtual ~LayerBlur(); @@ -43,6 +38,7 @@ public: virtual void onDraw(const Region& clip) const; virtual bool needsBlending() const { return true; } virtual bool isSecure() const { return false; } + virtual const char* getTypeId() const { return "LayerBlur"; } virtual uint32_t doTransaction(uint32_t flags); virtual void setVisibleRegion(const Region& visibleRegion); diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index 5c21593db22a6e7bc89ad1ddb98e91fdc6ba933a..8a582daa7c4fd989c9ceabbba8c975c54cc653b9 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -39,8 +39,6 @@ namespace android { // --------------------------------------------------------------------------- -const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20; -const char* const LayerBuffer::typeID = "LayerBuffer"; gralloc_module_t const* LayerBuffer::sGrallocModule = 0; // --------------------------------------------------------------------------- @@ -120,7 +118,7 @@ uint32_t LayerBuffer::doTransaction(uint32_t flags) source->onTransaction(flags); uint32_t res = LayerBase::doTransaction(flags); // we always want filtering for these surfaces - mUseLinearFiltering = !(mFlags & DisplayHardware::SLOW_CONFIG); + mNeedsFiltering = !(mFlags & DisplayHardware::SLOW_CONFIG); return res; } @@ -145,14 +143,6 @@ void LayerBuffer::onDraw(const Region& clip) const } } -bool LayerBuffer::transformed() const -{ - sp source(getSource()); - if (LIKELY(source != 0)) - return source->transformed(); - return false; -} - void LayerBuffer::serverDestroy() { sp source(clearSource()); @@ -321,16 +311,13 @@ void LayerBuffer::Source::postBuffer(ssize_t offset) { } void LayerBuffer::Source::unregisterBuffers() { } -bool LayerBuffer::Source::transformed() const { - return mLayer.mTransformed; -} // --------------------------------------------------------------------------- LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer, const ISurface::BufferHeap& buffers) : Source(layer), mStatus(NO_ERROR), mBufferSize(0), - mUseEGLImageDirectly(true) + mTextureManager(layer.mFlags) { if (buffers.heap == NULL) { // this is allowed, but in this case, it is illegal to receive @@ -444,11 +431,6 @@ void LayerBuffer::BufferSource::setBuffer(const sp& buffer) mBuffer = buffer; } -bool LayerBuffer::BufferSource::transformed() const -{ - return mBufferHeap.transform ? true : Source::transformed(); -} - void LayerBuffer::BufferSource::onDraw(const Region& clip) const { sp ourBuffer(getBuffer()); @@ -462,35 +444,10 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const NativeBuffer src(ourBuffer->getBuffer()); const Rect transformedBounds(mLayer.getTransformedBounds()); - if (UNLIKELY(mTexture.name == -1LU)) { - mTexture.name = mLayer.createTexture(); - } - #if defined(EGL_ANDROID_image_native_buffer) if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) { err = INVALID_OPERATION; if (ourBuffer->supportsCopybit()) { - - // there are constraints on buffers used by the GPU and these may not - // be honored here. We need to change the API so the buffers - // are allocated with gralloc. For now disable this code-path -#if 0 - // First, try to use the buffer as an EGLImage directly - if (mUseEGLImageDirectly) { - // NOTE: Assume the buffer is allocated with the proper USAGE flags - - sp buffer = new GraphicBuffer( - src.img.w, src.img.h, src.img.format, - GraphicBuffer::USAGE_HW_TEXTURE, - src.img.w, src.img.handle, false); - - err = mLayer.initializeEglImage(buffer, &mTexture); - if (err != NO_ERROR) { - mUseEGLImageDirectly = false; - } - } -#endif - copybit_device_t* copybit = mLayer.mBlitEngine; if (copybit && err != NO_ERROR) { // create our EGLImageKHR the first time @@ -527,7 +484,7 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const t.format = src.img.format; t.data = (GGLubyte*)src.img.base; const Region dirty(Rect(t.width, t.height)); - mLayer.loadTexture(&mTexture, dirty, t); + mTextureManager.loadTexture(&mTexture, dirty, t); } mTexture.transform = mBufferHeap.transform; @@ -569,7 +526,7 @@ status_t LayerBuffer::BufferSource::initTempBuffer() const // figure out if we need linear filtering if (buffers.w * h == buffers.h * w) { // same pixel area, don't use filtering - mLayer.mUseLinearFiltering = false; + mLayer.mNeedsFiltering = false; } // Allocate a temporary buffer and create the corresponding EGLImageKHR @@ -593,7 +550,8 @@ status_t LayerBuffer::BufferSource::initTempBuffer() const dst.crop.r = w; dst.crop.b = h; - err = mLayer.initializeEglImage(buffer, &mTexture); + EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay()); + err = mTextureManager.initEglImage(&mTexture, dpy, buffer); } return err; @@ -609,7 +567,6 @@ void LayerBuffer::BufferSource::clearTempBufferImage() const glDeleteTextures(1, &mTexture.name); Texture defaultTexture; mTexture = defaultTexture; - mTexture.name = mLayer.createTexture(); } // --------------------------------------------------------------------------- @@ -665,9 +622,9 @@ LayerBuffer::OverlaySource::~OverlaySource() void LayerBuffer::OverlaySource::onDraw(const Region& clip) const { // this would be where the color-key would be set, should we need it. - GLclampx red = 0; - GLclampx green = 0; - GLclampx blue = 0; + GLclampf red = 0; + GLclampf green = 0; + GLclampf blue = 0; mLayer.clearWithOpenGL(clip, red, green, blue, 0); } diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index b1766238cd95c11aa74f675bc50857bedc837fcc..d38dde2255c8c4c62de2121fd56030512de48626 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -21,6 +21,7 @@ #include #include "LayerBase.h" +#include "TextureManager.h" struct copybit_device_t; @@ -45,31 +46,25 @@ class LayerBuffer : public LayerBaseClient virtual void onVisibilityResolved(const Transform& planeTransform); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); - virtual bool transformed() const; virtual void destroy() { } protected: LayerBuffer& mLayer; }; public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - LayerBuffer(SurfaceFlinger* flinger, DisplayID display, const sp& client, int32_t i); virtual ~LayerBuffer(); virtual void onFirstRef(); virtual bool needsBlending() const; + virtual const char* getTypeId() const { return "LayerBuffer"; } virtual sp createSurface() const; virtual status_t ditch(); virtual void onDraw(const Region& clip) const; virtual uint32_t doTransaction(uint32_t flags); virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); - virtual bool transformed() const; status_t registerBuffers(const ISurface::BufferHeap& buffers); void postBuffer(ssize_t offset); @@ -133,7 +128,6 @@ private: virtual void onDraw(const Region& clip) const; virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); - virtual bool transformed() const; virtual void destroy() { } private: status_t initTempBuffer() const; @@ -143,9 +137,9 @@ private: status_t mStatus; ISurface::BufferHeap mBufferHeap; size_t mBufferSize; - mutable LayerBase::Texture mTexture; + mutable Texture mTexture; mutable NativeBuffer mTempBuffer; - mutable bool mUseEGLImageDirectly; + mutable TextureManager mTextureManager; }; class OverlaySource : public Source { diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp index fd61e30d8f5a207747c62e7437d9f3f691a26cd6..568fedbf031e65af3bddf34c334d3e73a9f637c1 100644 --- a/libs/surfaceflinger/LayerDim.cpp +++ b/libs/surfaceflinger/LayerDim.cpp @@ -30,9 +30,6 @@ namespace android { // --------------------------------------------------------------------------- -const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10; -const char* const LayerDim::typeID = "LayerDim"; - bool LayerDim::sUseTexture; GLuint LayerDim::sTexId; EGLImageKHR LayerDim::sImage; diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h index d4672a1c44c5cb099883a18b81a1ec70d7c8398d..19a9990a09573bfd90b42666adbd0a1416c26abc 100644 --- a/libs/surfaceflinger/LayerDim.h +++ b/libs/surfaceflinger/LayerDim.h @@ -37,11 +37,6 @@ class LayerDim : public LayerBaseClient static int32_t sWidth; static int32_t sHeight; public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - LayerDim(SurfaceFlinger* flinger, DisplayID display, const sp& client, int32_t i); virtual ~LayerDim(); @@ -49,6 +44,7 @@ public: virtual void onDraw(const Region& clip) const; virtual bool needsBlending() const { return true; } virtual bool isSecure() const { return false; } + virtual const char* getTypeId() const { return "LayerDim"; } static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h); }; diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp index b43d80173a3fe7c47581c92b7018dc415a5b1886..d668e88d471fd72d9f4ab550d07725aa7f30c49c 100644 --- a/libs/surfaceflinger/MessageQueue.cpp +++ b/libs/surfaceflinger/MessageQueue.cpp @@ -60,9 +60,9 @@ MessageQueue::~MessageQueue() { } -MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout) +sp MessageQueue::waitMessage(nsecs_t timeout) { - MessageList::value_type result; + sp result; bool again; do { @@ -132,6 +132,7 @@ MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout) if (again) { // the message has been processed. release our reference to it // without holding the lock. + result->notify(); result = 0; } @@ -141,7 +142,7 @@ MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout) } status_t MessageQueue::postMessage( - const MessageList::value_type& message, nsecs_t relTime, uint32_t flags) + const sp& message, nsecs_t relTime, uint32_t flags) { return queueMessage(message, relTime, flags); } @@ -154,7 +155,7 @@ status_t MessageQueue::invalidate() { } status_t MessageQueue::queueMessage( - const MessageList::value_type& message, nsecs_t relTime, uint32_t flags) + const sp& message, nsecs_t relTime, uint32_t flags) { Mutex::Autolock _l(mLock); message->when = systemTime() + relTime; @@ -167,13 +168,13 @@ status_t MessageQueue::queueMessage( return NO_ERROR; } -void MessageQueue::dump(const MessageList::value_type& message) +void MessageQueue::dump(const sp& message) { Mutex::Autolock _l(mLock); dumpLocked(message); } -void MessageQueue::dumpLocked(const MessageList::value_type& message) +void MessageQueue::dumpLocked(const sp& message) { LIST::const_iterator cur(mMessages.begin()); LIST::const_iterator end(mMessages.end()); diff --git a/libs/surfaceflinger/MessageQueue.h b/libs/surfaceflinger/MessageQueue.h index dc8138d1667d417ae49f605d4f6c8f43c74ca4dc..890f809a3b574ed60849f480a496d6b2cc57f3d7 100644 --- a/libs/surfaceflinger/MessageQueue.h +++ b/libs/surfaceflinger/MessageQueue.h @@ -25,6 +25,7 @@ #include #include +#include "Barrier.h" namespace android { @@ -37,7 +38,6 @@ class MessageList List< sp > mList; typedef List< sp > LIST; public: - typedef sp value_type; inline LIST::iterator begin() { return mList.begin(); } inline LIST::const_iterator begin() const { return mList.begin(); } inline LIST::iterator end() { return mList.end(); } @@ -63,11 +63,19 @@ public: // return true if message has a handler virtual bool handler() { return false; } + + // waits for the handler to be processed + void wait() const { barrier.wait(); } + // releases all waiters. this is done automatically if + // handler returns true + void notify() const { barrier.open(); } + protected: virtual ~MessageBase() { } private: + mutable Barrier barrier; friend class LightRefBase; }; @@ -82,42 +90,33 @@ class MessageQueue typedef List< sp > LIST; public: - // this is a work-around the multichar constant warning. A macro would - // work too, but would pollute the namespace. - template - struct WHAT { - static const uint32_t Value = - (uint32_t(a&0xff)<<24)|(uint32_t(b&0xff)<<16)| - (uint32_t(c&0xff)<<8)|uint32_t(d&0xff); - }; - MessageQueue(); ~MessageQueue(); // pre-defined messages enum { - INVALIDATE = WHAT<'_','p','d','t'>::Value + INVALIDATE = '_upd' }; - MessageList::value_type waitMessage(nsecs_t timeout = -1); + sp waitMessage(nsecs_t timeout = -1); - status_t postMessage(const MessageList::value_type& message, + status_t postMessage(const sp& message, nsecs_t reltime=0, uint32_t flags = 0); - + status_t invalidate(); - void dump(const MessageList::value_type& message); + void dump(const sp& message); private: - status_t queueMessage(const MessageList::value_type& message, + status_t queueMessage(const sp& message, nsecs_t reltime, uint32_t flags); - void dumpLocked(const MessageList::value_type& message); + void dumpLocked(const sp& message); Mutex mLock; Condition mCondition; MessageList mMessages; bool mInvalidate; - MessageList::value_type mInvalidateMessage; + sp mInvalidateMessage; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 0722fda55eaf6aecc01b83fe9ab372e3b46d3058..fff08539275b98d6d82f0b02fef93a1d61c17d84 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -206,8 +206,8 @@ void SurfaceFlinger::init() property_get("debug.sf.showbackground", value, "0"); mDebugBackground = atoi(value); - LOGI_IF(mDebugRegion, "showupdates enabled"); - LOGI_IF(mDebugBackground, "showbackground enabled"); + LOGI_IF(mDebugRegion, "showupdates enabled"); + LOGI_IF(mDebugBackground, "showbackground enabled"); } SurfaceFlinger::~SurfaceFlinger() @@ -225,7 +225,7 @@ sp SurfaceFlinger::getCblk() const return mServerHeap; } -sp SurfaceFlinger::createConnection() +sp SurfaceFlinger::createConnection() { Mutex::Autolock _l(mStateLock); uint32_t token = mTokens.acquire(); @@ -357,7 +357,6 @@ status_t SurfaceFlinger::readyToRun() dcblk->ydpi = hw.getDpiY(); dcblk->fps = hw.getRefreshRate(); dcblk->density = hw.getDensity(); - asm volatile ("":::"memory"); // Initialize OpenGL|ES glActiveTexture(GL_TEXTURE0); @@ -427,7 +426,7 @@ void SurfaceFlinger::waitForEvent() timeout = waitTime>0 ? waitTime : 0; } - MessageList::value_type msg = mEventQueue.waitMessage(timeout); + sp msg = mEventQueue.waitMessage(timeout); // see if we timed out if (isFrozen()) { @@ -462,9 +461,20 @@ void SurfaceFlinger::signal() const { const_cast(this)->signalEvent(); } -void SurfaceFlinger::signalDelayedEvent(nsecs_t delay) +status_t SurfaceFlinger::postMessageAsync(const sp& msg, + nsecs_t reltime, uint32_t flags) { - mEventQueue.postMessage( new MessageBase(MessageQueue::INVALIDATE), delay); + return mEventQueue.postMessage(msg, reltime, flags); +} + +status_t SurfaceFlinger::postMessageSync(const sp& msg, + nsecs_t reltime, uint32_t flags) +{ + status_t res = mEventQueue.postMessage(msg, reltime, flags); + if (res == NO_ERROR) { + msg->wait(); + } + return res; } // ---------------------------------------------------------------------------- @@ -1079,15 +1089,15 @@ status_t SurfaceFlinger::invalidateLayerVisibility(const sp& layer) status_t SurfaceFlinger::addLayer_l(const sp& layer) { - if (layer == 0) - return BAD_VALUE; ssize_t i = mCurrentState.layersSortedByZ.add( layer, &LayerBase::compareCurrentStateZ); - sp lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get()); - if (lbc != 0) { - mLayerMap.add(lbc->serverIndex(), lbc); - } - return NO_ERROR; + return (i < 0) ? status_t(i) : status_t(NO_ERROR); +} + +status_t SurfaceFlinger::addClientLayer_l(const sp& lbc) +{ + ssize_t serverIndex = lbc->serverIndex(); + return mLayerMap.add(serverIndex, lbc); } status_t SurfaceFlinger::removeLayer_l(const sp& layerBase) @@ -1095,10 +1105,9 @@ status_t SurfaceFlinger::removeLayer_l(const sp& layerBase) ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase); if (index >= 0) { mLayersRemoved = true; - sp layer = - LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get()); - if (layer != 0) { - mLayerMap.removeItem(layer->serverIndex()); + ssize_t serverIndex = layerBase->serverIndex(); + if (serverIndex >= 0) { + mLayerMap.removeItem(serverIndex); } return NO_ERROR; } @@ -1137,15 +1146,11 @@ uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) return android_atomic_and(~flags, &mTransactionFlags) & flags; } -uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay) +uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) { uint32_t old = android_atomic_or(flags, &mTransactionFlags); if ((old & flags)==0) { // wake the server up - if (delay > 0) { - signalDelayedEvent(delay); - } else { - signalEvent(); - } + signalEvent(); } return old; } @@ -1225,7 +1230,7 @@ int SurfaceFlinger::setOrientation(DisplayID dpy, } sp SurfaceFlinger::createSurface(ClientID clientId, int pid, - const String8& name, ISurfaceFlingerClient::surface_data_t* params, + const String8& name, ISurfaceComposerClient::surface_data_t* params, DisplayID d, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { @@ -1247,7 +1252,7 @@ sp SurfaceFlinger::createSurface(ClientID clientId, int pid, //LOGD("createSurface for pid %d (%d x %d)", pid, w, h); int32_t id = client->generateId(pid); - if (uint32_t(id) >= NUM_LAYERS_MAX) { + if (uint32_t(id) >= SharedBufferStack::NUM_LAYERS_MAX) { LOGE("createSurface() failed, generateId = %d", id); return surfaceHandle; } @@ -1298,7 +1303,7 @@ sp SurfaceFlinger::createNormalSurfaceLocked( format = PIXEL_FORMAT_RGBA_8888; break; case PIXEL_FORMAT_OPAQUE: - format = PIXEL_FORMAT_RGB_565; + format = PIXEL_FORMAT_RGBX_8888; break; } @@ -1307,6 +1312,7 @@ sp SurfaceFlinger::createNormalSurfaceLocked( if (LIKELY(err == NO_ERROR)) { layer->initStates(w, h, flags); addLayer_l(layer); + addClientLayer_l(layer); } else { LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err)); layer.clear(); @@ -1321,6 +1327,7 @@ sp SurfaceFlinger::createBlurSurfaceLocked( sp layer = new LayerBlur(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); + addClientLayer_l(layer); return layer; } @@ -1331,6 +1338,7 @@ sp SurfaceFlinger::createDimSurfaceLocked( sp layer = new LayerDim(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); + addClientLayer_l(layer); return layer; } @@ -1341,6 +1349,7 @@ sp SurfaceFlinger::createPushBuffersSurfaceLocked( sp layer = new LayerBuffer(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); + addClientLayer_l(layer); return layer; } @@ -1397,7 +1406,7 @@ status_t SurfaceFlinger::destroySurface(const sp& layer) } }; - mEventQueue.postMessage( new MessageDestroySurface(this, layer) ); + postMessageAsync( new MessageDestroySurface(this, layer) ); return NO_ERROR; } @@ -1512,83 +1521,17 @@ status_t SurfaceFlinger::dump(int fd, const Vector& args) result.append(buffer); } - size_t s = mClientsMap.size(); - char name[64]; - for (size_t i=0 ; i client = mClientsMap.valueAt(i); - sprintf(name, " Client (id=0x%08x)", client->cid); - client->dump(name); - } const LayerVector& currentLayers = mCurrentState.layersSortedByZ; const size_t count = currentLayers.size(); for (size_t i=0 ; i& layer = currentLayers[i]; - const Layer::State& s = layer->drawingState(); - snprintf(buffer, SIZE, - "+ %s %p\n" - " " - "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), " - "needsBlending=%1d, needsDithering=%1d, invalidate=%1d, " - "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", - layer->getTypeID(), layer.get(), - s.z, layer->tx(), layer->ty(), s.w, s.h, - layer->needsBlending(), layer->needsDithering(), - layer->contentDirty, - s.alpha, s.flags, - s.transform[0][0], s.transform[0][1], - s.transform[1][0], s.transform[1][1]); - result.append(buffer); - buffer[0] = 0; - /*** LayerBaseClient ***/ - sp lbc = - LayerBase::dynamicCast< LayerBaseClient* >(layer.get()); - if (lbc != 0) { - sp client(lbc->client.promote()); - snprintf(buffer, SIZE, - " name=%s\n", lbc->getName().string()); - result.append(buffer); - snprintf(buffer, SIZE, - " id=0x%08x, client=0x%08x, identity=%u\n", - lbc->clientIndex(), client.get() ? client->cid : 0, - lbc->getIdentity()); - - result.append(buffer); - buffer[0] = 0; - } - /*** Layer ***/ - sp l = LayerBase::dynamicCast< Layer* >(layer.get()); - if (l != 0) { - SharedBufferStack::Statistics stats = l->lcblk->getStats(); - result.append( l->lcblk->dump(" ") ); - sp buf0(l->getBuffer(0)); - sp buf1(l->getBuffer(1)); - uint32_t w0=0, h0=0, s0=0; - uint32_t w1=0, h1=0, s1=0; - if (buf0 != 0) { - w0 = buf0->getWidth(); - h0 = buf0->getHeight(); - s0 = buf0->getStride(); - } - if (buf1 != 0) { - w1 = buf1->getWidth(); - h1 = buf1->getHeight(); - s1 = buf1->getStride(); - } - snprintf(buffer, SIZE, - " " - "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u]," - " freezeLock=%p, dq-q-time=%u us\n", - l->pixelFormat(), - w0, h0, s0, w1, h1, s1, - l->getFreezeLock().get(), stats.totalTime); - result.append(buffer); - buffer[0] = 0; - } + const sp& layer(currentLayers[i]); + layer->dump(result, buffer, SIZE); + const Layer::State& s(layer->drawingState()); s.transparentRegion.dump(result, "transparentRegion"); layer->transparentRegionScreen.dump(result, "transparentRegionScreen"); layer->visibleRegionScreen.dump(result, "visibleRegionScreen"); } + mWormholeRegion.dump(result, "WormholeRegion"); const DisplayHardware& hw(graphicPlane(0).displayHardware()); snprintf(buffer, SIZE, @@ -1601,16 +1544,19 @@ status_t SurfaceFlinger::dump(int fd, const Vector& args) " last transaction time : %f us\n", mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0); result.append(buffer); + if (inSwapBuffersDuration || !locked) { snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n", inSwapBuffersDuration/1000.0); result.append(buffer); } + if (inTransactionDuration || !locked) { snprintf(buffer, SIZE, " transaction time: %f us\n", inTransactionDuration/1000.0); result.append(buffer); } + snprintf(buffer, SIZE, " client count: %d\n", mClientsMap.size()); result.append(buffer); const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get()); @@ -1733,7 +1679,7 @@ Client::~Client() { int32_t Client::generateId(int pid) { const uint32_t i = clz( ~mBitmap ); - if (i >= NUM_LAYERS_MAX) { + if (i >= SharedBufferStack::NUM_LAYERS_MAX) { return NO_MEMORY; } mPid = pid; @@ -1760,7 +1706,8 @@ void Client::free(int32_t id) } bool Client::isValid(int32_t i) const { - return (uint32_t(i) Client::getLayerUser(int32_t i) const { @@ -1773,10 +1720,6 @@ sp Client::getLayerUser(int32_t i) const { return lbc; } -void Client::dump(const char* what) -{ -} - // --------------------------------------------------------------------------- #if 0 #pragma mark - @@ -1797,7 +1740,7 @@ sp BClient::getControlBlock() const { } sp BClient::createSurface( - ISurfaceFlingerClient::surface_data_t* params, int pid, + ISurfaceComposerClient::surface_data_t* params, int pid, const String8& name, DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index d75dc15f183e71a12c7e3190c88a6f53cd2b7dab..d8fe98cf1311504550b02340a59a9d56d621fc85 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -32,7 +32,7 @@ #include #include -#include +#include #include "Barrier.h" #include "Layer.h" @@ -73,7 +73,6 @@ public: inline bool isValid(int32_t i) const; sp getLayerUser(int32_t i) const; - void dump(const char* what); const Vector< wp >& getLayers() const { return mLayers; @@ -159,7 +158,7 @@ public: virtual status_t dump(int fd, const Vector& args); // ISurfaceComposer interface - virtual sp createConnection(); + virtual sp createConnection(); virtual sp getCblk() const; virtual void bootFinished(); virtual void openGlobalTransaction(); @@ -190,7 +189,7 @@ private: friend class LayerDim; sp createSurface(ClientID client, int pid, const String8& name, - ISurfaceFlingerClient::surface_data_t* params, + ISurfaceComposerClient::surface_data_t* params, DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); @@ -256,8 +255,6 @@ private: public: // hack to work around gcc 4.0.3 bug void signalEvent(); private: - void signalDelayedEvent(nsecs_t delay); - void handleConsoleEvents(); void handleTransaction(uint32_t transactionFlags); void handleTransactionLocked( @@ -281,12 +278,13 @@ private: void destroyConnection(ClientID cid); sp getLayerUser_l(SurfaceID index) const; status_t addLayer_l(const sp& layer); + status_t addClientLayer_l(const sp& lbc); status_t removeLayer_l(const sp& layer); status_t purgatorizeLayer_l(const sp& layer); void free_resources_l(); uint32_t getTransactionFlags(uint32_t flags); - uint32_t setTransactionFlags(uint32_t flags, nsecs_t delay = 0); + uint32_t setTransactionFlags(uint32_t flags); void commitTransaction(); @@ -310,7 +308,12 @@ private: mutable MessageQueue mEventQueue; - + + status_t postMessageAsync(const sp& msg, + nsecs_t reltime=0, uint32_t flags = 0); + + status_t postMessageSync(const sp& msg, + nsecs_t reltime=0, uint32_t flags = 0); // access must be protected by mStateLock @@ -390,14 +393,14 @@ public: // --------------------------------------------------------------------------- -class BClient : public BnSurfaceFlingerClient +class BClient : public BnSurfaceComposerClient { public: BClient(SurfaceFlinger *flinger, ClientID cid, const sp& cblk); ~BClient(); - // ISurfaceFlingerClient interface + // ISurfaceComposerClient interface virtual sp getControlBlock() const; virtual sp createSurface( diff --git a/libs/surfaceflinger/TextureManager.cpp b/libs/surfaceflinger/TextureManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee2159b3ffed7057cc3f90965c56f4c8a136be63 --- /dev/null +++ b/libs/surfaceflinger/TextureManager.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2010 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 +#include + +#include +#include + +#include + +#include +#include + +#include + +#include "clz.h" +#include "DisplayHardware/DisplayHardware.h" +#include "TextureManager.h" + +namespace android { + +// --------------------------------------------------------------------------- + +TextureManager::TextureManager(uint32_t flags) + : mFlags(flags) +{ +} + +GLuint TextureManager::createTexture() +{ + GLuint textureName = -1; + glGenTextures(1, &textureName); + glBindTexture(GL_TEXTURE_2D, textureName); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + return textureName; +} + +bool TextureManager::isSupportedYuvFormat(int format) +{ + switch (format) { + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_422_P: + case HAL_PIXEL_FORMAT_YCbCr_420_P: + case HAL_PIXEL_FORMAT_YCbCr_422_I: + case HAL_PIXEL_FORMAT_YCbCr_420_I: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + return true; + } + return false; +} + +status_t TextureManager::initEglImage(Image* texture, + EGLDisplay dpy, const sp& buffer) +{ + status_t err = NO_ERROR; + if (!texture->dirty) return err; + + // free the previous image + if (texture->image != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(dpy, texture->image); + texture->image = EGL_NO_IMAGE_KHR; + } + + // construct an EGL_NATIVE_BUFFER_ANDROID + android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); + + // create the new EGLImageKHR + const EGLint attrs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE, EGL_NONE + }; + texture->image = eglCreateImageKHR( + dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, + (EGLClientBuffer)clientBuf, attrs); + + if (texture->image != EGL_NO_IMAGE_KHR) { + if (texture->name == -1UL) { + texture->name = createTexture(); + texture->width = 0; + texture->height = 0; + } + glBindTexture(GL_TEXTURE_2D, texture->name); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, + (GLeglImageOES)texture->image); + GLint error = glGetError(); + if (error != GL_NO_ERROR) { + LOGE("glEGLImageTargetTexture2DOES(%p) failed err=0x%04x", + texture->image, error); + err = INVALID_OPERATION; + } else { + // Everything went okay! + texture->dirty = false; + texture->width = clientBuf->width; + texture->height = clientBuf->height; + } + } else { + LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError()); + err = INVALID_OPERATION; + } + return err; +} + +status_t TextureManager::loadTexture(Texture* texture, + const Region& dirty, const GGLSurface& t) +{ + if (texture->name == -1UL) { + texture->name = createTexture(); + texture->width = 0; + texture->height = 0; + } + + glBindTexture(GL_TEXTURE_2D, texture->name); + + /* + * In OpenGL ES we can't specify a stride with glTexImage2D (however, + * GL_UNPACK_ALIGNMENT is a limited form of stride). + * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we + * need to do something reasonable (here creating a bigger texture). + * + * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT); + * + * This situation doesn't happen often, but some h/w have a limitation + * for their framebuffer (eg: must be multiple of 8 pixels), and + * we need to take that into account when using these buffers as + * textures. + * + * This should never be a problem with POT textures + */ + + int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format)); + unpack = 1 << ((unpack > 3) ? 3 : unpack); + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); + + /* + * round to POT if needed + */ + if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { + texture->NPOTAdjust = true; + } + + if (texture->NPOTAdjust) { + // find the smallest power-of-two that will accommodate our surface + texture->potWidth = 1 << (31 - clz(t.width)); + texture->potHeight = 1 << (31 - clz(t.height)); + if (texture->potWidth < t.width) texture->potWidth <<= 1; + if (texture->potHeight < t.height) texture->potHeight <<= 1; + texture->wScale = float(t.width) / texture->potWidth; + texture->hScale = float(t.height) / texture->potHeight; + } else { + texture->potWidth = t.width; + texture->potHeight = t.height; + } + + Rect bounds(dirty.bounds()); + GLvoid* data = 0; + if (texture->width != t.width || texture->height != t.height) { + texture->width = t.width; + texture->height = t.height; + + // texture size changed, we need to create a new one + bounds.set(Rect(t.width, t.height)); + if (t.width == texture->potWidth && + t.height == texture->potHeight) { + // we can do it one pass + data = t.data; + } + + if (t.format == HAL_PIXEL_FORMAT_RGB_565) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGB, texture->potWidth, texture->potHeight, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); + } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGBA, texture->potWidth, texture->potHeight, 0, + GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); + } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 || + t.format == HAL_PIXEL_FORMAT_RGBX_8888) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGBA, texture->potWidth, texture->potHeight, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); + } else if (isSupportedYuvFormat(t.format)) { + // just show the Y plane of YUV buffers + glTexImage2D(GL_TEXTURE_2D, 0, + GL_LUMINANCE, texture->potWidth, texture->potHeight, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + } else { + // oops, we don't handle this format! + LOGE("texture=%d, using format %d, which is not " + "supported by the GL", texture->name, t.format); + } + } + if (!data) { + if (t.format == HAL_PIXEL_FORMAT_RGB_565) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + t.data + bounds.top*t.stride*2); + } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, + t.data + bounds.top*t.stride*2); + } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 || + t.format == HAL_PIXEL_FORMAT_RGBX_8888) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGBA, GL_UNSIGNED_BYTE, + t.data + bounds.top*t.stride*4); + } else if (isSupportedYuvFormat(t.format)) { + // just show the Y plane of YUV buffers + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_LUMINANCE, GL_UNSIGNED_BYTE, + t.data + bounds.top*t.stride); + } + } + return NO_ERROR; +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/TextureManager.h b/libs/surfaceflinger/TextureManager.h new file mode 100644 index 0000000000000000000000000000000000000000..d0acfe90ac669cf3589c42841625279c15372759 --- /dev/null +++ b/libs/surfaceflinger/TextureManager.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2010 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 ANDROID_TEXTURE_MANAGER_H +#define ANDROID_TEXTURE_MANAGER_H + +#include +#include + +#include +#include +#include + +#include + +#include + +namespace android { + +// --------------------------------------------------------------------------- + +class GraphicBuffer; + +// --------------------------------------------------------------------------- + +struct Image { + Image() : name(-1U), image(EGL_NO_IMAGE_KHR), width(0), height(0), + transform(0), dirty(true) { } + GLuint name; + EGLImageKHR image; + GLuint width; + GLuint height; + uint32_t transform; + bool dirty; +}; + +struct Texture : public Image { + Texture() : Image(), NPOTAdjust(false) { } + GLuint potWidth; + GLuint potHeight; + GLfloat wScale; + GLfloat hScale; + bool NPOTAdjust; +}; + +// --------------------------------------------------------------------------- + +class TextureManager { + uint32_t mFlags; + GLuint createTexture(); + static bool isSupportedYuvFormat(int format); +public: + + TextureManager(uint32_t flags); + + // load bitmap data into the active buffer + status_t loadTexture(Texture* texture, + const Region& dirty, const GGLSurface& t); + + // make active buffer an EGLImage if needed + status_t initEglImage(Image* texture, + EGLDisplay dpy, const sp& buffer); +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_TEXTURE_MANAGER_H diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp index 175f989ef0cd1b1feb541aa5627faeb037064d31..5e27cc9bd9bf9eed76675d7598d4fee95b9a0c6b 100644 --- a/libs/surfaceflinger/Transform.cpp +++ b/libs/surfaceflinger/Transform.cpp @@ -229,14 +229,13 @@ Transform::vec3 Transform::transform(const vec3& v) const { return r; } -void Transform::transform(fixed1616* point, int x, int y) const +void Transform::transform(float* point, int x, int y) const { - const float toFixed = 65536.0f; const mat33& M(mMatrix); vec2 v(x, y); v = transform(v); - point[0] = v[0] * toFixed; - point[1] = v[1] * toFixed; + point[0] = v[0]; + point[1] = v[1]; } Rect Transform::makeBounds(int w, int h) const diff --git a/libs/surfaceflinger/Transform.h b/libs/surfaceflinger/Transform.h index 2e5b893eced246b27400a7441b98a125749a0177..20fa11a46ace8c5023b949086b4a9918cb2aa950 100644 --- a/libs/surfaceflinger/Transform.h +++ b/libs/surfaceflinger/Transform.h @@ -37,8 +37,6 @@ public: explicit Transform(uint32_t orientation); ~Transform(); - typedef int32_t fixed1616; - // FIXME: must match OVERLAY_TRANSFORM_*, pull from hardware.h enum orientation_flags { ROT_0 = 0x00000000, @@ -76,7 +74,7 @@ public: // transform data Rect makeBounds(int w, int h) const; - void transform(fixed1616* point, int x, int y) const; + void transform(float* point, int x, int y) const; Region transform(const Region& reg) const; Transform operator * (const Transform& rhs) const; diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk index fe85b34986a18bdc10f7cd76ef787db352af342a..ce3c71a7d9bb9ffd128a9606068047b5dd37b05e 100644 --- a/libs/surfaceflinger_client/Android.mk +++ b/libs/surfaceflinger_client/Android.mk @@ -4,7 +4,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ ISurfaceComposer.cpp \ ISurface.cpp \ - ISurfaceFlingerClient.cpp \ + ISurfaceComposerClient.cpp \ LayerState.cpp \ SharedBufferStack.cpp \ Surface.cpp \ diff --git a/libs/surfaceflinger_client/ISurface.cpp b/libs/surfaceflinger_client/ISurface.cpp index bb8619987649582b6aee4bbbc18fc63461c37116..7049d9e42d1638375118b33a051f79b3bcd55214 100644 --- a/libs/surfaceflinger_client/ISurface.cpp +++ b/libs/surfaceflinger_client/ISurface.cpp @@ -71,11 +71,15 @@ public: { } - virtual sp requestBuffer(int bufferIdx, int usage) + virtual sp requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { Parcel data, reply; data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); data.writeInt32(bufferIdx); + data.writeInt32(w); + data.writeInt32(h); + data.writeInt32(format); data.writeInt32(usage); remote()->transact(REQUEST_BUFFER, data, &reply); sp buffer = new GraphicBuffer(); @@ -83,6 +87,16 @@ public: return buffer; } + virtual status_t setBufferCount(int bufferCount) + { + Parcel data, reply; + data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); + data.writeInt32(bufferCount); + remote()->transact(SET_BUFFER_COUNT, data, &reply); + status_t err = reply.readInt32(); + return err; + } + virtual status_t registerBuffers(const BufferHeap& buffers) { Parcel data, reply; @@ -140,12 +154,22 @@ status_t BnSurface::onTransact( case REQUEST_BUFFER: { CHECK_INTERFACE(ISurface, data, reply); int bufferIdx = data.readInt32(); - int usage = data.readInt32(); - sp buffer(requestBuffer(bufferIdx, usage)); + uint32_t w = data.readInt32(); + uint32_t h = data.readInt32(); + uint32_t format = data.readInt32(); + uint32_t usage = data.readInt32(); + sp buffer(requestBuffer(bufferIdx, w, h, format, usage)); if (buffer == NULL) return BAD_VALUE; return reply->write(*buffer); } + case SET_BUFFER_COUNT: { + CHECK_INTERFACE(ISurface, data, reply); + int bufferCount = data.readInt32(); + status_t err = setBufferCount(bufferCount); + reply->writeInt32(err); + return NO_ERROR; + } case REGISTER_BUFFERS: { CHECK_INTERFACE(ISurface, data, reply); BufferHeap buffer; diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp index b6f4e24a2ab01e7a96ac8f666958b3be807c473d..50495c16b065b17e7129cc116de5830236d1d2e1 100644 --- a/libs/surfaceflinger_client/ISurfaceComposer.cpp +++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp @@ -46,13 +46,13 @@ public: { } - virtual sp createConnection() + virtual sp createConnection() { uint32_t n; Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply); - return interface_cast(reply.readStrongBinder()); + return interface_cast(reply.readStrongBinder()); } virtual sp getCblk() const diff --git a/libs/surfaceflinger_client/ISurfaceFlingerClient.cpp b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp similarity index 83% rename from libs/surfaceflinger_client/ISurfaceFlingerClient.cpp rename to libs/surfaceflinger_client/ISurfaceComposerClient.cpp index def96d70ff09f1f6f8b64470afd156b7ff262353..67c7df815b2d94afb449d0ca487abe9c88778a7b 100644 --- a/libs/surfaceflinger_client/ISurfaceFlingerClient.cpp +++ b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include #include // --------------------------------------------------------------------------- @@ -56,18 +56,18 @@ enum { SET_STATE }; -class BpSurfaceFlingerClient : public BpInterface +class BpSurfaceComposerClient : public BpInterface { public: - BpSurfaceFlingerClient(const sp& impl) - : BpInterface(impl) + BpSurfaceComposerClient(const sp& impl) + : BpInterface(impl) { } virtual sp getControlBlock() const { Parcel data, reply; - data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor()); + data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor()); remote()->transact(GET_CBLK, data, &reply); return interface_cast(reply.readStrongBinder()); } @@ -82,7 +82,7 @@ public: uint32_t flags) { Parcel data, reply; - data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor()); + data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor()); data.writeInt32(pid); data.writeString8(name); data.writeInt32(display); @@ -94,11 +94,11 @@ public: params->readFromParcel(reply); return interface_cast(reply.readStrongBinder()); } - + virtual status_t destroySurface(SurfaceID sid) { Parcel data, reply; - data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor()); + data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor()); data.writeInt32(sid); remote()->transact(DESTROY_SURFACE, data, &reply); return reply.readInt32(); @@ -107,7 +107,7 @@ public: virtual status_t setState(int32_t count, const layer_state_t* states) { Parcel data, reply; - data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor()); + data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor()); data.writeInt32(count); for (int i=0 ; i ctl(getControlBlock()); reply->writeStrongBinder(ctl->asBinder()); return NO_ERROR; @@ -135,7 +135,7 @@ status_t BnSurfaceFlingerClient::onTransact( } // these must be checked - + IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); const int uid = ipc->getCallingUid(); @@ -150,10 +150,10 @@ status_t BnSurfaceFlingerClient::onTransact( return PERMISSION_DENIED; } } - + switch(code) { case CREATE_SURFACE: { - CHECK_INTERFACE(ISurfaceFlingerClient, data, reply); + CHECK_INTERFACE(ISurfaceComposerClient, data, reply); surface_data_t params; int32_t pid = data.readInt32(); String8 name = data.readString8(); @@ -169,12 +169,12 @@ status_t BnSurfaceFlingerClient::onTransact( return NO_ERROR; } break; case DESTROY_SURFACE: { - CHECK_INTERFACE(ISurfaceFlingerClient, data, reply); + CHECK_INTERFACE(ISurfaceComposerClient, data, reply); reply->writeInt32( destroySurface( data.readInt32() ) ); return NO_ERROR; } break; case SET_STATE: { - CHECK_INTERFACE(ISurfaceFlingerClient, data, reply); + CHECK_INTERFACE(ISurfaceComposerClient, data, reply); int32_t count = data.readInt32(); layer_state_t* states = new layer_state_t[count]; for (int i=0 ; iwriteInt32(token); parcel->writeInt32(identity); diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp index a17e8acc577cf45a7aa231285a5ac97a07390e9f..8d031453b03ccc2f1f76bea794f3e08b9cae6867 100644 --- a/libs/surfaceflinger_client/SharedBufferStack.cpp +++ b/libs/surfaceflinger_client/SharedBufferStack.cpp @@ -44,15 +44,11 @@ SharedClient::~SharedClient() { // these functions are used by the clients status_t SharedClient::validate(size_t i) const { - if (uint32_t(i) >= uint32_t(NUM_LAYERS_MAX)) + if (uint32_t(i) >= uint32_t(SharedBufferStack::NUM_LAYERS_MAX)) return BAD_INDEX; return surfaces[i].status; } -uint32_t SharedClient::getIdentity(size_t token) const { - return uint32_t(surfaces[token].identity); -} - // ---------------------------------------------------------------------------- @@ -67,19 +63,47 @@ void SharedBufferStack::init(int32_t i) identity = i; } +status_t SharedBufferStack::setCrop(int buffer, const Rect& crop) +{ + if (uint32_t(buffer) >= NUM_BUFFER_MAX) + return BAD_INDEX; + + buffers[buffer].crop.l = uint16_t(crop.left); + buffers[buffer].crop.t = uint16_t(crop.top); + buffers[buffer].crop.r = uint16_t(crop.right); + buffers[buffer].crop.b = uint16_t(crop.bottom); + return NO_ERROR; +} + status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty) { if (uint32_t(buffer) >= NUM_BUFFER_MAX) return BAD_INDEX; - // in the current implementation we only send a single rectangle - const Rect bounds(dirty.getBounds()); - FlatRegion& reg(dirtyRegion[buffer]); - reg.count = 1; - reg.rects[0] = uint16_t(bounds.left); - reg.rects[1] = uint16_t(bounds.top); - reg.rects[2] = uint16_t(bounds.right); - reg.rects[3] = uint16_t(bounds.bottom); + FlatRegion& reg(buffers[buffer].dirtyRegion); + if (dirty.isEmpty()) { + reg.count = 0; + return NO_ERROR; + } + + size_t count; + Rect const* r = dirty.getArray(&count); + if (count > FlatRegion::NUM_RECT_MAX) { + const Rect bounds(dirty.getBounds()); + reg.count = 1; + reg.rects[0].l = uint16_t(bounds.left); + reg.rects[0].t = uint16_t(bounds.top); + reg.rects[0].r = uint16_t(bounds.right); + reg.rects[0].b = uint16_t(bounds.bottom); + } else { + reg.count = count; + for (size_t i=0 ; i= NUM_BUFFER_MAX) return res; - const FlatRegion& reg(dirtyRegion[buffer]); - res.set(Rect(reg.rects[0], reg.rects[1], reg.rects[2], reg.rects[3])); + const FlatRegion& reg(buffers[buffer].dirtyRegion); + if (reg.count > FlatRegion::NUM_RECT_MAX) + return res; + + if (reg.count == 1) { + const Rect r( + reg.rects[0].l, + reg.rects[0].t, + reg.rects[0].r, + reg.rects[0].b); + res.set(r); + } else { + for (size_t i=0 ; isurfaces + surface), - mNumBuffers(num), mIdentity(identity) + mIdentity(identity) { } @@ -108,16 +151,16 @@ SharedBufferBase::~SharedBufferBase() { } -uint32_t SharedBufferBase::getIdentity() +status_t SharedBufferBase::getStatus() const { SharedBufferStack& stack( *mSharedStack ); - return stack.identity; + return stack.status; } -status_t SharedBufferBase::getStatus() const +int32_t SharedBufferBase::getIdentity() const { SharedBufferStack& stack( *mSharedStack ); - return stack.status; + return stack.identity; } size_t SharedBufferBase::getFrontBuffer() const @@ -132,16 +175,52 @@ String8 SharedBufferBase::dump(char const* prefix) const char buffer[SIZE]; String8 result; SharedBufferStack& stack( *mSharedStack ); - int tail = (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers; snprintf(buffer, SIZE, - "%s[ head=%2d, available=%2d, queued=%2d, tail=%2d ] " - "reallocMask=%08x, inUse=%2d, identity=%d, status=%d\n", - prefix, stack.head, stack.available, stack.queued, tail, + "%s[ head=%2d, available=%2d, queued=%2d ] " + "reallocMask=%08x, inUse=%2d, identity=%d, status=%d", + prefix, stack.head, stack.available, stack.queued, stack.reallocMask, stack.inUse, stack.identity, stack.status); result.append(buffer); + result.append("\n"); return result; } +status_t SharedBufferBase::waitForCondition(const ConditionBase& condition) +{ + const SharedBufferStack& stack( *mSharedStack ); + SharedClient& client( *mSharedClient ); + const nsecs_t TIMEOUT = s2ns(1); + const int identity = mIdentity; + + Mutex::Autolock _l(client.lock); + while ((condition()==false) && + (stack.identity == identity) && + (stack.status == NO_ERROR)) + { + status_t err = client.cv.waitRelative(client.lock, TIMEOUT); + // handle errors and timeouts + if (CC_UNLIKELY(err != NO_ERROR)) { + if (err == TIMED_OUT) { + if (condition()) { + LOGE("waitForCondition(%s) timed out (identity=%d), " + "but condition is true! We recovered but it " + "shouldn't happen." , condition.name(), stack.identity); + break; + } else { + LOGW("waitForCondition(%s) timed out " + "(identity=%d, status=%d). " + "CPU may be pegged. trying again.", condition.name(), + stack.identity, stack.status); + } + } else { + LOGE("waitForCondition(%s) error (%s) ", + condition.name(), strerror(-err)); + return err; + } + } + } + return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status; +} // ============================================================================ // conditions and updates // ============================================================================ @@ -149,24 +228,34 @@ String8 SharedBufferBase::dump(char const* prefix) const SharedBufferClient::DequeueCondition::DequeueCondition( SharedBufferClient* sbc) : ConditionBase(sbc) { } -bool SharedBufferClient::DequeueCondition::operator()() { +bool SharedBufferClient::DequeueCondition::operator()() const { return stack.available > 0; } SharedBufferClient::LockCondition::LockCondition( SharedBufferClient* sbc, int buf) : ConditionBase(sbc), buf(buf) { } -bool SharedBufferClient::LockCondition::operator()() { - return (buf != stack.head || +bool SharedBufferClient::LockCondition::operator()() const { + // NOTE: if stack.head is messed up, we could crash the client + // or cause some drawing artifacts. This is okay, as long as it is + // limited to the client. + return (buf != stack.index[stack.head] || (stack.queued > 0 && stack.inUse != buf)); } SharedBufferServer::ReallocateCondition::ReallocateCondition( SharedBufferBase* sbb, int buf) : ConditionBase(sbb), buf(buf) { } -bool SharedBufferServer::ReallocateCondition::operator()() { +bool SharedBufferServer::ReallocateCondition::operator()() const { + int32_t head = stack.head; + if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX) { + // if stack.head is messed up, we cannot allow the server to + // crash (since stack.head is mapped on the client side) + stack.status = BAD_VALUE; + return false; + } // TODO: we should also check that buf has been dequeued - return (buf != stack.head); + return (buf != stack.index[head]); } // ---------------------------------------------------------------------------- @@ -206,11 +295,12 @@ SharedBufferServer::RetireUpdate::RetireUpdate( : UpdateBase(sbb), numBuffers(numBuffers) { } ssize_t SharedBufferServer::RetireUpdate::operator()() { - // head is only written in this function, which is single-thread. int32_t head = stack.head; + if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX) + return BAD_VALUE; // Preventively lock the current buffer before updating queued. - android_atomic_write(head, &stack.inUse); + android_atomic_write(stack.index[head], &stack.inUse); // Decrement the number of queued buffers int32_t queued; @@ -221,16 +311,15 @@ ssize_t SharedBufferServer::RetireUpdate::operator()() { } } while (android_atomic_cmpxchg(queued, queued-1, &stack.queued)); - // update the head pointer - head = ((head+1 >= numBuffers) ? 0 : head+1); - // lock the buffer before advancing head, which automatically unlocks // the buffer we preventively locked upon entering this function - android_atomic_write(head, &stack.inUse); - // advance head + head = (head + 1) % numBuffers; + android_atomic_write(stack.index[head], &stack.inUse); + + // head is only modified here, so we don't need to use cmpxchg android_atomic_write(head, &stack.head); - + // now that head has moved, we can increment the number of available buffers android_atomic_inc(&stack.available); return head; @@ -250,41 +339,31 @@ ssize_t SharedBufferServer::StatusUpdate::operator()() { SharedBufferClient::SharedBufferClient(SharedClient* sharedClient, int surface, int num, int32_t identity) - : SharedBufferBase(sharedClient, surface, num, identity), tail(0) + : SharedBufferBase(sharedClient, surface, identity), + mNumBuffers(num), tail(0), undoDequeueTail(0) { + SharedBufferStack& stack( *mSharedStack ); tail = computeTail(); + queued_head = stack.head; } int32_t SharedBufferClient::computeTail() const { SharedBufferStack& stack( *mSharedStack ); - // we need to make sure we read available and head coherently, - // w.r.t RetireUpdate. - int32_t newTail; - int32_t avail; - int32_t head; - do { - avail = stack.available; - head = stack.head; - } while (stack.available != avail); - newTail = head - avail + 1; - if (newTail < 0) { - newTail += mNumBuffers; - } else if (newTail >= mNumBuffers) { - newTail -= mNumBuffers; - } - return newTail; + return (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers; } ssize_t SharedBufferClient::dequeue() { SharedBufferStack& stack( *mSharedStack ); - if (stack.head == tail && stack.available == 2) { + if (stack.head == tail && stack.available == mNumBuffers) { LOGW("dequeue: tail=%d, head=%d, avail=%d, queued=%d", tail, stack.head, stack.available, stack.queued); } - + + RWLock::AutoRLock _rd(mLock); + const nsecs_t dequeueTime = systemTime(SYSTEM_TIME_THREAD); //LOGD("[%d] about to dequeue a buffer", @@ -301,9 +380,10 @@ ssize_t SharedBufferClient::dequeue() LOGW("dequeue probably called from multiple threads!"); } - int dequeued = tail; + undoDequeueTail = tail; + int dequeued = stack.index[tail]; tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1); - LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail=%d, %s", + LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail++=%d, %s", dequeued, tail, dump("").string()); mDequeueTime[dequeued] = dequeueTime; @@ -313,16 +393,23 @@ ssize_t SharedBufferClient::dequeue() status_t SharedBufferClient::undoDequeue(int buf) { + RWLock::AutoRLock _rd(mLock); + + // TODO: we can only undo the previous dequeue, we should + // enforce that in the api UndoDequeueUpdate update(this); status_t err = updateCondition( update ); if (err == NO_ERROR) { - tail = computeTail(); + tail = undoDequeueTail; } return err; } status_t SharedBufferClient::lock(int buf) { + RWLock::AutoRLock _rd(mLock); + + SharedBufferStack& stack( *mSharedStack ); LockCondition condition(this, buf); status_t err = waitForCondition(condition); return err; @@ -330,53 +417,100 @@ status_t SharedBufferClient::lock(int buf) status_t SharedBufferClient::queue(int buf) { + RWLock::AutoRLock _rd(mLock); + + SharedBufferStack& stack( *mSharedStack ); + + queued_head = (queued_head + 1) % mNumBuffers; + stack.index[queued_head] = buf; + QueueUpdate update(this); status_t err = updateCondition( update ); LOGD_IF(DEBUG_ATOMICS, "queued=%d, %s", buf, dump("").string()); - SharedBufferStack& stack( *mSharedStack ); + const nsecs_t now = systemTime(SYSTEM_TIME_THREAD); stack.stats.totalTime = ns2us(now - mDequeueTime[buf]); return err; } -bool SharedBufferClient::needNewBuffer(int buffer) const +bool SharedBufferClient::needNewBuffer(int buf) const { SharedBufferStack& stack( *mSharedStack ); - const uint32_t mask = 1<= SharedBufferStack::NUM_BUFFER_MAX) + return BAD_VALUE; + + if (uint32_t(bufferCount) < SharedBufferStack::NUM_BUFFER_MIN) + return BAD_VALUE; + + RWLock::AutoWLock _wr(mLock); + + status_t err = ipc(bufferCount); + if (err == NO_ERROR) { + mNumBuffers = bufferCount; + queued_head = (stack.head + stack.queued) % mNumBuffers; + } + return err; } // ---------------------------------------------------------------------------- SharedBufferServer::SharedBufferServer(SharedClient* sharedClient, int surface, int num, int32_t identity) - : SharedBufferBase(sharedClient, surface, num, identity) + : SharedBufferBase(sharedClient, surface, identity), + mNumBuffers(num) { mSharedStack->init(identity); mSharedStack->head = num-1; mSharedStack->available = num; mSharedStack->queued = 0; mSharedStack->reallocMask = 0; - memset(mSharedStack->dirtyRegion, 0, sizeof(mSharedStack->dirtyRegion)); + memset(mSharedStack->buffers, 0, sizeof(mSharedStack->buffers)); + for (int i=0 ; iindex[i] = i; + } } ssize_t SharedBufferServer::retireAndLock() { + RWLock::AutoRLock _l(mLock); + RetireUpdate update(this, mNumBuffers); ssize_t buf = updateCondition( update ); - LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s", int(buf), dump("").string()); + if (buf >= 0) { + if (uint32_t(buf) >= SharedBufferStack::NUM_BUFFER_MAX) + return BAD_VALUE; + SharedBufferStack& stack( *mSharedStack ); + buf = stack.index[buf]; + LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s", + int(buf), dump("").string()); + } return buf; } -status_t SharedBufferServer::unlock(int buffer) +status_t SharedBufferServer::unlock(int buf) { - UnlockUpdate update(this, buffer); + UnlockUpdate update(this, buf); status_t err = updateCondition( update ); return err; } @@ -389,11 +523,25 @@ void SharedBufferServer::setStatus(status_t status) } } -status_t SharedBufferServer::reallocate() +status_t SharedBufferServer::reallocateAll() { + RWLock::AutoRLock _l(mLock); + SharedBufferStack& stack( *mSharedStack ); - uint32_t mask = (1<= SharedBufferStack::NUM_BUFFER_MAX) + return BAD_VALUE; + + RWLock::AutoWLock _l(mLock); + + // for now we're not supporting shrinking + const int numBuffers = mNumBuffers; + if (newNumBuffers < numBuffers) + return BAD_VALUE; + + SharedBufferStack& stack( *mSharedStack ); + const int extra = newNumBuffers - numBuffers; + + // read the head, make sure it's valid + int32_t head = stack.head; + if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX) + return BAD_VALUE; + + int base = numBuffers; + int32_t avail = stack.available; + int tail = head - avail + 1; + + if (tail >= 0) { + int8_t* const index = const_cast(stack.index); + const int nb = numBuffers - head; + memmove(&index[head + extra], &index[head], nb); + base = head; + // move head 'extra' ahead, this doesn't impact stack.index[head]; + stack.head = head + extra; + } + stack.available += extra; + + // fill the new free space with unused buffers + BufferList::const_iterator curr(mBufferList.free_begin()); + for (int i=0 ; i= mCapacity) + return BAD_VALUE; + uint32_t mask = 1<<(31-value); + if (mList & mask) + return ALREADY_EXISTS; + mList |= mask; + return NO_ERROR; +} + +status_t SharedBufferServer::BufferList::remove(int value) +{ + if (uint32_t(value) >= mCapacity) + return BAD_VALUE; + uint32_t mask = 1<<(31-value); + if (!(mList & mask)) + return NAME_NOT_FOUND; + mList &= ~mask; + return NO_ERROR; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp index 5dd75c32135f02b931677cfbeec5913f9c058e67..ac4b198396e59b85cb56ec0b0447600b134505b1 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -17,8 +17,6 @@ #define LOG_TAG "Surface" #include -#include -#include #include #include #include @@ -28,8 +26,6 @@ #include #include -#include - #include #include @@ -55,6 +51,8 @@ static status_t copyBlt( const sp& src, const Region& reg) { + // src and dst with, height and format must be identical. no verification + // is done here. status_t err; uint8_t const * src_bits = NULL; err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); @@ -67,7 +65,6 @@ static status_t copyBlt( Region::const_iterator head(reg.begin()); Region::const_iterator tail(reg.end()); if (head != tail && src_bits && dst_bits) { - // NOTE: dst and src must be the same format const size_t bpp = bytesPerPixel(src->format); const size_t dbpr = dst->stride * bpp; const size_t sbpr = src->stride * bpp; @@ -107,7 +104,7 @@ static status_t copyBlt( SurfaceControl::SurfaceControl( const sp& client, const sp& surface, - const ISurfaceFlingerClient::surface_data_t& data, + const ISurfaceComposerClient::surface_data_t& data, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) : mClient(client), mSurface(surface), mToken(data.token), mIdentity(data.identity), @@ -154,75 +151,75 @@ bool SurfaceControl::isSameSurface( } status_t SurfaceControl::setLayer(int32_t layer) { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->setLayer(mToken, layer); } status_t SurfaceControl::setPosition(int32_t x, int32_t y) { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->setPosition(mToken, x, y); } status_t SurfaceControl::setSize(uint32_t w, uint32_t h) { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->setSize(mToken, w, h); } status_t SurfaceControl::hide() { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->hide(mToken); } status_t SurfaceControl::show(int32_t layer) { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->show(mToken, layer); } status_t SurfaceControl::freeze() { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->freeze(mToken); } status_t SurfaceControl::unfreeze() { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->unfreeze(mToken); } status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->setFlags(mToken, flags, mask); } status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->setTransparentRegionHint(mToken, transparent); } status_t SurfaceControl::setAlpha(float alpha) { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->setAlpha(mToken, alpha); } status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy); } status_t SurfaceControl::setFreezeTint(uint32_t tint) { - const sp& client(mClient); status_t err = validate(); if (err < 0) return err; + const sp& client(mClient); return client->setFreezeTint(mToken, tint); } @@ -233,23 +230,6 @@ status_t SurfaceControl::validate() const mToken, mIdentity, mClient.get()); return NO_INIT; } - SharedClient const* cblk = mClient->mControl; - if (cblk == 0) { - LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity); - return NO_INIT; - } - status_t err = cblk->validate(mToken); - if (err != NO_ERROR) { - LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", - mToken, mIdentity, err, strerror(-err)); - return err; - } - uint32_t identity = cblk->getIdentity(mToken); - if (mIdentity != identity) { - LOGE("using an invalid surface id=%d, identity=%u should be %d", - mToken, mIdentity, identity); - return NO_INIT; - } return NO_ERROR; } @@ -299,22 +279,22 @@ sp SurfaceControl::getSurface() const // ============================================================================ Surface::Surface(const sp& surface) - : mClient(surface->mClient), mSurface(surface->mSurface), + : mSurface(surface->mSurface), mToken(surface->mToken), mIdentity(surface->mIdentity), mFormat(surface->mFormat), mFlags(surface->mFlags), mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL), + mInitCheck(NO_INIT), mWidth(surface->mWidth), mHeight(surface->mHeight) { - mSharedBufferClient = new SharedBufferClient( - mClient->mControl, mToken, 2, mIdentity); - + mClient = new SurfaceClient(surface->mClient); init(); } Surface::Surface(const Parcel& parcel) - : mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL) + : mBufferMapper(GraphicBufferMapper::get()), + mSharedBufferClient(NULL), mInitCheck(NO_INIT) { - sp clientBinder = parcel.readStrongBinder(); + sp conn = parcel.readStrongBinder(); mSurface = interface_cast(parcel.readStrongBinder()); mToken = parcel.readInt32(); mIdentity = parcel.readInt32(); @@ -322,15 +302,7 @@ Surface::Surface(const Parcel& parcel) mHeight = parcel.readInt32(); mFormat = parcel.readInt32(); mFlags = parcel.readInt32(); - - // FIXME: what does that mean if clientBinder is NULL here? - if (clientBinder != NULL) { - mClient = SurfaceComposerClient::clientForConnection(clientBinder); - - mSharedBufferClient = new SharedBufferClient( - mClient->mControl, mToken, 2, mIdentity); - } - + mClient = new SurfaceClient(conn); init(); } @@ -342,7 +314,7 @@ void Surface::init() android_native_window_t::queueBuffer = queueBuffer; android_native_window_t::query = query; android_native_window_t::perform = perform; - mSwapRectangle.makeInvalid(); + DisplayInfo dinfo; SurfaceComposerClient::getDisplayInfo(0, &dinfo); const_cast(android_native_window_t::xdpi) = dinfo.xdpi; @@ -351,17 +323,27 @@ void Surface::init() const_cast(android_native_window_t::minSwapInterval) = 1; const_cast(android_native_window_t::maxSwapInterval) = 1; const_cast(android_native_window_t::flags) = 0; - // be default we request a hardware surface - mUsage = GRALLOC_USAGE_HW_RENDER; + mConnected = 0; - mNeedFullUpdate = false; + mSwapRectangle.makeInvalid(); + // two buffers by default + mBuffers.setCapacity(2); + mBuffers.insertAt(0, 2); + + if (mClient != 0 && mClient->initCheck() == NO_ERROR) { + mSharedBufferClient = new SharedBufferClient( + mClient->getSharedClient(), mToken, 2, mIdentity); + } + + mInitCheck = initCheck(); } Surface::~Surface() { // this is a client-side operation, the surface is destroyed, unmap // its buffers in this process. - for (int i=0 ; i<2 ; i++) { + size_t size = mBuffers.size(); + for (size_t i=0 ; ihandle != 0) { getBufferMapper().unregisterBuffer(mBuffers[i]->handle); } @@ -369,62 +351,78 @@ Surface::~Surface() // clear all references and trigger an IPC now, to make sure things // happen without delay, since these resources are quite heavy. + mBuffers.clear(); mClient.clear(); mSurface.clear(); delete mSharedBufferClient; IPCThreadState::self()->flushCommands(); } -sp Surface::getClient() const { - return mClient; -} - -sp Surface::getISurface() const { - return mSurface; +status_t Surface::initCheck() const +{ + if (mToken<0 || mClient==0 || mClient->initCheck() != NO_ERROR) { + return NO_INIT; + } + SharedClient const* cblk = mClient->getSharedClient(); + if (cblk == 0) { + LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity); + return NO_INIT; + } + return cblk->validate(mToken); } bool Surface::isValid() { - return mToken>=0 && mClient!=0; + return mInitCheck == NO_ERROR; } status_t Surface::validate() const { - sp client(getClient()); - if (mToken<0 || mClient==0) { - LOGE("invalid token (%d, identity=%u) or client (%p)", - mToken, mIdentity, client.get()); - return NO_INIT; + // check that we initialized ourself properly + if (mInitCheck != NO_ERROR) { + LOGE("invalid token (%d, identity=%u) or client (%p)", + mToken, mIdentity, mClient.get()); + return mInitCheck; } - SharedClient const* cblk = mClient->mControl; - if (cblk == 0) { - LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity); + + // verify the identity of this surface + uint32_t identity = mSharedBufferClient->getIdentity(); + + // this is a bit of a (temporary) special case, identity==0 means that + // no operation are allowed from the client (eg: dequeue/queue), this + // is used with PUSH_BUFFER surfaces for instance + if (identity == 0) { + LOGE("[Surface] invalid operation (identity=%u)", mIdentity); + return INVALID_OPERATION; + } + + if (mIdentity != identity) { + LOGE("[Surface] using an invalid surface id=%d, " + "identity=%u should be %d", + mToken, mIdentity, identity); return NO_INIT; } - status_t err = cblk->validate(mToken); + + // check the surface didn't become invalid + status_t err = mSharedBufferClient->getStatus(); if (err != NO_ERROR) { LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", mToken, mIdentity, err, strerror(-err)); return err; } - uint32_t identity = cblk->getIdentity(mToken); - if (mIdentity != identity) { - LOGE("using an invalid surface id=%d, identity=%u should be %d", - mToken, mIdentity, identity); - return NO_INIT; - } + return NO_ERROR; } - -bool Surface::isSameSurface( - const sp& lhs, const sp& rhs) -{ +bool Surface::isSameSurface(const sp& lhs, const sp& rhs) { if (lhs == 0 || rhs == 0) return false; - return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); } +sp Surface::getISurface() const { + return mSurface; +} + // ---------------------------------------------------------------------------- int Surface::setSwapInterval(android_native_window_t* window, int interval) { @@ -467,21 +465,24 @@ int Surface::perform(android_native_window_t* window, // ---------------------------------------------------------------------------- -status_t Surface::dequeueBuffer(sp* buffer) { - android_native_buffer_t* out; - status_t err = dequeueBuffer(&out); - if (err == NO_ERROR) { - *buffer = GraphicBuffer::getSelf(out); +bool Surface::needNewBuffer(int bufIdx, + uint32_t *pWidth, uint32_t *pHeight, + uint32_t *pFormat, uint32_t *pUsage) const +{ + Mutex::Autolock _l(mSurfaceLock); + + // Always call needNewBuffer(), since it clears the needed buffers flags + bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx); + bool validBuffer = mBufferInfo.validateBuffer(mBuffers[bufIdx]); + bool newNeewBuffer = needNewBuffer || !validBuffer; + if (newNeewBuffer) { + mBufferInfo.get(pWidth, pHeight, pFormat, pUsage); } - return err; + return newNeewBuffer; } -// ---------------------------------------------------------------------------- - - int Surface::dequeueBuffer(android_native_buffer_t** buffer) { - sp client(getClient()); status_t err = validate(); if (err != NO_ERROR) return err; @@ -492,24 +493,28 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer) return bufIdx; } - // below we make sure we AT LEAST have the usage flags we want - const uint32_t usage(getUsage()); - const sp& backBuffer(mBuffers[bufIdx]); - if (backBuffer == 0 || - ((uint32_t(backBuffer->usage) & usage) != usage) || - mSharedBufferClient->needNewBuffer(bufIdx)) - { - err = getBufferLocked(bufIdx, usage); - LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)", - bufIdx, usage, strerror(-err)); + // grow the buffer array if needed + const size_t size = mBuffers.size(); + const size_t needed = bufIdx+1; + if (size < needed) { + mBuffers.insertAt(size, needed-size); + } + + uint32_t w, h, format, usage; + if (needNewBuffer(bufIdx, &w, &h, &format, &usage)) { + err = getBufferLocked(bufIdx, w, h, format, usage); + LOGE_IF(err, "getBufferLocked(%ld, %u, %u, %u, %08x) failed (%s)", + bufIdx, w, h, format, usage, strerror(-err)); if (err == NO_ERROR) { // reset the width/height with the what we get from the buffer + const sp& backBuffer(mBuffers[bufIdx]); mWidth = uint32_t(backBuffer->width); mHeight = uint32_t(backBuffer->height); } } // if we still don't have a buffer here, we probably ran out of memory + const sp& backBuffer(mBuffers[bufIdx]); if (!err && backBuffer==0) { err = NO_MEMORY; } @@ -526,12 +531,11 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer) int Surface::lockBuffer(android_native_buffer_t* buffer) { - sp client(getClient()); status_t err = validate(); if (err != NO_ERROR) return err; - int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex(); + int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer)); err = mSharedBufferClient->lock(bufIdx); LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err)); return err; @@ -539,7 +543,6 @@ int Surface::lockBuffer(android_native_buffer_t* buffer) int Surface::queueBuffer(android_native_buffer_t* buffer) { - sp client(getClient()); status_t err = validate(); if (err != NO_ERROR) return err; @@ -548,14 +551,15 @@ int Surface::queueBuffer(android_native_buffer_t* buffer) mDirtyRegion.set(mSwapRectangle); } - int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex(); + int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer)); + mSharedBufferClient->setCrop(bufIdx, mNextBufferCrop); mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion); err = mSharedBufferClient->queue(bufIdx); LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err)); if (err == NO_ERROR) { // FIXME: can we avoid this IPC if we know there is one pending? - client->signalServer(); + mClient->signalServer(); } return err; } @@ -578,6 +582,10 @@ int Surface::query(int what, int* value) int Surface::perform(int operation, va_list args) { + status_t err = validate(); + if (err != NO_ERROR) + return err; + int res = NO_ERROR; switch (operation) { case NATIVE_WINDOW_SET_USAGE: @@ -589,6 +597,15 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_DISCONNECT: res = dispatch_disconnect( args ); break; + case NATIVE_WINDOW_SET_CROP: + res = dispatch_crop( args ); + break; + case NATIVE_WINDOW_SET_BUFFER_COUNT: + res = dispatch_set_buffer_count( args ); + break; + case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: + res = dispatch_set_buffers_geometry( args ); + break; default: res = NAME_NOT_FOUND; break; @@ -608,12 +625,25 @@ int Surface::dispatch_disconnect(va_list args) { int api = va_arg(args, int); return disconnect( api ); } - +int Surface::dispatch_crop(va_list args) { + android_native_rect_t const* rect = va_arg(args, android_native_rect_t*); + return crop( reinterpret_cast(rect) ); +} +int Surface::dispatch_set_buffer_count(va_list args) { + size_t bufferCount = va_arg(args, size_t); + return setBufferCount(bufferCount); +} +int Surface::dispatch_set_buffers_geometry(va_list args) { + int w = va_arg(args, int); + int h = va_arg(args, int); + int f = va_arg(args, int); + return setBuffersGeometry(w, h, f); +} void Surface::setUsage(uint32_t reqUsage) { Mutex::Autolock _l(mSurfaceLock); - mUsage = reqUsage; + mBufferInfo.set(reqUsage); } int Surface::connect(int api) @@ -654,19 +684,55 @@ int Surface::disconnect(int api) return err; } -uint32_t Surface::getUsage() const +int Surface::crop(Rect const* rect) { Mutex::Autolock _l(mSurfaceLock); - return mUsage; + // TODO: validate rect size + mNextBufferCrop = *rect; + return NO_ERROR; } +int Surface::setBufferCount(int bufferCount) +{ + sp s(mSurface); + if (s == 0) return NO_INIT; + + class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback { + sp surface; + virtual status_t operator()(int bufferCount) const { + return surface->setBufferCount(bufferCount); + } + public: + SetBufferCountIPC(const sp& surface) : surface(surface) { } + } ipc(s); + + status_t err = mSharedBufferClient->setBufferCount(bufferCount, ipc); + LOGE_IF(err, "ISurface::setBufferCount(%d) returned %s", + bufferCount, strerror(-err)); + return err; +} + +int Surface::setBuffersGeometry(int w, int h, int format) +{ + if (w<0 || h<0 || format<0) + return BAD_VALUE; + + if ((w && !h) || (!w && h)) + return BAD_VALUE; + + Mutex::Autolock _l(mSurfaceLock); + mBufferInfo.set(w, h, format); + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + int Surface::getConnectedApi() const { Mutex::Autolock _l(mSurfaceLock); return mConnected; } - // ---------------------------------------------------------------------------- status_t Surface::lock(SurfaceInfo* info, bool blocking) { @@ -703,45 +769,47 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) // we're intending to do software rendering from this point setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); - sp backBuffer; - status_t err = dequeueBuffer(&backBuffer); + android_native_buffer_t* out; + status_t err = dequeueBuffer(&out); LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); if (err == NO_ERROR) { + sp backBuffer(GraphicBuffer::getSelf(out)); err = lockBuffer(backBuffer.get()); LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)", - backBuffer->getIndex(), strerror(-err)); + getBufferIndex(backBuffer), strerror(-err)); if (err == NO_ERROR) { - // we handle copy-back here... - const Rect bounds(backBuffer->width, backBuffer->height); - Region scratch(bounds); + const Region boundsRegion(bounds); + Region scratch(boundsRegion); Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); + newDirtyRegion &= boundsRegion; - if (mNeedFullUpdate) { - // reset newDirtyRegion to bounds when a buffer is reallocated - // it would be better if this information was associated with - // the buffer and made available to outside of Surface. - // This will do for now though. - mNeedFullUpdate = false; - newDirtyRegion.set(bounds); - } else { - newDirtyRegion.andSelf(bounds); - } - + // figure out if we can copy the frontbuffer back const sp& frontBuffer(mPostedBuffer); - if (frontBuffer !=0 && - backBuffer->width == frontBuffer->width && - backBuffer->height == frontBuffer->height && - !(mFlags & ISurfaceComposer::eDestroyBackbuffer)) - { + const bool canCopyBack = (frontBuffer != 0 && + backBuffer->width == frontBuffer->width && + backBuffer->height == frontBuffer->height && + backBuffer->format == frontBuffer->format && + !(mFlags & ISurfaceComposer::eDestroyBackbuffer)); + + // the dirty region we report to surfaceflinger is the one + // given by the user (as opposed to the one *we* return to the + // user). + mDirtyRegion = newDirtyRegion; + + if (canCopyBack) { + // copy the area that is invalid and not repainted this round const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); - if (!copyback.isEmpty() && frontBuffer!=0) { - // copy front to back + if (!copyback.isEmpty()) copyBlt(backBuffer, frontBuffer, copyback); - } + } else { + // if we can't copy-back anything, modify the user's dirty + // region to make sure they redraw the whole buffer + newDirtyRegion = boundsRegion; } - mDirtyRegion = newDirtyRegion; + // keep track of the are of the buffer that is "clean" + // (ie: that will be redrawn) mOldDirtyRegion = newDirtyRegion; void* vaddr; @@ -777,7 +845,7 @@ status_t Surface::unlockAndPost() err = queueBuffer(mLockedBuffer.get()); LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)", - mLockedBuffer->getIndex(), strerror(-err)); + getBufferIndex(mLockedBuffer), strerror(-err)); mPostedBuffer = mLockedBuffer; mLockedBuffer = 0; @@ -789,7 +857,13 @@ void Surface::setSwapRectangle(const Rect& r) { mSwapRectangle = r; } -status_t Surface::getBufferLocked(int index, int usage) +int Surface::getBufferIndex(const sp& buffer) const +{ + return buffer->getIndex(); +} + +status_t Surface::getBufferLocked(int index, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { sp s(mSurface); if (s == 0) return NO_INIT; @@ -797,20 +871,21 @@ status_t Surface::getBufferLocked(int index, int usage) status_t err = NO_MEMORY; // free the current buffer - sp& currentBuffer(mBuffers[index]); + sp& currentBuffer(mBuffers.editItemAt(index)); if (currentBuffer != 0) { getBufferMapper().unregisterBuffer(currentBuffer->handle); currentBuffer.clear(); } - sp buffer = s->requestBuffer(index, usage); + sp buffer = s->requestBuffer(index, w, h, format, usage); LOGE_IF(buffer==0, "ISurface::getBuffer(%d, %08x) returned NULL", index, usage); if (buffer != 0) { // this should never happen by construction LOGE_IF(buffer->handle == NULL, - "Surface (identity=%d) requestBuffer(%d, %08x) returned" - "a buffer with a null handle", mIdentity, index, usage); + "Surface (identity=%d) requestBuffer(%d, %u, %u, %u, %08x) " + "returned a buffer with a null handle", + mIdentity, index, w, h, format, usage); err = mSharedBufferClient->getStatus(); LOGE_IF(err, "Surface (identity=%d) state = %d", mIdentity, err); if (!err && buffer->handle != NULL) { @@ -820,14 +895,52 @@ status_t Surface::getBufferLocked(int index, int usage) if (err == NO_ERROR) { currentBuffer = buffer; currentBuffer->setIndex(index); - mNeedFullUpdate = true; } } else { - err = err<0 ? err : NO_MEMORY; + err = err<0 ? err : status_t(NO_MEMORY); } } return err; } +// ---------------------------------------------------------------------------- +Surface::BufferInfo::BufferInfo() + : mWidth(0), mHeight(0), mFormat(0), + mUsage(GRALLOC_USAGE_HW_RENDER), mDirty(0) +{ +} + +void Surface::BufferInfo::set(uint32_t w, uint32_t h, uint32_t format) { + if ((mWidth != w) || (mHeight != h) || (mFormat != format)) { + mWidth = w; + mHeight = h; + mFormat = format; + mDirty |= GEOMETRY; + } +} + +void Surface::BufferInfo::set(uint32_t usage) { + mUsage = usage; +} + +void Surface::BufferInfo::get(uint32_t *pWidth, uint32_t *pHeight, + uint32_t *pFormat, uint32_t *pUsage) const { + *pWidth = mWidth; + *pHeight = mHeight; + *pFormat = mFormat; + *pUsage = mUsage; +} + +bool Surface::BufferInfo::validateBuffer(const sp& buffer) const { + // make sure we AT LEAST have the usage flags we want + if (mDirty || buffer==0 || + ((buffer->usage & mUsage) != mUsage)) { + mDirty = 0; + return false; + } + return true; +} + +// ---------------------------------------------------------------------------- }; // namespace android diff --git a/libs/surfaceflinger_client/SurfaceComposerClient.cpp b/libs/surfaceflinger_client/SurfaceComposerClient.cpp index 3117495d3f41b3ba979c9038321d857845f7aff2..0670d2003c291e40c3fca2b558d313e2d23593c4 100644 --- a/libs/surfaceflinger_client/SurfaceComposerClient.cpp +++ b/libs/surfaceflinger_client/SurfaceComposerClient.cpp @@ -17,98 +17,147 @@ #define LOG_TAG "SurfaceComposerClient" #include -#include -#include -#include #include -#include -#include - -#include #include #include -#include +#include #include +#include #include #include #include -#include #include -#include +#include #include #include #include #include -#define VERBOSE(...) ((void)0) -//#define VERBOSE LOGD - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) namespace android { - // --------------------------------------------------------------------------- -// Must not be holding SurfaceComposerClient::mLock when acquiring gLock here. -static Mutex gLock; -static sp gSurfaceManager; -static DefaultKeyedVector< sp, sp > gActiveConnections; -static SortedVector > gOpenTransactions; -static sp gServerCblkMemory; -static volatile surface_flinger_cblk_t* gServerCblk; - -static sp getComposerService() -{ - sp sc; - Mutex::Autolock _l(gLock); - if (gSurfaceManager != 0) { - sc = gSurfaceManager; - } else { - // release the lock while we're waiting... - gLock.unlock(); - - sp binder; - sp sm = defaultServiceManager(); - do { - binder = sm->getService(String16("SurfaceFlinger")); - if (binder == 0) { - LOGW("SurfaceFlinger not published, waiting..."); - usleep(500000); // 0.5 s - } - } while(binder == 0); - - // grab the lock again for updating gSurfaceManager - gLock.lock(); - if (gSurfaceManager == 0) { - sc = interface_cast(binder); - gSurfaceManager = sc; - } else { - sc = gSurfaceManager; +class ComposerService : public Singleton +{ + // these are constants + sp mComposerService; + sp mServerCblkMemory; + surface_flinger_cblk_t volatile* mServerCblk; + + ComposerService() : Singleton() { + const String16 name("SurfaceFlinger"); + while (getService(name, &mComposerService) != NO_ERROR) { + usleep(250000); } + mServerCblkMemory = mComposerService->getCblk(); + mServerCblk = static_cast( + mServerCblkMemory->getBase()); + } + + friend class Singleton; + +public: + static sp getComposerService() { + return ComposerService::getInstance().mComposerService; + } + static surface_flinger_cblk_t const volatile * getControlBlock() { + return ComposerService::getInstance().mServerCblk; } - return sc; +}; + +ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService); + + +static inline sp getComposerService() { + return ComposerService::getComposerService(); +} + +static inline surface_flinger_cblk_t const volatile * get_cblk() { + return ComposerService::getControlBlock(); } -static volatile surface_flinger_cblk_t const * get_cblk() +// --------------------------------------------------------------------------- + +class Composer : public Singleton { - if (gServerCblk == 0) { - sp sm(getComposerService()); - Mutex::Autolock _l(gLock); - if (gServerCblk == 0) { - gServerCblkMemory = sm->getCblk(); - LOGE_IF(gServerCblkMemory==0, "Can't get server control block"); - gServerCblk = (surface_flinger_cblk_t *)gServerCblkMemory->getBase(); - LOGE_IF(gServerCblk==0, "Can't get server control block address"); + Mutex mLock; + SortedVector< wp > mActiveConnections; + SortedVector > mOpenTransactions; + + Composer() : Singleton() { + } + + void addClientImpl(const sp& client) { + Mutex::Autolock _l(mLock); + mActiveConnections.add(client); + } + + void removeClientImpl(const sp& client) { + Mutex::Autolock _l(mLock); + mActiveConnections.remove(client); + } + + void openGlobalTransactionImpl() + { + Mutex::Autolock _l(mLock); + if (mOpenTransactions.size()) { + LOGE("openGlobalTransaction() called more than once. skipping."); + return; + } + const size_t N = mActiveConnections.size(); + for (size_t i=0; i client(mActiveConnections[i].promote()); + if (client != 0 && mOpenTransactions.indexOf(client) < 0) { + if (client->openTransaction() == NO_ERROR) { + mOpenTransactions.add(client); + } else { + LOGE("openTransaction on client %p failed", client.get()); + // let it go, it'll fail later when the user + // tries to do something with the transaction + } + } } } - return gServerCblk; -} + + void closeGlobalTransactionImpl() + { + mLock.lock(); + SortedVector< sp > clients(mOpenTransactions); + mOpenTransactions.clear(); + mLock.unlock(); + + sp sm(getComposerService()); + sm->openGlobalTransaction(); + const size_t N = clients.size(); + for (size_t i=0; icloseTransaction(); + } + sm->closeGlobalTransaction(); + } + + friend class Singleton; + +public: + static void addClient(const sp& client) { + Composer::getInstance().addClientImpl(client); + } + static void removeClient(const sp& client) { + Composer::getInstance().removeClientImpl(client); + } + static void openGlobalTransaction() { + Composer::getInstance().openGlobalTransactionImpl(); + } + static void closeGlobalTransaction() { + Composer::getInstance().closeGlobalTransactionImpl(); + } +}; + +ANDROID_SINGLETON_STATIC_INSTANCE(Composer); // --------------------------------------------------------------------------- @@ -120,61 +169,27 @@ static inline int compare_type( const layer_state_t& lhs, } SurfaceComposerClient::SurfaceComposerClient() + : mTransactionOpen(0), mPrebuiltLayerState(0), mStatus(NO_INIT) { - sp sm(getComposerService()); - if (sm == 0) { - _init(0, 0); - return; - } - - _init(sm, sm->createConnection()); - - if (mClient != 0) { - Mutex::Autolock _l(gLock); - VERBOSE("Adding client %p to map", this); - gActiveConnections.add(mClient->asBinder(), this); - } } -SurfaceComposerClient::SurfaceComposerClient( - const sp& sm, const sp& conn) -{ - _init(sm, interface_cast(conn)); -} - - -status_t SurfaceComposerClient::linkToComposerDeath( - const sp& recipient, - void* cookie, uint32_t flags) +void SurfaceComposerClient::onFirstRef() { sp sm(getComposerService()); - return sm->asBinder()->linkToDeath(recipient, cookie, flags); -} - -void SurfaceComposerClient::_init( - const sp& sm, const sp& conn) -{ - VERBOSE("Creating client %p, conn %p", this, conn.get()); - - mPrebuiltLayerState = 0; - mTransactionOpen = 0; - mStatus = NO_ERROR; - mControl = 0; - - mClient = conn; - if (mClient == 0) { - mStatus = NO_INIT; - return; + if (sm != 0) { + sp conn = sm->createConnection(); + if (conn != 0) { + mClient = conn; + Composer::addClient(this); + mPrebuiltLayerState = new layer_state_t; + mStatus = NO_ERROR; + } } - - mControlMemory = mClient->getControlBlock(); - mSignalServer = sm; - mControl = static_cast(mControlMemory->getBase()); } SurfaceComposerClient::~SurfaceComposerClient() { - VERBOSE("Destroying client %p, conn %p", this, mClient.get()); + delete mPrebuiltLayerState; dispose(); } @@ -188,69 +203,31 @@ sp SurfaceComposerClient::connection() const return (mClient != 0) ? mClient->asBinder() : 0; } -sp -SurfaceComposerClient::clientForConnection(const sp& conn) +status_t SurfaceComposerClient::linkToComposerDeath( + const sp& recipient, + void* cookie, uint32_t flags) { - sp client; - - { // scope for lock - Mutex::Autolock _l(gLock); - client = gActiveConnections.valueFor(conn); - } - - if (client == 0) { - // Need to make a new client. - sp sm(getComposerService()); - client = new SurfaceComposerClient(sm, conn); - if (client != 0 && client->initCheck() == NO_ERROR) { - Mutex::Autolock _l(gLock); - gActiveConnections.add(conn, client); - //LOGD("we have %d connections", gActiveConnections.size()); - } else { - client.clear(); - } - } - - return client; + sp sm(getComposerService()); + return sm->asBinder()->linkToDeath(recipient, cookie, flags); } void SurfaceComposerClient::dispose() { // this can be called more than once. - - sp controlMemory; - sp client; - - { - Mutex::Autolock _lg(gLock); - Mutex::Autolock _lm(mLock); - - mSignalServer = 0; - - if (mClient != 0) { - client = mClient; - mClient.clear(); - - ssize_t i = gActiveConnections.indexOfKey(client->asBinder()); - if (i >= 0 && gActiveConnections.valueAt(i) == this) { - VERBOSE("Removing client %p from map at %d", this, int(i)); - gActiveConnections.removeItemsAt(i); - } - } - - delete mPrebuiltLayerState; - mPrebuiltLayerState = 0; - controlMemory = mControlMemory; - mControlMemory.clear(); - mControl = 0; - mStatus = NO_INIT; + sp client; + Mutex::Autolock _lm(mLock); + if (mClient != 0) { + Composer::removeClient(this); + client = mClient; // hold ref while lock is held + mClient.clear(); } + mStatus = NO_INIT; } status_t SurfaceComposerClient::getDisplayInfo( DisplayID dpy, DisplayInfo* info) { - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) + if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX) return BAD_VALUE; volatile surface_flinger_cblk_t const * cblk = get_cblk(); @@ -268,7 +245,7 @@ status_t SurfaceComposerClient::getDisplayInfo( ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy) { - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) + if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX) return BAD_VALUE; volatile surface_flinger_cblk_t const * cblk = get_cblk(); volatile display_cblk_t const * dcblk = cblk->displays + dpy; @@ -277,7 +254,7 @@ ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy) ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy) { - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) + if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX) return BAD_VALUE; volatile surface_flinger_cblk_t const * cblk = get_cblk(); volatile display_cblk_t const * dcblk = cblk->displays + dpy; @@ -286,7 +263,7 @@ ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy) ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy) { - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) + if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX) return BAD_VALUE; volatile surface_flinger_cblk_t const * cblk = get_cblk(); volatile display_cblk_t const * dcblk = cblk->displays + dpy; @@ -305,12 +282,6 @@ ssize_t SurfaceComposerClient::getNumberOfDisplays() return n; } - -void SurfaceComposerClient::signalServer() -{ - mSignalServer->signal(); -} - sp SurfaceComposerClient::createSurface( int pid, DisplayID display, @@ -327,7 +298,6 @@ sp SurfaceComposerClient::createSurface( return SurfaceComposerClient::createSurface(pid, name, display, w, h, format, flags); - } sp SurfaceComposerClient::createSurface( @@ -341,11 +311,11 @@ sp SurfaceComposerClient::createSurface( { sp result; if (mStatus == NO_ERROR) { - ISurfaceFlingerClient::surface_data_t data; + ISurfaceComposerClient::surface_data_t data; sp surface = mClient->createSurface(&data, pid, name, display, w, h, format, flags); if (surface != 0) { - if (uint32_t(data.token) < NUM_LAYERS_MAX) { + if (uint32_t(data.token) < SharedBufferStack::NUM_LAYERS_MAX) { result = new SurfaceControl(this, surface, data, w, h, format, flags); } } @@ -373,56 +343,14 @@ status_t SurfaceComposerClient::destroySurface(SurfaceID sid) void SurfaceComposerClient::openGlobalTransaction() { - Mutex::Autolock _l(gLock); - - if (gOpenTransactions.size()) { - LOGE("openGlobalTransaction() called more than once. skipping."); - return; - } - - const size_t N = gActiveConnections.size(); - VERBOSE("openGlobalTransaction (%ld clients)", N); - for (size_t i=0; i client(gActiveConnections.valueAt(i)); - if (gOpenTransactions.indexOf(client) < 0) { - if (client->openTransaction() == NO_ERROR) { - if (gOpenTransactions.add(client) < 0) { - // Ooops! - LOGE( "Unable to add a SurfaceComposerClient " - "to the global transaction set (out of memory?)"); - client->closeTransaction(); - // let it go, it'll fail later when the user - // tries to do something with the transaction - } - } else { - LOGE("openTransaction on client %p failed", client.get()); - // let it go, it'll fail later when the user - // tries to do something with the transaction - } - } - } + Composer::openGlobalTransaction(); } void SurfaceComposerClient::closeGlobalTransaction() { - gLock.lock(); - SortedVector< sp > clients(gOpenTransactions); - gOpenTransactions.clear(); - gLock.unlock(); - - const size_t N = clients.size(); - VERBOSE("closeGlobalTransaction (%ld clients)", N); - - sp sm(getComposerService()); - sm->openGlobalTransaction(); - for (size_t i=0; icloseTransaction(); - } - sm->closeGlobalTransaction(); - + Composer::closeGlobalTransaction(); } - status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags) { sp sm(getComposerService()); @@ -447,26 +375,16 @@ status_t SurfaceComposerClient::openTransaction() if (mStatus != NO_ERROR) return mStatus; Mutex::Autolock _l(mLock); - VERBOSE( "openTransaction (client %p, mTransactionOpen=%d)", - this, mTransactionOpen); mTransactionOpen++; - if (mPrebuiltLayerState == 0) { - mPrebuiltLayerState = new layer_state_t; - } return NO_ERROR; } - status_t SurfaceComposerClient::closeTransaction() { if (mStatus != NO_ERROR) return mStatus; Mutex::Autolock _l(mLock); - - VERBOSE( "closeTransaction (client %p, mTransactionOpen=%d)", - this, mTransactionOpen); - if (mTransactionOpen <= 0) { LOGE( "closeTransaction (client %p, mTransactionOpen=%d) " "called more times than openTransaction()", @@ -488,7 +406,7 @@ status_t SurfaceComposerClient::closeTransaction() return NO_ERROR; } -layer_state_t* SurfaceComposerClient::_get_state_l(SurfaceID index) +layer_state_t* SurfaceComposerClient::get_state_l(SurfaceID index) { // API usage error, do nothing. if (mTransactionOpen<=0) { @@ -498,7 +416,7 @@ layer_state_t* SurfaceComposerClient::_get_state_l(SurfaceID index) } // use mPrebuiltLayerState just to find out if we already have it - layer_state_t& dummy = *mPrebuiltLayerState; + layer_state_t& dummy(*mPrebuiltLayerState); dummy.surface = index; ssize_t i = mStates.indexOf(dummy); if (i < 0) { @@ -508,49 +426,49 @@ layer_state_t* SurfaceComposerClient::_get_state_l(SurfaceID index) return mStates.editArray() + i; } -layer_state_t* SurfaceComposerClient::_lockLayerState(SurfaceID id) +layer_state_t* SurfaceComposerClient::lockLayerState(SurfaceID id) { layer_state_t* s; mLock.lock(); - s = _get_state_l(id); + s = get_state_l(id); if (!s) mLock.unlock(); return s; } -void SurfaceComposerClient::_unlockLayerState() +void SurfaceComposerClient::unlockLayerState() { mLock.unlock(); } status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) { - layer_state_t* s = _lockLayerState(id); + layer_state_t* s = lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::ePositionChanged; s->x = x; s->y = y; - _unlockLayerState(); + unlockLayerState(); return NO_ERROR; } status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) { - layer_state_t* s = _lockLayerState(id); + layer_state_t* s = lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eSizeChanged; s->w = w; s->h = h; - _unlockLayerState(); + unlockLayerState(); return NO_ERROR; } status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) { - layer_state_t* s = _lockLayerState(id); + layer_state_t* s = lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eLayerChanged; s->z = z; - _unlockLayerState(); + unlockLayerState(); return NO_ERROR; } @@ -579,34 +497,34 @@ status_t SurfaceComposerClient::unfreeze(SurfaceID id) status_t SurfaceComposerClient::setFlags(SurfaceID id, uint32_t flags, uint32_t mask) { - layer_state_t* s = _lockLayerState(id); + layer_state_t* s = lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eVisibilityChanged; s->flags &= ~mask; s->flags |= (flags & mask); s->mask |= mask; - _unlockLayerState(); + unlockLayerState(); return NO_ERROR; } status_t SurfaceComposerClient::setTransparentRegionHint( SurfaceID id, const Region& transparentRegion) { - layer_state_t* s = _lockLayerState(id); + layer_state_t* s = lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eTransparentRegionChanged; s->transparentRegion = transparentRegion; - _unlockLayerState(); + unlockLayerState(); return NO_ERROR; } status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) { - layer_state_t* s = _lockLayerState(id); + layer_state_t* s = lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eAlphaChanged; s->alpha = alpha; - _unlockLayerState(); + unlockLayerState(); return NO_ERROR; } @@ -615,7 +533,7 @@ status_t SurfaceComposerClient::setMatrix( float dsdx, float dtdx, float dsdy, float dtdy ) { - layer_state_t* s = _lockLayerState(id); + layer_state_t* s = lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eMatrixChanged; layer_state_t::matrix22_t matrix; @@ -624,19 +542,56 @@ status_t SurfaceComposerClient::setMatrix( matrix.dsdy = dsdy; matrix.dtdy = dtdy; s->matrix = matrix; - _unlockLayerState(); + unlockLayerState(); return NO_ERROR; } status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) { - layer_state_t* s = _lockLayerState(id); + layer_state_t* s = lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eFreezeTintChanged; s->tint = tint; - _unlockLayerState(); + unlockLayerState(); return NO_ERROR; } +// ---------------------------------------------------------------------------- + +SurfaceClient::SurfaceClient(const sp& client) + : mStatus(NO_INIT), mControl(0) +{ + if (client != 0) { + sp conn = client->connection(); + init(conn); + } +} +SurfaceClient::SurfaceClient(const sp& conn) + : mStatus(NO_INIT), mControl(0) +{ + init(conn); +} +void SurfaceClient::init(const sp& conn) +{ + mComposerService = getComposerService(); + sp sf(interface_cast(conn)); + if (sf != 0) { + mConnection = conn; + mControlMemory = sf->getControlBlock(); + mControl = static_cast(mControlMemory->getBase()); + mStatus = NO_ERROR; + } +} +status_t SurfaceClient::initCheck() const { + return mStatus; +} +SharedClient* SurfaceClient::getSharedClient() const { + return mControl; +} +void SurfaceClient::signalServer() const { + mComposerService->signal(); +} + +// ---------------------------------------------------------------------------- }; // namespace android diff --git a/libs/surfaceflinger_client/tests/Android.mk b/libs/surfaceflinger_client/tests/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..5053e7d64389d3eaa35c6e807277fff9f83898f6 --- /dev/null +++ b/libs/surfaceflinger_client/tests/Android.mk @@ -0,0 +1 @@ +include $(call all-subdir-makefiles) diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk b/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..d3dfe042850f2cf1699853ecfbd51bef1afd4636 --- /dev/null +++ b/libs/surfaceflinger_client/tests/SharedBufferStack/Android.mk @@ -0,0 +1,17 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + SharedBufferStackTest.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + libui \ + libsurfaceflinger_client + +LOCAL_MODULE:= test-sharedbufferstack + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_EXECUTABLE) diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f409f482897044b27000f336919328912eb14b43 --- /dev/null +++ b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp @@ -0,0 +1,279 @@ +/* + * 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. + */ + +#undef NDEBUG + +#include +#include +#include +#include +#include + +using namespace android; + +void log(const char* prefix, int *b, size_t num); +void test0(SharedBufferServer& s, SharedBufferClient& c, size_t num, int* list); + +// ---------------------------------------------------------------------------- + +int main(int argc, char** argv) +{ + SharedClient client; + SharedBufferServer s(&client, 0, 4, 0); + SharedBufferClient c(&client, 0, 4, 0); + + printf("basic test 0\n"); + int list0[4] = {0, 1, 2, 3}; + test0(s, c, 4, list0); + + printf("basic test 1\n"); + int list1[4] = {2, 1, 0, 3}; + test0(s, c, 4, list1); + + int b = c.dequeue(); + c.lock(b); + c.queue(b); + s.retireAndLock(); + + printf("basic test 2\n"); + int list2[4] = {1, 2, 3, 0}; + test0(s, c, 4, list2); + + + printf("resize test\n"); + class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback { + SharedBufferServer& s; + virtual status_t operator()(int bufferCount) const { + return s.resize(bufferCount); + } + public: + SetBufferCountIPC(SharedBufferServer& s) : s(s) { } + } resize(s); + + c.setBufferCount(6, resize); + int list3[6] = {3, 2, 1, 4, 5, 0}; + test0(s, c, 6, list3); + + return 0; +} + +void log(const char* prefix, int *b, size_t num) +{ + printf("%s: ", prefix); + for (size_t i=0 ; i #include @@ -61,9 +63,9 @@ void GraphicBufferAllocator::dump(String8& result) const const size_t c = list.size(); for (size_t i=0 ; i0 ? c : 1; -} - status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, buffer_handle_t* handle, int32_t* stride) { - // make sure to not allocate a 0 x 0 buffer - w = clamp(w); - h = clamp(h); + // make sure to not allocate a N x 0 or 0 x N buffer, since this is + // allowed from an API stand-point allocate a 1x1 buffer instead. + if (!w || !h) + w = h = 1; // we have a h/w allocator and h/w buffer is requested status_t err; @@ -100,9 +99,9 @@ status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat forma alloc_rec_t rec; rec.w = w; rec.h = h; + rec.s = *stride; rec.format = format; rec.usage = usage; - rec.vaddr = 0; rec.size = h * stride[0] * bytesPerPixel(format); list.add(*handle, rec); } else { diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp index 5a05e6a61f1778acb0f1c80ac9c2d1136e067f7f..60a0d82e255d9244b0477d6c23e2ba9a40052c50 100644 --- a/libs/utils/AssetManager.cpp +++ b/libs/utils/AssetManager.cpp @@ -824,7 +824,7 @@ Asset* AssetManager::openAssetFromZipLocked(const ZipFileRO* pZipFile, // TODO: look for previously-created shared memory slice? int method; - long uncompressedLen; + size_t uncompressedLen; //printf("USING Zip '%s'\n", pEntry->getFileName()); diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 7e0f881af674ae49d857faa39ac7288337328783..a1401addf34543c293af456082a339bd9371abbf 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -4178,6 +4178,9 @@ void ResTable::print(bool inclValues) const case ResTable_config::SCREENSIZE_LARGE: printf(" (large)"); break; + case ResTable_config::SCREENSIZE_XLARGE: + printf(" (xlarge)"); + break; } printf(" lng=%d", type->config.screenLayout&ResTable_config::MASK_SCREENLONG); diff --git a/libs/utils/ZipFileCRO.cpp b/libs/utils/ZipFileCRO.cpp index 45f6c8baa70778ddd1011471d1650abeef0f4175..16b219cad4a21d1051b351c5d4cfa09079df1f04 100644 --- a/libs/utils/ZipFileCRO.cpp +++ b/libs/utils/ZipFileCRO.cpp @@ -39,8 +39,8 @@ ZipEntryCRO ZipFileCRO_findEntryByName(ZipFileCRO zipToken, } bool ZipFileCRO_getEntryInfo(ZipFileCRO zipToken, ZipEntryRO entryToken, - int* pMethod, long* pUncompLen, - long* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) { + int* pMethod, size_t* pUncompLen, + size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) { ZipFileRO* zip = (ZipFileRO*)zipToken; ZipEntryRO entry = (ZipEntryRO)entryToken; return zip->getEntryInfo(entry, pMethod, pUncompLen, pCompLen, pOffset, diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp index 6c701dd0b67347a58f906475b4e5715471b566ab..28dc512bb65823c6fc01df34066c8c82af228735 100644 --- a/libs/utils/ZipFileRO.cpp +++ b/libs/utils/ZipFileRO.cpp @@ -29,6 +29,22 @@ #include #include #include +#include + +/* + * TEMP_FAILURE_RETRY is defined by some, but not all, versions of + * . (Alas, it is not as standard as we'd hoped!) So, if it's + * not already defined, then define it here. + */ +#ifndef TEMP_FAILURE_RETRY +/* Used to retry syscalls that can return EINTR. */ +#define TEMP_FAILURE_RETRY(exp) ({ \ + typeof (exp) _rc; \ + do { \ + _rc = (exp); \ + } while (_rc == -1 && errno == EINTR); \ + _rc; }) +#endif using namespace android; @@ -38,6 +54,7 @@ using namespace android; #define kEOCDSignature 0x06054b50 #define kEOCDLen 22 #define kEOCDNumEntries 8 // offset to #of entries in file +#define kEOCDSize 12 // size of the central directory #define kEOCDFileOffset 16 // offset to central directory #define kMaxCommentLen 65535 // longest possible in ushort @@ -90,9 +107,8 @@ int ZipFileRO::entryToIndex(const ZipEntryRO entry) const status_t ZipFileRO::open(const char* zipFileName) { int fd = -1; - off_t length; - assert(mFileMap == NULL); + assert(mDirectoryMap == NULL); /* * Open and map the specified file. @@ -103,172 +119,240 @@ status_t ZipFileRO::open(const char* zipFileName) return NAME_NOT_FOUND; } - length = lseek(fd, 0, SEEK_END); - if (length < 0) { + mFileLength = lseek(fd, 0, SEEK_END); + if (mFileLength < kEOCDLen) { close(fd); return UNKNOWN_ERROR; } - mFileMap = new FileMap(); - if (mFileMap == NULL) { - close(fd); - return NO_MEMORY; - } - if (!mFileMap->create(zipFileName, fd, 0, length, true)) { - LOGW("Unable to map '%s': %s\n", zipFileName, strerror(errno)); - close(fd); - return UNKNOWN_ERROR; + if (mFileName != NULL) { + free(mFileName); } + mFileName = strdup(zipFileName); mFd = fd; /* - * Got it mapped, verify it and create data structures for fast access. + * Find the Central Directory and store its size and number of entries. + */ + if (!mapCentralDirectory()) { + goto bail; + } + + /* + * Verify Central Directory and create data structures for fast access. */ if (!parseZipArchive()) { - mFileMap->release(); - mFileMap = NULL; - return UNKNOWN_ERROR; + goto bail; } return OK; + +bail: + free(mFileName); + mFileName = NULL; + close(fd); + return UNKNOWN_ERROR; } /* * Parse the Zip archive, verifying its contents and initializing internal * data structures. */ -bool ZipFileRO::parseZipArchive(void) +bool ZipFileRO::mapCentralDirectory(void) { -#define CHECK_OFFSET(_off) { \ - if ((unsigned int) (_off) >= maxOffset) { \ - LOGE("ERROR: bad offset %u (max %d): %s\n", \ - (unsigned int) (_off), maxOffset, #_off); \ - goto bail; \ - } \ - } - const unsigned char* basePtr = (const unsigned char*)mFileMap->getDataPtr(); - const unsigned char* ptr; - size_t length = mFileMap->getDataLength(); - bool result = false; - unsigned int i, numEntries, cdOffset; - unsigned int val; + size_t readAmount = kMaxEOCDSearch; + if (readAmount > (size_t) mFileLength) + readAmount = mFileLength; + + unsigned char* scanBuf = (unsigned char*) malloc(readAmount); + if (scanBuf == NULL) { + LOGW("couldn't allocate scanBuf: %s", strerror(errno)); + free(scanBuf); + return false; + } /* - * The first 4 bytes of the file will either be the local header - * signature for the first file (kLFHSignature) or, if the archive doesn't - * have any files in it, the end-of-central-directory signature - * (kEOCDSignature). + * Make sure this is a Zip archive. */ - val = get4LE(basePtr); - if (val == kEOCDSignature) { - LOGI("Found Zip archive, but it looks empty\n"); - goto bail; - } else if (val != kLFHSignature) { - LOGV("Not a Zip archive (found 0x%08x)\n", val); - goto bail; + if (lseek(mFd, 0, SEEK_SET) != 0) { + LOGW("seek to start failed: %s", strerror(errno)); + free(scanBuf); + return false; + } + + ssize_t actual = TEMP_FAILURE_RETRY(read(mFd, scanBuf, sizeof(int32_t))); + if (actual != (ssize_t) sizeof(int32_t)) { + LOGI("couldn't read first signature from zip archive: %s", strerror(errno)); + free(scanBuf); + return false; + } + + { + unsigned int header = get4LE(scanBuf); + if (header == kEOCDSignature) { + LOGI("Found Zip archive, but it looks empty\n"); + free(scanBuf); + return false; + } else if (header != kLFHSignature) { + LOGV("Not a Zip archive (found 0x%08x)\n", val); + free(scanBuf); + return false; + } } /* - * Find the EOCD. We'll find it immediately unless they have a file - * comment. + * Perform the traditional EOCD snipe hunt. + * + * We're searching for the End of Central Directory magic number, + * which appears at the start of the EOCD block. It's followed by + * 18 bytes of EOCD stuff and up to 64KB of archive comment. We + * need to read the last part of the file into a buffer, dig through + * it to find the magic number, parse some values out, and use those + * to determine the extent of the CD. + * + * We start by pulling in the last part of the file. */ - ptr = basePtr + length - kEOCDLen; + off_t searchStart = mFileLength - readAmount; - while (ptr >= basePtr) { - if (*ptr == (kEOCDSignature & 0xff) && get4LE(ptr) == kEOCDSignature) + if (lseek(mFd, searchStart, SEEK_SET) != searchStart) { + LOGW("seek %ld failed: %s\n", (long) searchStart, strerror(errno)); + free(scanBuf); + return false; + } + actual = TEMP_FAILURE_RETRY(read(mFd, scanBuf, readAmount)); + if (actual != (ssize_t) readAmount) { + LOGW("Zip: read %zd failed: %s\n", readAmount, strerror(errno)); + free(scanBuf); + return false; + } + + /* + * Scan backward for the EOCD magic. In an archive without a trailing + * comment, we'll find it on the first try. (We may want to consider + * doing an initial minimal read; if we don't find it, retry with a + * second read as above.) + */ + int i; + for (i = readAmount - kEOCDLen; i >= 0; i--) { + if (scanBuf[i] == 0x50 && get4LE(&scanBuf[i]) == kEOCDSignature) { + LOGV("+++ Found EOCD at buf+%d\n", i); break; - ptr--; + } } - if (ptr < basePtr) { - LOGI("Could not find end-of-central-directory in Zip\n"); - goto bail; + if (i < 0) { + LOGD("Zip: EOCD not found, %s is not zip\n", mFileName); + free(scanBuf); + return false; } + off_t eocdOffset = searchStart + i; + const unsigned char* eocdPtr = scanBuf + i; + + assert(eocdOffset < mFileLength); + /* - * There are two interesting items in the EOCD block: the number of - * entries in the file, and the file offset of the start of the - * central directory. - * - * (There's actually a count of the #of entries in this file, and for - * all files which comprise a spanned archive, but for our purposes - * we're only interested in the current file. Besides, we expect the - * two to be equivalent for our stuff.) + * Grab the CD offset and size, and the number of entries in the + * archive. Verify that they look reasonable. */ - numEntries = get2LE(ptr + kEOCDNumEntries); - cdOffset = get4LE(ptr + kEOCDFileOffset); + unsigned int numEntries = get2LE(eocdPtr + kEOCDNumEntries); + unsigned int dirSize = get4LE(eocdPtr + kEOCDSize); + unsigned int dirOffset = get4LE(eocdPtr + kEOCDFileOffset); + + if ((long long) dirOffset + (long long) dirSize > (long long) eocdOffset) { + LOGW("bad offsets (dir %ld, size %u, eocd %ld)\n", + (long) dirOffset, dirSize, (long) eocdOffset); + free(scanBuf); + return false; + } + if (numEntries == 0) { + LOGW("empty archive?\n"); + free(scanBuf); + return false; + } - /* valid offsets are [0,EOCD] */ - unsigned int maxOffset; - maxOffset = (ptr - basePtr) +1; + LOGV("+++ numEntries=%d dirSize=%d dirOffset=%d\n", + numEntries, dirSize, dirOffset); - LOGV("+++ numEntries=%d cdOffset=%d\n", numEntries, cdOffset); - if (numEntries == 0 || cdOffset >= length) { - LOGW("Invalid entries=%d offset=%d (len=%zd)\n", - numEntries, cdOffset, length); - goto bail; + mDirectoryMap = new FileMap(); + if (mDirectoryMap == NULL) { + LOGW("Unable to create directory map: %s", strerror(errno)); + free(scanBuf); + return false; } + if (!mDirectoryMap->create(mFileName, mFd, dirOffset, dirSize, true)) { + LOGW("Unable to map '%s' (%zd to %zd): %s\n", mFileName, + dirOffset, dirOffset + dirSize, strerror(errno)); + free(scanBuf); + return false; + } + + mNumEntries = numEntries; + mDirectoryOffset = dirOffset; + + return true; +} + +bool ZipFileRO::parseZipArchive(void) +{ + bool result = false; + const unsigned char* cdPtr = (const unsigned char*) mDirectoryMap->getDataPtr(); + size_t cdLength = mDirectoryMap->getDataLength(); + int numEntries = mNumEntries; + /* * Create hash table. We have a minimum 75% load factor, possibly as * low as 50% after we round off to a power of 2. */ - mNumEntries = numEntries; - mHashTableSize = roundUpPower2(1 + ((numEntries * 4) / 3)); - mHashTable = (HashEntry*) calloc(1, sizeof(HashEntry) * mHashTableSize); + mHashTableSize = roundUpPower2(1 + (numEntries * 4) / 3); + mHashTable = (HashEntry*) calloc(mHashTableSize, sizeof(HashEntry)); /* * Walk through the central directory, adding entries to the hash * table. */ - ptr = basePtr + cdOffset; - for (i = 0; i < numEntries; i++) { - unsigned int fileNameLen, extraLen, commentLen, localHdrOffset; - const unsigned char* localHdr; - unsigned int hash; - + const unsigned char* ptr = cdPtr; + for (int i = 0; i < numEntries; i++) { if (get4LE(ptr) != kCDESignature) { LOGW("Missed a central dir sig (at %d)\n", i); goto bail; } - if (ptr + kCDELen > basePtr + length) { + if (ptr + kCDELen > cdPtr + cdLength) { LOGW("Ran off the end (at %d)\n", i); goto bail; } - localHdrOffset = get4LE(ptr + kCDELocalOffset); - CHECK_OFFSET(localHdrOffset); + long localHdrOffset = (long) get4LE(ptr + kCDELocalOffset); + if (localHdrOffset >= mDirectoryOffset) { + LOGW("bad LFH offset %ld at entry %d\n", localHdrOffset, i); + goto bail; + } + + unsigned int fileNameLen, extraLen, commentLen, hash; + fileNameLen = get2LE(ptr + kCDENameLen); extraLen = get2LE(ptr + kCDEExtraLen); commentLen = get2LE(ptr + kCDECommentLen); - //LOGV("+++ %d: localHdr=%d fnl=%d el=%d cl=%d\n", - // i, localHdrOffset, fileNameLen, extraLen, commentLen); - //LOGV(" '%.*s'\n", fileNameLen, ptr + kCDELen); - /* add the CDE filename to the hash table */ hash = computeHash((const char*)ptr + kCDELen, fileNameLen); addToHash((const char*)ptr + kCDELen, fileNameLen, hash); - localHdr = basePtr + localHdrOffset; - if (get4LE(localHdr) != kLFHSignature) { - LOGW("Bad offset to local header: %d (at %d)\n", - localHdrOffset, i); + ptr += kCDELen + fileNameLen + extraLen + commentLen; + if ((size_t)(ptr - cdPtr) > cdLength) { + LOGW("bad CD advance (%d vs %zd) at entry %d\n", + (int) (ptr - cdPtr), cdLength, i); goto bail; } - - ptr += kCDELen + fileNameLen + extraLen + commentLen; - CHECK_OFFSET(ptr - basePtr); } - + LOGV("+++ zip good scan %d entries\n", numEntries); result = true; bail: return result; -#undef CHECK_OFFSET } - /* * Simple string hash function for non-null-terminated strings. */ @@ -315,7 +399,7 @@ ZipEntryRO ZipFileRO::findEntryByName(const char* fileName) const memcmp(mHashTable[ent].name, fileName, nameLen) == 0) { /* match */ - return (ZipEntryRO) (ent + kZipEntryAdj); + return (ZipEntryRO)(long)(ent + kZipEntryAdj); } ent = (ent + 1) & (mHashTableSize-1); @@ -354,20 +438,24 @@ ZipEntryRO ZipFileRO::findEntryByIndex(int idx) const * Returns "false" if the offsets to the fields or the contents of the fields * appear to be bogus. */ -bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, long* pUncompLen, - long* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) const +bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, + size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) const { - int ent = entryToIndex(entry); + bool ret = false; + + const int ent = entryToIndex(entry); if (ent < 0) return false; + HashEntry hashEntry = mHashTable[ent]; + /* * Recover the start of the central directory entry from the filename - * pointer. + * pointer. The filename is the first entry past the fixed-size data, + * so we can just subtract back from that. */ - const unsigned char* basePtr = (const unsigned char*)mFileMap->getDataPtr(); - const unsigned char* ptr = (const unsigned char*) mHashTable[ent].name; - size_t zipLength = mFileMap->getDataLength(); + const unsigned char* ptr = (const unsigned char*) hashEntry.name; + off_t cdOffset = mDirectoryOffset; ptr -= kCDELen; @@ -380,48 +468,78 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, long* pUncompLen, if (pCrc32 != NULL) *pCrc32 = get4LE(ptr + kCDECRC); + size_t compLen = get4LE(ptr + kCDECompLen); + if (pCompLen != NULL) + *pCompLen = compLen; + size_t uncompLen = get4LE(ptr + kCDEUncompLen); + if (pUncompLen != NULL) + *pUncompLen = uncompLen; + /* - * We need to make sure that the lengths are not so large that somebody - * trying to map the compressed or uncompressed data runs off the end - * of the mapped region. + * If requested, determine the offset of the start of the data. All we + * have is the offset to the Local File Header, which is variable size, + * so we have to read the contents of the struct to figure out where + * the actual data starts. + * + * We also need to make sure that the lengths are not so large that + * somebody trying to map the compressed or uncompressed data runs + * off the end of the mapped region. + * + * Note we don't verify compLen/uncompLen if they don't request the + * dataOffset, because dataOffset is expensive to determine. However, + * if they don't have the file offset, they're not likely to be doing + * anything with the contents. */ - unsigned long localHdrOffset = get4LE(ptr + kCDELocalOffset); - if (localHdrOffset + kLFHLen >= zipLength) { - LOGE("ERROR: bad local hdr offset in zip\n"); - return false; - } - const unsigned char* localHdr = basePtr + localHdrOffset; - off_t dataOffset = localHdrOffset + kLFHLen - + get2LE(localHdr + kLFHNameLen) + get2LE(localHdr + kLFHExtraLen); - if ((unsigned long) dataOffset >= zipLength) { - LOGE("ERROR: bad data offset in zip\n"); - return false; - } + if (pOffset != NULL) { + long localHdrOffset = get4LE(ptr + kCDELocalOffset); + if (localHdrOffset + kLFHLen >= cdOffset) { + LOGE("ERROR: bad local hdr offset in zip\n"); + return false; + } - if (pCompLen != NULL) { - *pCompLen = get4LE(ptr + kCDECompLen); - if (*pCompLen < 0 || (size_t)(dataOffset + *pCompLen) >= zipLength) { - LOGE("ERROR: bad compressed length in zip\n"); + unsigned char lfhBuf[kLFHLen]; + if (lseek(mFd, localHdrOffset, SEEK_SET) != localHdrOffset) { + LOGW("failed seeking to lfh at offset %ld\n", localHdrOffset); return false; } - } - if (pUncompLen != NULL) { - *pUncompLen = get4LE(ptr + kCDEUncompLen); - if (*pUncompLen < 0) { - LOGE("ERROR: negative uncompressed length in zip\n"); + ssize_t actual = + TEMP_FAILURE_RETRY(read(mFd, lfhBuf, sizeof(lfhBuf))); + if (actual != sizeof(lfhBuf)) { + LOGW("failed reading lfh from offset %ld\n", localHdrOffset); + return false; + } + + if (get4LE(lfhBuf) != kLFHSignature) { + LOGW("didn't find signature at start of lfh, offset=%ld\n", + localHdrOffset); return false; } + + off_t dataOffset = localHdrOffset + kLFHLen + + get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen); + if (dataOffset >= cdOffset) { + LOGW("bad data offset %ld in zip\n", (long) dataOffset); + return false; + } + + /* check lengths */ + if ((off_t)(dataOffset + compLen) > cdOffset) { + LOGW("bad compressed length in zip (%ld + %zd > %ld)\n", + (long) dataOffset, compLen, (long) cdOffset); + return false; + } + if (method == kCompressStored && - (size_t)(dataOffset + *pUncompLen) >= zipLength) + (off_t)(dataOffset + uncompLen) > cdOffset) { - LOGE("ERROR: bad uncompressed length in zip\n"); + LOGE("ERROR: bad uncompressed length in zip (%ld + %zd > %ld)\n", + (long) dataOffset, uncompLen, (long) cdOffset); return false; } - } - if (pOffset != NULL) { *pOffset = dataOffset; } + return true; } @@ -457,14 +575,14 @@ FileMap* ZipFileRO::createEntryFileMap(ZipEntryRO entry) const */ FileMap* newMap; - long compLen; + size_t compLen; off_t offset; if (!getEntryInfo(entry, NULL, NULL, &compLen, &offset, NULL, NULL)) return NULL; newMap = new FileMap(); - if (!newMap->create(mFileMap->getFileName(), mFd, offset, compLen, true)) { + if (!newMap->create(mFileName, mFd, offset, compLen, true)) { newMap->release(); return NULL; } @@ -480,19 +598,26 @@ FileMap* ZipFileRO::createEntryFileMap(ZipEntryRO entry) const */ bool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer) const { - const int kSequentialMin = 32768; + const size_t kSequentialMin = 32768; bool result = false; int ent = entryToIndex(entry); if (ent < 0) return -1; - const unsigned char* basePtr = (const unsigned char*)mFileMap->getDataPtr(); int method; - long uncompLen, compLen; + size_t uncompLen, compLen; off_t offset; + const unsigned char* ptr; getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL); + FileMap* file = createEntryFileMap(entry); + if (file == NULL) { + goto bail; + } + + ptr = (const unsigned char*) file->getDataPtr(); + /* * Experiment with madvise hint. When we want to uncompress a file, * we pull some stuff out of the central dir entry and then hit a @@ -507,17 +632,17 @@ bool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer) const * pair of system calls are negated by a reduction in page faults. */ if (compLen > kSequentialMin) - mFileMap->advise(FileMap::SEQUENTIAL); + file->advise(FileMap::SEQUENTIAL); if (method == kCompressStored) { - memcpy(buffer, basePtr + offset, uncompLen); + memcpy(buffer, ptr, uncompLen); } else { - if (!inflateBuffer(buffer, basePtr + offset, uncompLen, compLen)) + if (!inflateBuffer(buffer, ptr, uncompLen, compLen)) goto bail; } if (compLen > kSequentialMin) - mFileMap->advise(FileMap::NORMAL); + file->advise(FileMap::NORMAL); result = true; @@ -537,29 +662,34 @@ bool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const if (ent < 0) return -1; - const unsigned char* basePtr = (const unsigned char*)mFileMap->getDataPtr(); int method; - long uncompLen, compLen; + size_t uncompLen, compLen; off_t offset; + const unsigned char* ptr; getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL); - if (method == kCompressStored) { - ssize_t actual; + const FileMap* file = createEntryFileMap(entry); + if (file == NULL) { + goto bail; + } + + ptr = (const unsigned char*) file->getDataPtr(); - actual = write(fd, basePtr + offset, uncompLen); + if (method == kCompressStored) { + ssize_t actual = write(fd, ptr, uncompLen); if (actual < 0) { LOGE("Write failed: %s\n", strerror(errno)); goto bail; - } else if (actual != uncompLen) { - LOGE("Partial write during uncompress (%d of %ld)\n", - (int)actual, uncompLen); + } else if ((size_t) actual != uncompLen) { + LOGE("Partial write during uncompress (%zd of %zd)\n", + actual, uncompLen); goto bail; } else { LOGI("+++ successful write\n"); } } else { - if (!inflateBuffer(fd, basePtr+offset, uncompLen, compLen)) + if (!inflateBuffer(fd, ptr, uncompLen, compLen)) goto bail; } @@ -573,7 +703,7 @@ bail: * Uncompress "deflate" data from one buffer to another. */ /*static*/ bool ZipFileRO::inflateBuffer(void* outBuf, const void* inBuf, - long uncompLen, long compLen) + size_t uncompLen, size_t compLen) { bool result = false; z_stream zstream; @@ -582,7 +712,7 @@ bail: /* * Initialize the zlib stream struct. */ - memset(&zstream, 0, sizeof(zstream)); + memset(&zstream, 0, sizeof(zstream)); zstream.zalloc = Z_NULL; zstream.zfree = Z_NULL; zstream.opaque = Z_NULL; @@ -592,10 +722,10 @@ bail: zstream.avail_out = uncompLen; zstream.data_type = Z_UNKNOWN; - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ + /* + * Use the undocumented "negative window bits" feature to tell zlib + * that there's no zlib header waiting for it. + */ zerr = inflateInit2(&zstream, -MAX_WBITS); if (zerr != Z_OK) { if (zerr == Z_VERSION_ERROR) { @@ -619,8 +749,8 @@ bail: } /* paranoia */ - if ((long) zstream.total_out != uncompLen) { - LOGW("Size mismatch on inflated file (%ld vs %ld)\n", + if (zstream.total_out != uncompLen) { + LOGW("Size mismatch on inflated file (%ld vs %zd)\n", zstream.total_out, uncompLen); goto z_bail; } @@ -638,10 +768,10 @@ bail: * Uncompress "deflate" data from one buffer to an open file descriptor. */ /*static*/ bool ZipFileRO::inflateBuffer(int fd, const void* inBuf, - long uncompLen, long compLen) + size_t uncompLen, size_t compLen) { bool result = false; - const int kWriteBufSize = 32768; + const size_t kWriteBufSize = 32768; unsigned char writeBuf[kWriteBufSize]; z_stream zstream; int zerr; @@ -649,7 +779,7 @@ bail: /* * Initialize the zlib stream struct. */ - memset(&zstream, 0, sizeof(zstream)); + memset(&zstream, 0, sizeof(zstream)); zstream.zalloc = Z_NULL; zstream.zfree = Z_NULL; zstream.opaque = Z_NULL; @@ -659,10 +789,10 @@ bail: zstream.avail_out = sizeof(writeBuf); zstream.data_type = Z_UNKNOWN; - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ + /* + * Use the undocumented "negative window bits" feature to tell zlib + * that there's no zlib header waiting for it. + */ zerr = inflateInit2(&zstream, -MAX_WBITS); if (zerr != Z_OK) { if (zerr == Z_VERSION_ERROR) { @@ -708,8 +838,8 @@ bail: assert(zerr == Z_STREAM_END); /* other errors should've been caught */ /* paranoia */ - if ((long) zstream.total_out != uncompLen) { - LOGW("Size mismatch on inflated file (%ld vs %ld)\n", + if (zstream.total_out != uncompLen) { + LOGW("Size mismatch on inflated file (%ld vs %zd)\n", zstream.total_out, uncompLen); goto z_bail; } diff --git a/location/java/android/location/Address.java b/location/java/android/location/Address.java index ac275c677c76f184e09b5a8d374a81759d9fa0af..b152f48a3e9e0dfcfc03c155840cc314a7d9ce26 100644 --- a/location/java/android/location/Address.java +++ b/location/java/android/location/Address.java @@ -500,7 +500,10 @@ public class Address implements Parcelable { a.mAdminArea = in.readString(); a.mSubAdminArea = in.readString(); a.mLocality = in.readString(); + a.mSubLocality = in.readString(); a.mThoroughfare = in.readString(); + a.mSubThoroughfare = in.readString(); + a.mPremises = in.readString(); a.mPostalCode = in.readString(); a.mCountryCode = in.readString(); a.mCountryName = in.readString(); @@ -544,7 +547,10 @@ public class Address implements Parcelable { parcel.writeString(mAdminArea); parcel.writeString(mSubAdminArea); parcel.writeString(mLocality); + parcel.writeString(mSubLocality); parcel.writeString(mThoroughfare); + parcel.writeString(mSubThoroughfare); + parcel.writeString(mPremises); parcel.writeString(mPostalCode); parcel.writeString(mCountryCode); parcel.writeString(mCountryName); diff --git a/location/java/android/location/Criteria.java b/location/java/android/location/Criteria.java index 9d258d061d92ecde8e21e78b9f78a9483368f859..647a9df2c38f2ac21b01c2c69ac8de45013aa7a8 100644 --- a/location/java/android/location/Criteria.java +++ b/location/java/android/location/Criteria.java @@ -57,9 +57,72 @@ public class Criteria implements Parcelable { */ public static final int ACCURACY_COARSE = 2; - private int mAccuracy = NO_REQUIREMENT; + /** + * A constant indicating a low location accuracy requirement + * - may be used for horizontal, altitude, speed or bearing accuracy. + * For horizontal and vertical position this corresponds to an accuracy + * greater than 500 meters. For speed and bearing, this corresponds + * to greater than 5 meters/second velocity and 10 degrees for bearing. + */ + public static final int ACCURACY_LOW = 1; + + /** + * A constant indicating a medium accuracy requirement + * - may be used for horizontal, altitude, speed or bearing accuracy. + * For horizontal position this corresponds to an accuracy of between + * 100 and 500 meters, and between 200 and 500 meters for vertical accuracy. + * For speed and bearing, this corresponds to 1 meter/second to 5 meters/second + * velocity and and between 5 and 10 degrees for bearing. + */ + public static final int ACCURACY_MEDIUM = 2; + + /** + * a constant indicating a high accuracy requirement + * - may be used for horizontal, altitude, speed or bearing accuracy. + * For horizontal and vertical position this corresponds to an accuracy + * less than 100 meters. For speed and bearing, this corresponds + * to less 1 meter/second velocity less than 5 degrees for bearing. + */ + public static final int ACCURACY_HIGH = 3; + + /** + * a constant indicating the best accuracy that is available for any + * location provider available + * - may be used for horizontal, altitude, speed or bearing accuracy. + */ + public static final int ACCURACY_BEST = 4; + + /** + * A constant indicating horizontal accuracy has the top priority + */ + public static final int HORIZONTAL_ACCURACY_PRIORITY = 1; + + /** + * A constant indicating altitude accuracy has the top priority + */ + public static final int VERTICAL_ACCURACY_PRIORITY = 2; + + /** + * A constant indicating speed accuracy has the top priority + */ + public static final int SPEED_ACCURACY_PRIORITY = 3; + + /** + * A constant indicating bearing accuracy has the top priority + */ + public static final int BEARING_ACCURACY_PRIORITY = 4; + + /** + * A constant indicating power requirement has the top priority + */ + public static final int POWER_REQUIREMENT_PRIORITY = 5; + + private int mHorizontalAccuracy = NO_REQUIREMENT; + private int mVerticalAccuracy = NO_REQUIREMENT; + private int mSpeedAccuracy = NO_REQUIREMENT; + private int mBearingAccuracy = NO_REQUIREMENT; + private int mPriority = HORIZONTAL_ACCURACY_PRIORITY; private int mPowerRequirement = NO_REQUIREMENT; -// private int mPreferredResponseTime = NO_REQUIREMENT; private boolean mAltitudeRequired = false; private boolean mBearingRequired = false; private boolean mSpeedRequired = false; @@ -77,29 +140,162 @@ public class Criteria implements Parcelable { * Constructs a new Criteria object that is a copy of the given criteria. */ public Criteria(Criteria criteria) { - mAccuracy = criteria.mAccuracy; + mHorizontalAccuracy = criteria.mHorizontalAccuracy; + mVerticalAccuracy = criteria.mVerticalAccuracy; + mSpeedAccuracy = criteria.mSpeedAccuracy; + mBearingAccuracy = criteria.mBearingAccuracy; + mPriority = criteria.mPriority; mPowerRequirement = criteria.mPowerRequirement; -// mPreferredResponseTime = criteria.mPreferredResponseTime; mAltitudeRequired = criteria.mAltitudeRequired; mBearingRequired = criteria.mBearingRequired; mSpeedRequired = criteria.mSpeedRequired; mCostAllowed = criteria.mCostAllowed; } + /** + * Indicates the desired horizontal accuracy (latitude and longitude). + * Accuracy may be {@link #ACCURACY_LOW}, {@link #ACCURACY_MEDIUM}, + * {@link #ACCURACY_HIGH}, {@link #ACCURACY_BEST}, + * More accurate location may consume more power and may take longer. + * + * @throws IllegalArgumentException if accuracy is not one of the supported constants + */ + public void setHorizontalAccuracy(int accuracy) { + if (accuracy < NO_REQUIREMENT || accuracy > ACCURACY_BEST) { + throw new IllegalArgumentException("accuracy=" + accuracy); + } + mHorizontalAccuracy = accuracy; + } + + /** + * Returns a constant indicating the desired horizontal accuracy (latitude and longitude). + * Accuracy may be {@link #ACCURACY_LOW}, {@link #ACCURACY_MEDIUM}, + * {@link #ACCURACY_HIGH}, {@link #ACCURACY_BEST}, + */ + public int getHorizontalAccuracy() { + return mHorizontalAccuracy; + } + + /** + * Indicates the desired vertical accuracy (altitude). + * Accuracy may be {@link #ACCURACY_LOW}, {@link #ACCURACY_MEDIUM}, + * {@link #ACCURACY_HIGH}, {@link #ACCURACY_BEST}, + * More accurate location may consume more power and may take longer. + * + * @throws IllegalArgumentException if accuracy is not one of the supported constants + */ + public void setVerticalAccuracy(int accuracy) { + if (accuracy < NO_REQUIREMENT || accuracy > ACCURACY_BEST) { + throw new IllegalArgumentException("accuracy=" + accuracy); + } + mVerticalAccuracy = accuracy; + } + + /** + * Returns a constant indicating the desired vertical accuracy (altitude). + * Accuracy may be {@link #ACCURACY_LOW}, {@link #ACCURACY_MEDIUM}, + * {@link #ACCURACY_HIGH}, {@link #ACCURACY_BEST}, + */ + public int getVerticalAccuracy() { + return mVerticalAccuracy; + } + + /** + * Indicates the desired speed accuracy. + * Accuracy may be {@link #ACCURACY_LOW}, {@link #ACCURACY_MEDIUM}, + * {@link #ACCURACY_HIGH}, {@link #ACCURACY_BEST}, + * More accurate location may consume more power and may take longer. + * + * @throws IllegalArgumentException if accuracy is not one of the supported constants + */ + public void setSpeedAccuracy(int accuracy) { + if (accuracy < NO_REQUIREMENT || accuracy > ACCURACY_BEST) { + throw new IllegalArgumentException("accuracy=" + accuracy); + } + mSpeedAccuracy = accuracy; + } + + /** + * Returns a constant indicating the desired speed accuracy + * Accuracy may be {@link #ACCURACY_LOW}, {@link #ACCURACY_MEDIUM}, + * {@link #ACCURACY_HIGH}, {@link #ACCURACY_BEST}, + */ + public int getSpeedAccuracy() { + return mSpeedAccuracy; + } + + /** + * Indicates the desired bearing accuracy. + * Accuracy may be {@link #ACCURACY_LOW}, {@link #ACCURACY_MEDIUM}, + * {@link #ACCURACY_HIGH}, {@link #ACCURACY_BEST}, + * More accurate location may consume more power and may take longer. + * + * @throws IllegalArgumentException if accuracy is not one of the supported constants + */ + public void setBearingAccuracy(int accuracy) { + if (accuracy < NO_REQUIREMENT || accuracy > ACCURACY_BEST) { + throw new IllegalArgumentException("accuracy=" + accuracy); + } + mBearingAccuracy = accuracy; + } + + /** + * Returns a constant indicating the desired bearing accuracy. + * Accuracy may be {@link #ACCURACY_LOW}, {@link #ACCURACY_MEDIUM}, + * {@link #ACCURACY_HIGH}, {@link #ACCURACY_BEST}, + */ + public int getBearingAccuracy() { + return mBearingAccuracy; + } + + /** + * Indicates the top priority to optimize for if the criteria parameters are + * found to be in conflict. + * Since a location provider might only be able to optimize for one requirement, + * the other requirements are considered good to have, but not guaranteed. + * This parameter does not override the priorities communicated through the + * preferred accuracy and power consumption parameters. + * If this parameter is not specified and conflicts occur, the location manager + * will use thefollowing default priority (high priority to low priority): + * {@link #HORIZONTAL_ACCURACY_PRIORITY}, {@link #POWER_REQUIREMENT_PRIORITY}, + * {@link #VERTICAL_ACCURACY_PRIORITY}, {@link #SPEED_ACCURACY_PRIORITY}, + * {@link #BEARING_ACCURACY_PRIORITY}. + */ + public void setPreferredPriority(int priority) { + if (priority < HORIZONTAL_ACCURACY_PRIORITY || priority > POWER_REQUIREMENT_PRIORITY) { + throw new IllegalArgumentException("priority=" + priority); + } + mPriority = priority; + } + + /** + * Returns a constant indicating the top priority to optimize for if the + * criteria parameters are found to be in conflict. + * The value can be {@link #HORIZONTAL_ACCURACY_PRIORITY}, + * {@link #VERTICAL_ACCURACY_PRIORITY}, {@link #SPEED_ACCURACY_PRIORITY}, + * {@link #BEARING_ACCURACY_PRIORITY} or {@link #POWER_REQUIREMENT_PRIORITY}. + */ + public int getPriority() { + return mPriority; + } + /** * Indicates the desired accuracy for latitude and longitude. Accuracy * may be {@link #ACCURACY_FINE} if desired location * is fine, else it can be {@link #ACCURACY_COARSE}. - * More accurate location usually consumes more power and may take - * longer. + * More accurate location may consume more power and may take longer. * - * @throws IllegalArgumentException if accuracy is negative + * @throws IllegalArgumentException if accuracy is not one of the supported constants */ public void setAccuracy(int accuracy) { - if (accuracy < NO_REQUIREMENT && accuracy > ACCURACY_COARSE) { + if (accuracy < NO_REQUIREMENT || accuracy > ACCURACY_COARSE) { throw new IllegalArgumentException("accuracy=" + accuracy); } - mAccuracy = accuracy; + if (accuracy == ACCURACY_FINE) { + mHorizontalAccuracy = ACCURACY_BEST; + } else { + mHorizontalAccuracy = ACCURACY_LOW; + } } /** @@ -108,7 +304,11 @@ public class Criteria implements Parcelable { * is fine, else it can be {@link #ACCURACY_COARSE}. */ public int getAccuracy() { - return mAccuracy; + if (mHorizontalAccuracy >= ACCURACY_HIGH) { + return ACCURACY_FINE; + } else { + return ACCURACY_COARSE; + } } /** @@ -131,20 +331,6 @@ public class Criteria implements Parcelable { return mPowerRequirement; } -// /** -// * Indicates the preferred response time of the provider, in milliseconds. -// */ -// public void setPreferredResponseTime(int time) { -// mPreferredResponseTime = time; -// } -// -// /** -// * Returns the preferred response time of the provider, in milliseconds. -// */ -// public int getPreferredResponseTime() { -// return mPreferredResponseTime; -// } - /** * Indicates whether the provider is allowed to incur monetary cost. */ @@ -211,9 +397,12 @@ public class Criteria implements Parcelable { new Parcelable.Creator() { public Criteria createFromParcel(Parcel in) { Criteria c = new Criteria(); - c.mAccuracy = in.readInt(); + c.mHorizontalAccuracy = in.readInt(); + c.mVerticalAccuracy = in.readInt(); + c.mSpeedAccuracy = in.readInt(); + c.mBearingAccuracy = in.readInt(); + c.mPriority = in.readInt(); c.mPowerRequirement = in.readInt(); -// c.mPreferredResponseTime = in.readInt(); c.mAltitudeRequired = in.readInt() != 0; c.mBearingRequired = in.readInt() != 0; c.mSpeedRequired = in.readInt() != 0; @@ -231,9 +420,12 @@ public class Criteria implements Parcelable { } public void writeToParcel(Parcel parcel, int flags) { - parcel.writeInt(mAccuracy); + parcel.writeInt(mHorizontalAccuracy); + parcel.writeInt(mVerticalAccuracy); + parcel.writeInt(mSpeedAccuracy); + parcel.writeInt(mBearingAccuracy); + parcel.writeInt(mPriority); parcel.writeInt(mPowerRequirement); -// parcel.writeInt(mPreferredResponseTime); parcel.writeInt(mAltitudeRequired ? 1 : 0); parcel.writeInt(mBearingRequired ? 1 : 0); parcel.writeInt(mSpeedRequired ? 1 : 0); diff --git a/location/java/android/location/Geocoder.java b/location/java/android/location/Geocoder.java index c325b1b0c3c8c5732df9f21cb5223674677864a6..546bb9d84c7388fe7583f193b4526784eb34857e 100644 --- a/location/java/android/location/Geocoder.java +++ b/location/java/android/location/Geocoder.java @@ -40,7 +40,9 @@ import java.util.List; * * The Geocoder class requires a backend service that is not included in * the core android framework. The Geocoder query methods will return an - * empty list if there no backend service in the platform. + * empty list if there no backend service in the platform. Use the + * isImplemented() method to determine whether a Geocoder implementation + * exists. */ public final class Geocoder { private static final String TAG = "Geocoder"; @@ -48,6 +50,23 @@ public final class Geocoder { private GeocoderParams mParams; private ILocationManager mService; + /** + * Returns true if the Geocoder methods getFromLocation and + * getFromLocationName are implemented. Lack of network + * connectivity may still cause these methods to return null or + * empty lists. + */ + public static Boolean isImplemented() { + IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE); + ILocationManager lm = ILocationManager.Stub.asInterface(b); + try { + return lm.geocoderIsImplemented(); + } catch (RemoteException e) { + Log.e(TAG, "isImplemented: got RemoteException", e); + return false; + } + } + /** * Constructs a Geocoder whose responses will be localized for the * given Locale. diff --git a/location/java/android/location/GeocoderParams.java b/location/java/android/location/GeocoderParams.java index 174fe3e0af2ee20d4506468db054ccfb99859016..8b8e63b2c98af4ec5410683041db3491ddb7495a 100644 --- a/location/java/android/location/GeocoderParams.java +++ b/location/java/android/location/GeocoderParams.java @@ -29,8 +29,6 @@ import java.util.Locale; * as well as the Geocoder client's package name for geocoder server * logging. This information is kept in a separate class to allow for * future expansion of the IGeocodeProvider interface. - * - * @hide */ public class GeocoderParams implements Parcelable { private Locale mLocale; diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java index ce69ac13cde446075977d5faadb3e1a37b506951..4af55a65b0e3ac1eb337057689b5cd639050f5fd 100644 --- a/location/java/android/location/GpsStatus.java +++ b/location/java/android/location/GpsStatus.java @@ -150,15 +150,17 @@ public final class GpsStatus { for (i = 0; i < svCount; i++) { int prn = prns[i] - 1; int prnShift = (1 << prn); - GpsSatellite satellite = mSatellites[prn]; - - satellite.mValid = true; - satellite.mSnr = snrs[i]; - satellite.mElevation = elevations[i]; - satellite.mAzimuth = azimuths[i]; - satellite.mHasEphemeris = ((ephemerisMask & prnShift) != 0); - satellite.mHasAlmanac = ((almanacMask & prnShift) != 0); - satellite.mUsedInFix = ((usedInFixMask & prnShift) != 0); + if (prn >= 0 && prn < mSatellites.length) { + GpsSatellite satellite = mSatellites[prn]; + + satellite.mValid = true; + satellite.mSnr = snrs[i]; + satellite.mElevation = elevations[i]; + satellite.mAzimuth = azimuths[i]; + satellite.mHasEphemeris = ((ephemerisMask & prnShift) != 0); + satellite.mHasAlmanac = ((almanacMask & prnShift) != 0); + satellite.mUsedInFix = ((usedInFixMask & prnShift) != 0); + } } } diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 2c0399eadc159399b7b0c483bbd99d861641b3ad..32d4b274f00ca7e7a5bd34bb5553ebfb0ce32268 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -18,6 +18,7 @@ package android.location; import android.app.PendingIntent; import android.location.Address; +import android.location.Criteria; import android.location.GeocoderParams; import android.location.IGeocodeProvider; import android.location.IGpsStatusListener; @@ -32,13 +33,15 @@ import android.os.Bundle; */ interface ILocationManager { - List getAllProviders(); - List getProviders(boolean enabledOnly); + List getAllProviders(); + List getProviders(in Criteria criteria, boolean enabledOnly); + String getBestProvider(in Criteria criteria, boolean enabledOnly); + boolean providerMeetsCriteria(String provider, in Criteria criteria); - void requestLocationUpdates(String provider, long minTime, float minDistance, - in ILocationListener listener); - void requestLocationUpdatesPI(String provider, long minTime, float minDistance, - in PendingIntent intent); + void requestLocationUpdates(String provider, in Criteria criteria, long minTime, float minDistance, + boolean singleShot, in ILocationListener listener); + void requestLocationUpdatesPI(String provider, in Criteria criteria, long minTime, float minDistance, + boolean singleShot, in PendingIntent intent); void removeUpdates(in ILocationListener listener); void removeUpdatesPI(in PendingIntent intent); @@ -64,6 +67,7 @@ interface ILocationManager // it need not be shared with other providers. void reportLocation(in Location location, boolean passive); + boolean geocoderIsImplemented(); String getFromLocation(double latitude, double longitude, int maxResults, in GeocoderParams params, out List
addrs); String getFromLocationName(String locationName, diff --git a/location/java/android/location/ILocationProvider.aidl b/location/java/android/location/ILocationProvider.aidl index 97b283ca3d1b696a2b0e5d2c0bfcf2dd554f4a07..2b9782a64ddb238d01269461fdb5332b7ff0a958 100644 --- a/location/java/android/location/ILocationProvider.aidl +++ b/location/java/android/location/ILocationProvider.aidl @@ -16,6 +16,7 @@ package android.location; +import android.location.Criteria; import android.location.Location; import android.net.NetworkInfo; import android.os.Bundle; @@ -34,6 +35,7 @@ interface ILocationProvider { boolean supportsSpeed(); boolean supportsBearing(); int getPowerRequirement(); + boolean meetsCriteria(in Criteria criteria); int getAccuracy(); void enable(); void disable(); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 9e4a16b241e6cd93ea4d3db75e62dee50cda461e..7d07e4b222a6e661982e3d2089c998e19b37de67 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -28,8 +28,6 @@ import android.util.Log; import com.android.internal.location.DummyLocationProvider; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -117,6 +115,37 @@ public class LocationManager { */ public static final String KEY_LOCATION_CHANGED = "location"; + /** + * Broadcast intent action indicating that the GPS has either been + * enabled or disabled. An intent extra provides this state as a boolean, + * where {@code true} means enabled. + * @see #EXTRA_GPS_ENABLED + * + * {@hide} + */ + public static final String GPS_ENABLED_CHANGE_ACTION = + "android.location.GPS_ENABLED_CHANGE"; + + /** + * Broadcast intent action indicating that the GPS has either started or + * stopped receiving GPS fixes. An intent extra provides this state as a + * boolean, where {@code true} means that the GPS is actively receiving fixes. + * @see #EXTRA_GPS_ENABLED + * + * {@hide} + */ + public static final String GPS_FIX_CHANGE_ACTION = + "android.location.GPS_FIX_CHANGE"; + + /** + * The lookup key for a boolean that indicates whether GPS is enabled or + * disabled. {@code true} means GPS is enabled. Retrieve it with + * {@link android.content.Intent#getBooleanExtra(String,boolean)}. + * + * {@hide} + */ + public static final String EXTRA_GPS_ENABLED = "enabled"; + // Map from LocationListeners to their associated ListenerTransport objects private HashMap mListeners = new HashMap(); @@ -218,15 +247,12 @@ public class LocationManager { * factory Context.getSystemService. */ public LocationManager(ILocationManager service) { - if (false) { - Log.d(TAG, "Constructor: service = " + service); - } mService = service; } private LocationProvider createProvider(String name, Bundle info) { DummyLocationProvider provider = - new DummyLocationProvider(name); + new DummyLocationProvider(name, mService); provider.setRequiresNetwork(info.getBoolean("network")); provider.setRequiresSatellite(info.getBoolean("satellite")); provider.setRequiresCell(info.getBoolean("cell")); @@ -268,7 +294,7 @@ public class LocationManager { */ public List getProviders(boolean enabledOnly) { try { - return mService.getProviders(enabledOnly); + return mService.getProviders(null, enabledOnly); } catch (RemoteException ex) { Log.e(TAG, "getProviders: RemoteException", ex); } @@ -313,173 +339,15 @@ public class LocationManager { * @return list of Strings containing names of the providers */ public List getProviders(Criteria criteria, boolean enabledOnly) { - List goodProviders = Collections.emptyList(); - List providers = getProviders(enabledOnly); - for (String providerName : providers) { - LocationProvider provider = getProvider(providerName); - if (provider != null && provider.meetsCriteria(criteria)) { - if (goodProviders.isEmpty()) { - goodProviders = new ArrayList(); - } - goodProviders.add(providerName); - } - } - return goodProviders; - } - - /** - * Returns the next looser power requirement, in the sequence: - * - * POWER_LOW -> POWER_MEDIUM -> POWER_HIGH -> NO_REQUIREMENT - */ - private int nextPower(int power) { - switch (power) { - case Criteria.POWER_LOW: - return Criteria.POWER_MEDIUM; - case Criteria.POWER_MEDIUM: - return Criteria.POWER_HIGH; - case Criteria.POWER_HIGH: - return Criteria.NO_REQUIREMENT; - case Criteria.NO_REQUIREMENT: - default: - return Criteria.NO_REQUIREMENT; - } - } - - /** - * Returns the next looser accuracy requirement, in the sequence: - * - * ACCURACY_FINE -> ACCURACY_APPROXIMATE-> NO_REQUIREMENT - */ - private int nextAccuracy(int accuracy) { - if (accuracy == Criteria.ACCURACY_FINE) { - return Criteria.ACCURACY_COARSE; - } else { - return Criteria.NO_REQUIREMENT; - } - } - - private abstract class LpComparator implements Comparator { - - public int compare(int a1, int a2) { - if (a1 < a2) { - return -1; - } else if (a1 > a2) { - return 1; - } else { - return 0; - } + if (criteria == null) { + throw new IllegalArgumentException("criteria==null"); } - - public int compare(float a1, float a2) { - if (a1 < a2) { - return -1; - } else if (a1 > a2) { - return 1; - } else { - return 0; - } - } - } - - private class LpPowerComparator extends LpComparator { - public int compare(LocationProvider l1, LocationProvider l2) { - int a1 = l1.getPowerRequirement(); - int a2 = l2.getPowerRequirement(); - return compare(a1, a2); // Smaller is better - } - - public boolean equals(LocationProvider l1, LocationProvider l2) { - int a1 = l1.getPowerRequirement(); - int a2 = l2.getPowerRequirement(); - return a1 == a2; - } - } - - private class LpAccuracyComparator extends LpComparator { - public int compare(LocationProvider l1, LocationProvider l2) { - int a1 = l1.getAccuracy(); - int a2 = l2.getAccuracy(); - return compare(a1, a2); // Smaller is better - } - - public boolean equals(LocationProvider l1, LocationProvider l2) { - int a1 = l1.getAccuracy(); - int a2 = l2.getAccuracy(); - return a1 == a2; - } - } - - private class LpCapabilityComparator extends LpComparator { - - private static final int ALTITUDE_SCORE = 4; - private static final int BEARING_SCORE = 4; - private static final int SPEED_SCORE = 4; - - private int score(LocationProvider p) { - return (p.supportsAltitude() ? ALTITUDE_SCORE : 0) + - (p.supportsBearing() ? BEARING_SCORE : 0) + - (p.supportsSpeed() ? SPEED_SCORE : 0); - } - - public int compare(LocationProvider l1, LocationProvider l2) { - int a1 = score(l1); - int a2 = score(l2); - return compare(-a1, -a2); // Bigger is better - } - - public boolean equals(LocationProvider l1, LocationProvider l2) { - int a1 = score(l1); - int a2 = score(l2); - return a1 == a2; - } - } - - private LocationProvider best(List providerNames) { - List providers = new ArrayList(providerNames.size()); - for (String name : providerNames) { - providers.add(getProvider(name)); - } - - if (providers.size() < 2) { - return providers.get(0); - } - - // First, sort by power requirement - Collections.sort(providers, new LpPowerComparator()); - int power = providers.get(0).getPowerRequirement(); - if (power < providers.get(1).getPowerRequirement()) { - return providers.get(0); - } - - int idx, size; - - List tmp = new ArrayList(); - idx = 0; - size = providers.size(); - while ((idx < size) && (providers.get(idx).getPowerRequirement() == power)) { - tmp.add(providers.get(idx)); - idx++; - } - - // Next, sort by accuracy - Collections.sort(tmp, new LpAccuracyComparator()); - int acc = tmp.get(0).getAccuracy(); - if (acc < tmp.get(1).getAccuracy()) { - return tmp.get(0); - } - - List tmp2 = new ArrayList(); - idx = 0; - size = tmp.size(); - while ((idx < size) && (tmp.get(idx).getAccuracy() == acc)) { - tmp2.add(tmp.get(idx)); - idx++; + try { + return mService.getProviders(criteria, enabledOnly); + } catch (RemoteException ex) { + Log.e(TAG, "getProviders: RemoteException", ex); } - - // Finally, sort by capability "score" - Collections.sort(tmp2, new LpCapabilityComparator()); - return tmp2.get(0); + return null; } /** @@ -505,72 +373,14 @@ public class LocationManager { * @return name of the provider that best matches the requirements */ public String getBestProvider(Criteria criteria, boolean enabledOnly) { - List goodProviders = getProviders(criteria, enabledOnly); - if (!goodProviders.isEmpty()) { - return best(goodProviders).getName(); - } - - // Make a copy of the criteria that we can modify - criteria = new Criteria(criteria); - - // Loosen power requirement - int power = criteria.getPowerRequirement(); - while (goodProviders.isEmpty() && (power != Criteria.NO_REQUIREMENT)) { - power = nextPower(power); - criteria.setPowerRequirement(power); - goodProviders = getProviders(criteria, enabledOnly); + if (criteria == null) { + throw new IllegalArgumentException("criteria==null"); } - if (!goodProviders.isEmpty()) { - return best(goodProviders).getName(); - } - -// // Loosen response time requirement -// int responseTime = criteria.getPreferredResponseTime(); -// while (goodProviders.isEmpty() && -// (responseTime != Criteria.NO_REQUIREMENT)) { -// responseTime += 1000; -// if (responseTime > 60000) { -// responseTime = Criteria.NO_REQUIREMENT; -// } -// criteria.setPreferredResponseTime(responseTime); -// goodProviders = getProviders(criteria); -// } -// if (!goodProviders.isEmpty()) { -// return best(goodProviders); -// } - - // Loosen accuracy requirement - int accuracy = criteria.getAccuracy(); - while (goodProviders.isEmpty() && (accuracy != Criteria.NO_REQUIREMENT)) { - accuracy = nextAccuracy(accuracy); - criteria.setAccuracy(accuracy); - goodProviders = getProviders(criteria, enabledOnly); - } - if (!goodProviders.isEmpty()) { - return best(goodProviders).getName(); - } - - // Remove bearing requirement - criteria.setBearingRequired(false); - goodProviders = getProviders(criteria, enabledOnly); - if (!goodProviders.isEmpty()) { - return best(goodProviders).getName(); - } - - // Remove speed requirement - criteria.setSpeedRequired(false); - goodProviders = getProviders(criteria, enabledOnly); - if (!goodProviders.isEmpty()) { - return best(goodProviders).getName(); - } - - // Remove altitude requirement - criteria.setAltitudeRequired(false); - goodProviders = getProviders(criteria, enabledOnly); - if (!goodProviders.isEmpty()) { - return best(goodProviders).getName(); + try { + return mService.getBestProvider(criteria, enabledOnly); + } catch (RemoteException ex) { + Log.e(TAG, "getBestProvider: RemoteException", ex); } - return null; } @@ -627,7 +437,7 @@ public class LocationManager { if (listener == null) { throw new IllegalArgumentException("listener==null"); } - _requestLocationUpdates(provider, minTime, minDistance, listener, null); + _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, null); } /** @@ -670,10 +480,10 @@ public class LocationManager { * each location update * @param looper a Looper object whose message queue will be used to * implement the callback mechanism. + * If looper is null then the callbacks will be called on the main thread. * * @throws IllegalArgumentException if provider is null or doesn't exist * @throws IllegalArgumentException if listener is null - * @throws IllegalArgumentException if looper is null * @throws SecurityException if no suitable permission is present for the provider. */ public void requestLocationUpdates(String provider, @@ -685,15 +495,70 @@ public class LocationManager { if (listener == null) { throw new IllegalArgumentException("listener==null"); } - if (looper == null) { - throw new IllegalArgumentException("looper==null"); + _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, looper); + } + + /** + * Registers the current activity to be notified periodically based on + * the specified criteria. Periodically, the supplied LocationListener will + * be called with the current Location or with status updates. + * + *

It may take a while to receive the most recent location. If + * an immediate location is required, applications may use the + * {@link #getLastKnownLocation(String)} method. + * + *

In case the provider is disabled by the user, updates will stop, + * and the {@link LocationListener#onProviderDisabled(String)} + * method will be called. As soon as the provider is enabled again, + * the {@link LocationListener#onProviderEnabled(String)} method will + * be called and location updates will start again. + * + *

The frequency of notification may be controlled using the + * minTime and minDistance parameters. If minTime is greater than 0, + * the LocationManager could potentially rest for minTime milliseconds + * between location updates to conserve power. If minDistance is greater than 0, + * a location will only be broadcasted if the device moves by minDistance meters. + * To obtain notifications as frequently as possible, set both parameters to 0. + * + *

Background services should be careful about setting a sufficiently high + * minTime so that the device doesn't consume too much power by keeping the + * GPS or wireless radios on all the time. In particular, values under 60000ms + * are not recommended. + * + *

The supplied Looper is used to implement the callback mechanism. + * + * @param minTime the minimum time interval for notifications, in + * milliseconds. This field is only used as a hint to conserve power, and actual + * time between location updates may be greater or lesser than this value. + * @param minDistance the minimum distance interval for notifications, + * in meters + * @param criteria contains parameters for the location manager to choose the + * appropriate provider and parameters to compute the location + * @param listener a {#link LocationListener} whose + * {@link LocationListener#onLocationChanged} method will be called for + * each location update + * @param looper a Looper object whose message queue will be used to + * implement the callback mechanism. + * If looper is null then the callbacks will be called on the main thread. + * + * @throws IllegalArgumentException if criteria is null + * @throws IllegalArgumentException if listener is null + * @throws SecurityException if no suitable permission is present to access + * the location services. + */ + public void requestLocationUpdates(long minTime, float minDistance, + Criteria criteria, LocationListener listener, Looper looper) { + if (criteria == null) { + throw new IllegalArgumentException("criteria==null"); } - _requestLocationUpdates(provider, minTime, minDistance, listener, looper); + if (listener == null) { + throw new IllegalArgumentException("listener==null"); + } + _requestLocationUpdates(null, criteria, minTime, minDistance, false, listener, looper); } - private void _requestLocationUpdates(String provider, - long minTime, float minDistance, LocationListener listener, - Looper looper) { + private void _requestLocationUpdates(String provider, Criteria criteria, long minTime, + float minDistance, boolean singleShot, LocationListener listener, Looper looper) { if (minTime < 0L) { minTime = 0L; } @@ -708,7 +573,7 @@ public class LocationManager { transport = new ListenerTransport(listener, looper); } mListeners.put(listener, transport); - mService.requestLocationUpdates(provider, minTime, minDistance, transport); + mService.requestLocationUpdates(provider, criteria, minTime, minDistance, singleShot, transport); } } catch (RemoteException ex) { Log.e(TAG, "requestLocationUpdates: DeadObjectException", ex); @@ -754,7 +619,7 @@ public class LocationManager { * time between location updates may be greater or lesser than this value. * @param minDistance the minimum distance interval for notifications, * in meters - * @param intent a {#link PendingIntet} to be sent for each location update + * @param intent a {#link PendingIntent} to be sent for each location update * * @throws IllegalArgumentException if provider is null or doesn't exist * @throws IllegalArgumentException if intent is null @@ -768,11 +633,67 @@ public class LocationManager { if (intent == null) { throw new IllegalArgumentException("intent==null"); } - _requestLocationUpdates(provider, minTime, minDistance, intent); + _requestLocationUpdates(provider, null, minTime, minDistance, false, intent); } - private void _requestLocationUpdates(String provider, - long minTime, float minDistance, PendingIntent intent) { + /** + * Registers the current activity to be notified periodically based on + * the specified criteria. Periodically, the supplied PendingIntent will + * be broadcast with the current Location or with status updates. + * + *

Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value. + * + *

It may take a while to receive the most recent location. If + * an immediate location is required, applications may use the + * {@link #getLastKnownLocation(String)} method. + * + *

The frequency of notification or new locations may be controlled using the + * minTime and minDistance parameters. If minTime is greater than 0, + * the LocationManager could potentially rest for minTime milliseconds + * between location updates to conserve power. If minDistance is greater than 0, + * a location will only be broadcast if the device moves by minDistance meters. + * To obtain notifications as frequently as possible, set both parameters to 0. + * + *

Background services should be careful about setting a sufficiently high + * minTime so that the device doesn't consume too much power by keeping the + * GPS or wireless radios on all the time. In particular, values under 60000ms + * are not recommended. + * + *

In case the provider is disabled by the user, updates will stop, + * and an intent will be sent with an extra with key KEY_PROVIDER_ENABLED and a boolean value + * of false. If the provider is re-enabled, an intent will be sent with an + * extra with key KEY_PROVIDER_ENABLED and a boolean value of true and location updates will + * start again. + * + *

If the provider's status changes, an intent will be sent with an extra with key + * KEY_STATUS_CHANGED and an integer value indicating the new status. Any extras associated + * with the status update will be sent as well. + * + * @param minTime the minimum time interval for notifications, in + * milliseconds. This field is only used as a hint to conserve power, and actual + * time between location updates may be greater or lesser than this value. + * @param minDistance the minimum distance interval for notifications, + * in meters + * @param criteria contains parameters for the location manager to choose the + * appropriate provider and parameters to compute the location + * @param intent a {#link PendingIntent} to be sent for each location update + * + * @throws IllegalArgumentException if provider is null or doesn't exist + * @throws IllegalArgumentException if intent is null + * @throws SecurityException if no suitable permission is present for the provider. + */ + public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria, PendingIntent intent) { + if (criteria == null) { + throw new IllegalArgumentException("criteria==null"); + } + if (intent == null) { + throw new IllegalArgumentException("intent==null"); + } + _requestLocationUpdates(null, criteria, minTime, minDistance, false, intent); + } + + private void _requestLocationUpdates(String provider, Criteria criteria, + long minTime, float minDistance, boolean singleShot, PendingIntent intent) { if (minTime < 0L) { minTime = 0L; } @@ -781,12 +702,149 @@ public class LocationManager { } try { - mService.requestLocationUpdatesPI(provider, minTime, minDistance, intent); + mService.requestLocationUpdatesPI(provider, criteria, minTime, minDistance, singleShot, intent); } catch (RemoteException ex) { Log.e(TAG, "requestLocationUpdates: RemoteException", ex); } } + /** + * Registers the current activity to be notified periodically by + * the named provider. Periodically, the supplied LocationListener will + * be called with the current Location or with status updates. + * + *

It may take a while to receive the most recent location. If + * an immediate location is required, applications may use the + * {@link #getLastKnownLocation(String)} method. + * + *

In case the provider is disabled by the user, updates will stop, + * and the {@link LocationListener#onProviderDisabled(String)} + * method will be called. As soon as the provider is enabled again, + * the {@link LocationListener#onProviderEnabled(String)} method will + * be called and location updates will start again. + * + *

The supplied Looper is used to implement the callback mechanism. + * + * @param provider the name of the provider with which to register + * @param listener a {#link LocationListener} whose + * {@link LocationListener#onLocationChanged} method will be called for + * each location update + * @param looper a Looper object whose message queue will be used to + * implement the callback mechanism. + * If looper is null then the callbacks will be called on the main thread. + * + * @throws IllegalArgumentException if provider is null or doesn't exist + * @throws IllegalArgumentException if listener is null + * @throws SecurityException if no suitable permission is present for the provider. + */ + public void requestSingleUpdate(String provider, LocationListener listener, Looper looper) { + if (provider == null) { + throw new IllegalArgumentException("provider==null"); + } + if (listener == null) { + throw new IllegalArgumentException("listener==null"); + } + _requestLocationUpdates(provider, null, 0L, 0.0f, true, listener, looper); + } + + /** + * Registers the current activity to be notified periodically based on + * the specified criteria. Periodically, the supplied LocationListener will + * be called with the current Location or with status updates. + * + *

It may take a while to receive the most recent location. If + * an immediate location is required, applications may use the + * {@link #getLastKnownLocation(String)} method. + * + *

In case the provider is disabled by the user, updates will stop, + * and the {@link LocationListener#onProviderDisabled(String)} + * method will be called. As soon as the provider is enabled again, + * the {@link LocationListener#onProviderEnabled(String)} method will + * be called and location updates will start again. + * + *

The supplied Looper is used to implement the callback mechanism. + * + * @param criteria contains parameters for the location manager to choose the + * appropriate provider and parameters to compute the location + * @param listener a {#link LocationListener} whose + * {@link LocationListener#onLocationChanged} method will be called for + * each location update + * @param looper a Looper object whose message queue will be used to + * implement the callback mechanism. + * If looper is null then the callbacks will be called on the current thread. + * + * @throws IllegalArgumentException if criteria is null + * @throws IllegalArgumentException if listener is null + * @throws SecurityException if no suitable permission is present to access + * the location services. + */ + public void requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper) { + if (criteria == null) { + throw new IllegalArgumentException("criteria==null"); + } + if (listener == null) { + throw new IllegalArgumentException("listener==null"); + } + _requestLocationUpdates(null, criteria, 0L, 0.0f, true, listener, looper); + } + + /** + * Registers the current activity to be notified periodically by + * the named provider. Periodically, the supplied PendingIntent will + * be broadcast with the current Location or with status updates. + * + *

Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value. + * + *

It may take a while to receive the most recent location. If + * an immediate location is required, applications may use the + * {@link #getLastKnownLocation(String)} method. + * + * @param provider the name of the provider with which to register + * @param intent a {#link PendingIntent} to be sent for the location update + * + * @throws IllegalArgumentException if provider is null or doesn't exist + * @throws IllegalArgumentException if intent is null + * @throws SecurityException if no suitable permission is present for the provider. + */ + public void requestSingleUpdate(String provider, PendingIntent intent) { + if (provider == null) { + throw new IllegalArgumentException("provider==null"); + } + if (intent == null) { + throw new IllegalArgumentException("intent==null"); + } + _requestLocationUpdates(provider, null, 0L, 0.0f, true, intent); + } + + /** + * Registers the current activity to be notified periodically based on + * the specified criteria. Periodically, the supplied PendingIntent will + * be broadcast with the current Location or with status updates. + * + *

Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value. + * + *

It may take a while to receive the most recent location. If + * an immediate location is required, applications may use the + * {@link #getLastKnownLocation(String)} method. + * + * @param criteria contains parameters for the location manager to choose the + * appropriate provider and parameters to compute the location + * @param intent a {#link PendingIntent} to be sent for the location update + * + * @throws IllegalArgumentException if provider is null or doesn't exist + * @throws IllegalArgumentException if intent is null + * @throws SecurityException if no suitable permission is present for the provider. + */ + public void requestSingleUpdate(Criteria criteria, PendingIntent intent) { + if (criteria == null) { + throw new IllegalArgumentException("criteria==null"); + } + if (intent == null) { + throw new IllegalArgumentException("intent==null"); + } + _requestLocationUpdates(null, criteria, 0L, 0.0f, true, intent); + } + /** * Removes any current registration for location updates of the current activity * with the given LocationListener. Following this call, updates will no longer diff --git a/location/java/android/location/LocationProvider.java b/location/java/android/location/LocationProvider.java index bb3e2a58a885c6b07761cb638bdd8b6dcde6403d..8c1658011b554beb747c72c904346b568a5e8d5f 100644 --- a/location/java/android/location/LocationProvider.java +++ b/location/java/android/location/LocationProvider.java @@ -16,6 +16,9 @@ package android.location; +import android.os.RemoteException; +import android.util.Log; + /** * An abstract superclass for location providers. A location provider * provides periodic reports on the geographical location of the @@ -36,7 +39,8 @@ public abstract class LocationProvider { // in the name of a LocationProvider. static final String BAD_CHARS_REGEX = "[^a-zA-Z0-9]"; - private String mName; + private final String mName; + private final ILocationManager mService; public static final int OUT_OF_SERVICE = 0; public static final int TEMPORARILY_UNAVAILABLE = 1; @@ -50,13 +54,13 @@ public abstract class LocationProvider { * * {@hide} */ - public LocationProvider(String name) { + public LocationProvider(String name, ILocationManager service) { if (name.matches(BAD_CHARS_REGEX)) { throw new IllegalArgumentException("name " + name + " contains an illegal character"); } - // Log.d(TAG, "Constructor: name = " + name); mName = name; + mService = service; } /** @@ -71,29 +75,12 @@ public abstract class LocationProvider { * false otherwise. */ public boolean meetsCriteria(Criteria criteria) { - // We do not want to match the special passive provider based on criteria. - if (LocationManager.PASSIVE_PROVIDER.equals(mName)) { - return false; - } - if ((criteria.getAccuracy() != Criteria.NO_REQUIREMENT) && - (criteria.getAccuracy() < getAccuracy())) { - return false; - } - int criteriaPower = criteria.getPowerRequirement(); - if ((criteriaPower != Criteria.NO_REQUIREMENT) && - (criteriaPower < getPowerRequirement())) { - return false; - } - if (criteria.isAltitudeRequired() && !supportsAltitude()) { - return false; - } - if (criteria.isSpeedRequired() && !supportsSpeed()) { - return false; - } - if (criteria.isBearingRequired() && !supportsBearing()) { + try { + return mService.providerMeetsCriteria(mName, criteria); + } catch (RemoteException e) { + Log.e(TAG, "meetsCriteria: RemoteException", e); return false; } - return true; } /** diff --git a/location/java/android/location/provider/GeocodeProvider.java b/location/java/android/location/provider/GeocodeProvider.java index 86376a72d46f6038cb9c539b2be13aa1109afffc..9a587631690ae64fe66ce6cb38ea0e07cfbdca14 100644 --- a/location/java/android/location/provider/GeocodeProvider.java +++ b/location/java/android/location/provider/GeocodeProvider.java @@ -29,8 +29,6 @@ import java.util.List; * outside of the core android platform. * Geocode providers can be implemented as services and return the result of * {@link GeocodeProvider#getBinder()} in its getBinder() method. - * - * @hide */ public abstract class GeocodeProvider { @@ -53,7 +51,7 @@ public abstract class GeocodeProvider { /** * This method is overridden to implement the - * {@link Geocoder#getFromLocation(double, double, int)} method. + * {@link android.location.Geocoder#getFromLocation(double, double, int)} method. * Classes implementing this method should not hold a reference to the params parameter. */ public abstract String onGetFromLocation(double latitude, double longitude, int maxResults, @@ -61,7 +59,7 @@ public abstract class GeocodeProvider { /** * This method is overridden to implement the - * {@link Geocoder#getFromLocationName(String, int, double, double, double, double)} method. + * {@link android.location.Geocoder#getFromLocationName(String, int, double, double, double, double)} method. * Classes implementing this method should not hold a reference to the params parameter. */ public abstract String onGetFromLocationName(String locationName, diff --git a/location/java/android/location/provider/LocationProvider.java b/location/java/android/location/provider/LocationProvider.java index 56cfb332754b1ab34dbbd192541df6bb047e3b21..cf939de50d6148ed630855b024f5561675fdbf10 100644 --- a/location/java/android/location/provider/LocationProvider.java +++ b/location/java/android/location/provider/LocationProvider.java @@ -18,6 +18,7 @@ package android.location.provider; import android.content.Context; import android.net.NetworkInfo; +import android.location.Criteria; import android.location.ILocationManager; import android.location.ILocationProvider; import android.location.Location; @@ -32,8 +33,6 @@ import android.util.Log; * outside of the core android platform. * Location providers can be implemented as services and return the result of * {@link LocationProvider#getBinder()} in its getBinder() method. - * - * @hide */ public abstract class LocationProvider { @@ -75,6 +74,10 @@ public abstract class LocationProvider { return LocationProvider.this.onGetPowerRequirement(); } + public boolean meetsCriteria(Criteria criteria) { + return LocationProvider.this.onMeetsCriteria(criteria); + } + public int getAccuracy() { return LocationProvider.this.onGetAccuracy(); } @@ -225,6 +228,12 @@ public abstract class LocationProvider { */ public abstract int onGetPowerRequirement(); + /** + * Returns true if this provider meets the given criteria, + * false otherwise. + */ + public abstract boolean onMeetsCriteria(Criteria criteria); + /** * Returns a constant describing horizontal accuracy of this provider. * If the provider returns finer grain or exact location, @@ -246,11 +255,11 @@ public abstract class LocationProvider { /** * Returns a information on the status of this provider. - * {@link #OUT_OF_SERVICE} is returned if the provider is + * {@link android.location.LocationProvider#OUT_OF_SERVICE} is returned if the provider is * out of service, and this is not expected to change in the near - * future; {@link #TEMPORARILY_UNAVAILABLE} is returned if + * future; {@link android.location.LocationProvider#TEMPORARILY_UNAVAILABLE} is returned if * the provider is temporarily unavailable but is expected to be - * available shortly; and {@link #AVAILABLE} is returned + * available shortly; and {@link android.location.LocationProvider#AVAILABLE} is returned * if the provider is currently available. * *

If extras is non-null, additional status information may be @@ -299,9 +308,9 @@ public abstract class LocationProvider { /** * Updates the network state for the given provider. This function must - * be overwritten if {@link #requiresNetwork} returns true. The state is - * {@link #TEMPORARILY_UNAVAILABLE} (disconnected), OR {@link #AVAILABLE} - * (connected or connecting). + * be overwritten if {@link android.location.LocationProvider#requiresNetwork} returns true. + * The state is {@link android.location.LocationProvider#TEMPORARILY_UNAVAILABLE} (disconnected) + * OR {@link android.location.LocationProvider#AVAILABLE} (connected or connecting). * * @param state data state */ diff --git a/location/java/com/android/internal/location/DummyLocationProvider.java b/location/java/com/android/internal/location/DummyLocationProvider.java index ff5e27b086f7042a20f2d3111297ba284e392bcf..e7b5143db6393e1885ae09d3e01c6a9c939a2945 100644 --- a/location/java/com/android/internal/location/DummyLocationProvider.java +++ b/location/java/com/android/internal/location/DummyLocationProvider.java @@ -16,6 +16,7 @@ package com.android.internal.location; +import android.location.ILocationManager; import android.location.LocationProvider; /** @@ -41,8 +42,8 @@ public class DummyLocationProvider extends LocationProvider { int mPowerRequirement; int mAccuracy; - public DummyLocationProvider(String name) { - super(name); + public DummyLocationProvider(String name, ILocationManager service) { + super(name, service); } public void setRequiresNetwork(boolean requiresNetwork) { diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java index a5466d1be03dfb1880921fac7afb91061f09271e..d3a71b37273088cf2810ba3b960ea1fa0d087029 100755 --- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java +++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java @@ -23,6 +23,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.location.LocationManager; import android.os.Bundle; import android.os.RemoteException; import android.util.Log; @@ -81,7 +82,7 @@ public class GpsNetInitiatedHandler { private final Context mContext; // parent gps location provider - private final GpsLocationProvider mGpsLocationProvider; + private final LocationManager mLocationManager; // configuration of notificaiton behavior private boolean mPlaySounds = false; @@ -93,25 +94,25 @@ public class GpsNetInitiatedHandler { public static class GpsNiNotification { - int notificationId; - int niType; - boolean needNotify; - boolean needVerify; - boolean privacyOverride; - int timeout; - int defaultResponse; - String requestorId; - String text; - int requestorIdEncoding; - int textEncoding; - Bundle extras; + public int notificationId; + public int niType; + public boolean needNotify; + public boolean needVerify; + public boolean privacyOverride; + public int timeout; + public int defaultResponse; + public String requestorId; + public String text; + public int requestorIdEncoding; + public int textEncoding; + public Bundle extras; }; public static class GpsNiResponse { - /* User reponse, one of the values in GpsUserResponseType */ - int userResponse; - /* Optional extra data to pass with the user response */ - Bundle extras; + /* User reponse, one of the values in GpsUserResponseType */ + int userResponse; + /* Optional extra data to pass with the user response */ + Bundle extras; }; /** @@ -122,63 +123,57 @@ public class GpsNetInitiatedHandler { */ private Notification mNiNotification; - public GpsNetInitiatedHandler(Context context, GpsLocationProvider gpsLocationProvider) { - mContext = context; - mGpsLocationProvider = gpsLocationProvider; + public GpsNetInitiatedHandler(Context context) { + mContext = context; + mLocationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE); } // Handles NI events from HAL public void handleNiNotification(GpsNiNotification notif) { - if (DEBUG) Log.d(TAG, "handleNiNotification" + " notificationId: " + notif.notificationId - + " requestorId: " + notif.requestorId + " text: " + notif.text); - - // Notify and verify with immediate pop-up - if (notif.needNotify && notif.needVerify && mPopupImmediately) - { - // Popup the dialog box now - openNiDialog(notif); - } - - // Notify only, or delayed pop-up (change mPopupImmediately to FALSE) - if (notif.needNotify && !notif.needVerify || - notif.needNotify && notif.needVerify && !mPopupImmediately) - { - // Show the notification - - // if mPopupImmediately == FALSE and needVerify == TRUE, a dialog will be opened - // when the user opens the notification message - - setNiNotification(notif); - } - - // ACCEPT cases: 1. Notify, no verify; 2. no notify, no verify; 3. privacy override. - if ( notif.needNotify && !notif.needVerify || - !notif.needNotify && !notif.needVerify || - notif.privacyOverride) - { - try { - mGpsLocationProvider.getNetInitiatedListener().sendNiResponse(notif.notificationId, GPS_NI_RESPONSE_ACCEPT); - } - catch (RemoteException e) - { - Log.e(TAG, e.getMessage()); - } - } - - ////////////////////////////////////////////////////////////////////////// - // A note about timeout - // According to the protocol, in the need_notify and need_verify case, - // a default response should be sent when time out. - // - // In some GPS hardware, the GPS driver (under HAL) can handle the timeout case - // and this class GpsNetInitiatedHandler does not need to do anything. - // - // However, the UI should at least close the dialog when timeout. Further, - // for more general handling, timeout response should be added to the Handler here. - // + if (DEBUG) Log.d(TAG, "handleNiNotification" + " notificationId: " + notif.notificationId + + " requestorId: " + notif.requestorId + " text: " + notif.text); + + // Notify and verify with immediate pop-up + if (notif.needNotify && notif.needVerify && mPopupImmediately) + { + // Popup the dialog box now + openNiDialog(notif); + } + + // Notify only, or delayed pop-up (change mPopupImmediately to FALSE) + if (notif.needNotify && !notif.needVerify || + notif.needNotify && notif.needVerify && !mPopupImmediately) + { + // Show the notification + + // if mPopupImmediately == FALSE and needVerify == TRUE, a dialog will be opened + // when the user opens the notification message + + setNiNotification(notif); + } + + // ACCEPT cases: 1. Notify, no verify; 2. no notify, no verify; 3. privacy override. + if ( notif.needNotify && !notif.needVerify || + !notif.needNotify && !notif.needVerify || + notif.privacyOverride) + { + mLocationManager.sendNiResponse(notif.notificationId, GPS_NI_RESPONSE_ACCEPT); + } + + ////////////////////////////////////////////////////////////////////////// + // A note about timeout + // According to the protocol, in the need_notify and need_verify case, + // a default response should be sent when time out. + // + // In some GPS hardware, the GPS driver (under HAL) can handle the timeout case + // and this class GpsNetInitiatedHandler does not need to do anything. + // + // However, the UI should at least close the dialog when timeout. Further, + // for more general handling, timeout response should be added to the Handler here. + // } - + // Sets the NI notification. private synchronized void setNiNotification(GpsNiNotification notif) { NotificationManager notificationManager = (NotificationManager) mContext @@ -186,272 +181,272 @@ public class GpsNetInitiatedHandler { if (notificationManager == null) { return; } - - String title = getNotifTitle(notif); - String message = getNotifMessage(notif); - + + String title = getNotifTitle(notif); + String message = getNotifMessage(notif); + if (DEBUG) Log.d(TAG, "setNiNotification, notifyId: " + notif.notificationId + - ", title: " + title + - ", message: " + message); - - // Construct Notification - if (mNiNotification == null) { - mNiNotification = new Notification(); - mNiNotification.icon = com.android.internal.R.drawable.stat_sys_gps_on; /* Change notification icon here */ - mNiNotification.when = 0; + ", title: " + title + + ", message: " + message); + + // Construct Notification + if (mNiNotification == null) { + mNiNotification = new Notification(); + mNiNotification.icon = com.android.internal.R.drawable.stat_sys_gps_on; /* Change notification icon here */ + mNiNotification.when = 0; } - + if (mPlaySounds) { - mNiNotification.defaults |= Notification.DEFAULT_SOUND; + mNiNotification.defaults |= Notification.DEFAULT_SOUND; } else { - mNiNotification.defaults &= ~Notification.DEFAULT_SOUND; + mNiNotification.defaults &= ~Notification.DEFAULT_SOUND; } - + mNiNotification.flags = Notification.FLAG_ONGOING_EVENT; mNiNotification.tickerText = getNotifTicker(notif); - + // if not to popup dialog immediately, pending intent will open the dialog - Intent intent = !mPopupImmediately ? getDlgIntent(notif) : new Intent(); + Intent intent = !mPopupImmediately ? getDlgIntent(notif) : new Intent(); PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0); mNiNotification.setLatestEventInfo(mContext, title, message, pi); - + if (visible) { notificationManager.notify(notif.notificationId, mNiNotification); } else { notificationManager.cancel(notif.notificationId); } } - + // Opens the notification dialog and waits for user input - private void openNiDialog(GpsNiNotification notif) + private void openNiDialog(GpsNiNotification notif) { - Intent intent = getDlgIntent(notif); - - if (DEBUG) Log.d(TAG, "openNiDialog, notifyId: " + notif.notificationId + - ", requestorId: " + notif.requestorId + - ", text: " + notif.text); + Intent intent = getDlgIntent(notif); - mContext.startActivity(intent); + if (DEBUG) Log.d(TAG, "openNiDialog, notifyId: " + notif.notificationId + + ", requestorId: " + notif.requestorId + + ", text: " + notif.text); + + mContext.startActivity(intent); } - + // Construct the intent for bringing up the dialog activity, which shows the // notification and takes user input private Intent getDlgIntent(GpsNiNotification notif) { - Intent intent = new Intent(); - String title = getDialogTitle(notif); - String message = getDialogMessage(notif); - - // directly bring up the NI activity - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setClass(mContext, com.android.internal.app.NetInitiatedActivity.class); - - // put data in the intent - intent.putExtra(NI_INTENT_KEY_NOTIF_ID, notif.notificationId); - intent.putExtra(NI_INTENT_KEY_TITLE, title); - intent.putExtra(NI_INTENT_KEY_MESSAGE, message); - intent.putExtra(NI_INTENT_KEY_TIMEOUT, notif.timeout); - intent.putExtra(NI_INTENT_KEY_DEFAULT_RESPONSE, notif.defaultResponse); - - if (DEBUG) Log.d(TAG, "generateIntent, title: " + title + ", message: " + message + - ", timeout: " + notif.timeout); - - return intent; + Intent intent = new Intent(); + String title = getDialogTitle(notif); + String message = getDialogMessage(notif); + + // directly bring up the NI activity + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setClass(mContext, com.android.internal.app.NetInitiatedActivity.class); + + // put data in the intent + intent.putExtra(NI_INTENT_KEY_NOTIF_ID, notif.notificationId); + intent.putExtra(NI_INTENT_KEY_TITLE, title); + intent.putExtra(NI_INTENT_KEY_MESSAGE, message); + intent.putExtra(NI_INTENT_KEY_TIMEOUT, notif.timeout); + intent.putExtra(NI_INTENT_KEY_DEFAULT_RESPONSE, notif.defaultResponse); + + if (DEBUG) Log.d(TAG, "generateIntent, title: " + title + ", message: " + message + + ", timeout: " + notif.timeout); + + return intent; } - + // Converts a string (or Hex string) to a char array static byte[] stringToByteArray(String original, boolean isHex) { - int length = isHex ? original.length() / 2 : original.length(); - byte[] output = new byte[length]; - int i; - - if (isHex) - { - for (i = 0; i < length; i++) - { - output[i] = (byte) Integer.parseInt(original.substring(i*2, i*2+2), 16); - } - } - else { - for (i = 0; i < length; i++) - { - output[i] = (byte) original.charAt(i); - } - } - - return output; + int length = isHex ? original.length() / 2 : original.length(); + byte[] output = new byte[length]; + int i; + + if (isHex) + { + for (i = 0; i < length; i++) + { + output[i] = (byte) Integer.parseInt(original.substring(i*2, i*2+2), 16); + } + } + else { + for (i = 0; i < length; i++) + { + output[i] = (byte) original.charAt(i); + } + } + + return output; } - + /** * Unpacks an byte array containing 7-bit packed characters into a String. - * + * * @param input a 7-bit packed char array * @return the unpacked String */ static String decodeGSMPackedString(byte[] input) { - final char CHAR_CR = 0x0D; - int nStridx = 0; - int nPckidx = 0; - int num_bytes = input.length; - int cPrev = 0; - int cCurr = 0; - byte nShift; - byte nextChar; - byte[] stringBuf = new byte[input.length * 2]; - String result = ""; - - while(nPckidx < num_bytes) - { - nShift = (byte) (nStridx & 0x07); - cCurr = input[nPckidx++]; - if (cCurr < 0) cCurr += 256; - - /* A 7-bit character can be split at the most between two bytes of packed - ** data. - */ - nextChar = (byte) (( (cCurr << nShift) | (cPrev >> (8-nShift)) ) & 0x7F); - stringBuf[nStridx++] = nextChar; - - /* Special case where the whole of the next 7-bit character fits inside - ** the current byte of packed data. - */ - if(nShift == 6) - { - /* If the next 7-bit character is a CR (0x0D) and it is the last - ** character, then it indicates a padding character. Drop it. - */ - if (nPckidx == num_bytes || (cCurr >> 1) == CHAR_CR) - { - break; - } - - nextChar = (byte) (cCurr >> 1); - stringBuf[nStridx++] = nextChar; - } - - cPrev = cCurr; - } - - try{ - result = new String(stringBuf, 0, nStridx, "US-ASCII"); - } - catch (UnsupportedEncodingException e) - { - Log.e(TAG, e.getMessage()); - } - - return result; + final char CHAR_CR = 0x0D; + int nStridx = 0; + int nPckidx = 0; + int num_bytes = input.length; + int cPrev = 0; + int cCurr = 0; + byte nShift; + byte nextChar; + byte[] stringBuf = new byte[input.length * 2]; + String result = ""; + + while(nPckidx < num_bytes) + { + nShift = (byte) (nStridx & 0x07); + cCurr = input[nPckidx++]; + if (cCurr < 0) cCurr += 256; + + /* A 7-bit character can be split at the most between two bytes of packed + ** data. + */ + nextChar = (byte) (( (cCurr << nShift) | (cPrev >> (8-nShift)) ) & 0x7F); + stringBuf[nStridx++] = nextChar; + + /* Special case where the whole of the next 7-bit character fits inside + ** the current byte of packed data. + */ + if(nShift == 6) + { + /* If the next 7-bit character is a CR (0x0D) and it is the last + ** character, then it indicates a padding character. Drop it. + */ + if (nPckidx == num_bytes || (cCurr >> 1) == CHAR_CR) + { + break; + } + + nextChar = (byte) (cCurr >> 1); + stringBuf[nStridx++] = nextChar; + } + + cPrev = cCurr; + } + + try { + result = new String(stringBuf, 0, nStridx, "US-ASCII"); + } + catch (UnsupportedEncodingException e) + { + Log.e(TAG, e.getMessage()); + } + + return result; } - + static String decodeUTF8String(byte[] input) { - String decoded = ""; - try { - decoded = new String(input, "UTF-8"); - } - catch (UnsupportedEncodingException e) - { - Log.e(TAG, e.getMessage()); - } - return decoded; + String decoded = ""; + try { + decoded = new String(input, "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + Log.e(TAG, e.getMessage()); + } + return decoded; } - + static String decodeUCS2String(byte[] input) { - String decoded = ""; - try { - decoded = new String(input, "UTF-16"); - } - catch (UnsupportedEncodingException e) - { - Log.e(TAG, e.getMessage()); - } - return decoded; + String decoded = ""; + try { + decoded = new String(input, "UTF-16"); + } + catch (UnsupportedEncodingException e) + { + Log.e(TAG, e.getMessage()); + } + return decoded; } - + /** Decode NI string - * + * * @param original The text string to be decoded * @param isHex Specifies whether the content of the string has been encoded as a Hex string. Encoding - * a string as Hex can allow zeros inside the coded text. + * a string as Hex can allow zeros inside the coded text. * @param coding Specifies the coding scheme of the string, such as GSM, UTF8, UCS2, etc. This coding scheme - * needs to match those used passed to HAL from the native GPS driver. Decoding is done according + * needs to match those used passed to HAL from the native GPS driver. Decoding is done according * to the coding , after a Hex string is decoded. Generally, if the - * notification strings don't need further decoding, coding encoding can be + * notification strings don't need further decoding, coding encoding can be * set to -1, and isHex can be false. * @return the decoded string */ static private String decodeString(String original, boolean isHex, int coding) { - String decoded = original; - byte[] input = stringToByteArray(original, isHex); - - switch (coding) { - case GPS_ENC_NONE: - decoded = original; - break; - - case GPS_ENC_SUPL_GSM_DEFAULT: - decoded = decodeGSMPackedString(input); - break; - - case GPS_ENC_SUPL_UTF8: - decoded = decodeUTF8String(input); - break; - - case GPS_ENC_SUPL_UCS2: - decoded = decodeUCS2String(input); - break; - - case GPS_ENC_UNKNOWN: - decoded = original; - break; - - default: - Log.e(TAG, "Unknown encoding " + coding + " for NI text " + original); - break; - } - return decoded; + String decoded = original; + byte[] input = stringToByteArray(original, isHex); + + switch (coding) { + case GPS_ENC_NONE: + decoded = original; + break; + + case GPS_ENC_SUPL_GSM_DEFAULT: + decoded = decodeGSMPackedString(input); + break; + + case GPS_ENC_SUPL_UTF8: + decoded = decodeUTF8String(input); + break; + + case GPS_ENC_SUPL_UCS2: + decoded = decodeUCS2String(input); + break; + + case GPS_ENC_UNKNOWN: + decoded = original; + break; + + default: + Log.e(TAG, "Unknown encoding " + coding + " for NI text " + original); + break; + } + return decoded; } - + // change this to configure notification display static private String getNotifTicker(GpsNiNotification notif) { - String ticker = String.format("Position request! ReqId: [%s] ClientName: [%s]", - decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding), - decodeString(notif.text, mIsHexInput, notif.textEncoding)); - return ticker; + String ticker = String.format("Position request! ReqId: [%s] ClientName: [%s]", + decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding), + decodeString(notif.text, mIsHexInput, notif.textEncoding)); + return ticker; } - + // change this to configure notification display static private String getNotifTitle(GpsNiNotification notif) { - String title = String.format("Position Request"); - return title; + String title = String.format("Position Request"); + return title; } - + // change this to configure notification display static private String getNotifMessage(GpsNiNotification notif) { - String message = String.format( - "NI Request received from [%s] for client [%s]!", - decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding), - decodeString(notif.text, mIsHexInput, notif.textEncoding)); - return message; + String message = String.format( + "NI Request received from [%s] for client [%s]!", + decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding), + decodeString(notif.text, mIsHexInput, notif.textEncoding)); + return message; } - + // change this to configure dialog display (for verification) static public String getDialogTitle(GpsNiNotification notif) { - return getNotifTitle(notif); + return getNotifTitle(notif); } - + // change this to configure dialog display (for verification) static private String getDialogMessage(GpsNiNotification notif) { - return getNotifMessage(notif); + return getNotifMessage(notif); } - + } diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index b26906d1412f443ffe952100227e8029b0b45302..74488c5e339456581f36a836069b34fbfb335130 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -51,6 +51,19 @@ public class ExifInterface { public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef"; /** Type is String. */ public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef"; + + /** + * The altitude (in meters) based on the reference in TAG_GPS_ALTITUDE_REF. + * Type is rational. + */ + public static final String TAG_GPS_ALTITUDE = "GPSAltitude"; + + /** + * 0 if the altitude is above sea level. 1 if the altitude is below sea + * level. Type is int. + */ + public static final String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef"; + /** Type is String. */ public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp"; /** Type is String. */ @@ -288,6 +301,23 @@ public class ExifInterface { } } + /** + * Return the altitude in meters. If the exif tag does not exist, return + * defaultValue. + * + * @param defaultValue the value to return if the tag is not available. + */ + public double getAltitude(double defaultValue) { + double altitude = getAttributeDouble(TAG_GPS_ALTITUDE, -1); + int ref = getAttributeInt(TAG_GPS_ALTITUDE_REF, -1); + + if (altitude >= 0 && ref >= 0) { + return (double) (altitude * ((ref == 1) ? -1 : 1)); + } else { + return defaultValue; + } + } + /** * Returns number of milliseconds since Jan. 1, 1970, midnight. * Returns -1 if the date time information if not available. @@ -345,14 +375,14 @@ public class ExifInterface { / Float.parseFloat(pair[1].trim()))); pair = parts[2].split("/"); - float seconds = Float.parseFloat(pair[0].trim()) - / Float.parseFloat(pair[1].trim()); + double seconds = Double.parseDouble(pair[0].trim()) + / Double.parseDouble(pair[1].trim()); - float result = degrees + (minutes / 60F) + (seconds / (60F * 60F)); + double result = degrees + (minutes / 60.0) + (seconds / 3600.0); if ((ref.equals("S") || ref.equals("W"))) { - return -result; + return (float) -result; } - return result; + return (float) result; } catch (RuntimeException ex) { // if for whatever reason we can't parse the lat long then return // null diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index 9d1d4201cb2402f02e29f605277a6f0f21acc06b..f1da72fd29030ca506b177f341876eceada37ba7 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -46,8 +46,9 @@ public class MediaFile { public static final int FILE_TYPE_WMA = 6; public static final int FILE_TYPE_OGG = 7; public static final int FILE_TYPE_AAC = 8; + public static final int FILE_TYPE_MKA = 9; private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3; - private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_AAC; + private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_MKA; // MIDI file types public static final int FILE_TYPE_MID = 11; @@ -63,8 +64,9 @@ public class MediaFile { public static final int FILE_TYPE_3GPP2 = 24; public static final int FILE_TYPE_WMV = 25; public static final int FILE_TYPE_ASF = 26; + public static final int FILE_TYPE_MKV = 27; private static final int FIRST_VIDEO_FILE_TYPE = FILE_TYPE_MP4; - private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_ASF; + private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_MKV; // Image file types public static final int FILE_TYPE_JPEG = 31; @@ -134,6 +136,7 @@ public class MediaFile { addFileType("OGG", FILE_TYPE_OGG, "application/ogg"); addFileType("OGA", FILE_TYPE_OGG, "application/ogg"); addFileType("AAC", FILE_TYPE_AAC, "audio/aac"); + addFileType("MKA", FILE_TYPE_MKA, "audio/x-matroska"); addFileType("MID", FILE_TYPE_MID, "audio/midi"); addFileType("MIDI", FILE_TYPE_MID, "audio/midi"); @@ -151,6 +154,8 @@ public class MediaFile { addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp"); addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2"); addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2"); + addFileType("MKV", FILE_TYPE_MKV, "video/x-matroska"); + addFileType("WEBM", FILE_TYPE_MKV, "video/x-matroska"); if (isWMVEnabled()) { addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv"); addFileType("ASF", FILE_TYPE_ASF, "video/x-ms-asf"); diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index e8b89e0e63c5b7fc8bfa8082f6ad0a09a7e55e0e..8f6564a06450fc2f41b6033dfdae225982b8dbc9 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -133,7 +133,7 @@ import java.lang.ref.WeakReference; *

  • It is good programming practice to have your application * register a OnErrorListener to look out for error notifications from * the internal player engine.
  • - *
  • IlleglStateException is + *
  • IllegalStateException is * thrown to prevent programming errors such as calling {@link #prepare()}, * {@link #prepareAsync()}, or one of the overloaded setDataSource * methods in an invalid state.
  • diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index 8ed37301156e8fb9b0ff109dfb286cec507cd825..60ff26493487c2ead811331d4cb2380e86cbb3ba 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -636,7 +636,7 @@ android_media_MediaPlayer_native_init(JNIEnv *env) return; } - fields.surface_native = env->GetFieldID(surface, "mSurface", "I"); + fields.surface_native = env->GetFieldID(surface, ANDROID_VIEW_SURFACE_JNI_ID, "I"); if (fields.surface_native == NULL) { jniThrowException(env, "java/lang/RuntimeException", "Can't find Surface.mSurface"); return; diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index 00af3a28683609fd0c50d91e88e0464d67477e97..8cf2e51dcc72162afa822b9f5f097072ecbe1ef3 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -403,7 +403,7 @@ android_media_MediaRecorder_native_init(JNIEnv *env) return; } - fields.surface_native = env->GetFieldID(surface, "mSurface", "I"); + fields.surface_native = env->GetFieldID(surface, ANDROID_VIEW_SURFACE_JNI_ID, "I"); if (fields.surface_native == NULL) { jniThrowException(env, "java/lang/RuntimeException", "Can't find Surface.mSurface"); return; diff --git a/media/libdrm/mobile2/Android.mk b/media/libdrm/mobile2/Android.mk deleted file mode 100644 index e187139870243a15f9d3b805d49acc097e97c62e..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/Android.mk +++ /dev/null @@ -1,79 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -# --------------------------------------- -# First project -# -# Build DRM2 core library -# -# Output: libdrm2.so -# --------------------------------------- -include $(CLEAR_VARS) - -common_SRC_FILES := \ - src/util/ustl-1.0/bktrace.cpp \ - src/util/ustl-1.0/memblock.cpp \ - src/util/ustl-1.0/ofstream.cpp \ - src/util/ustl-1.0/ualgobase.cpp \ - src/util/ustl-1.0/unew.cpp \ - src/util/ustl-1.0/cmemlink.cpp \ - src/util/ustl-1.0/memlink.cpp \ - src/util/ustl-1.0/sistream.cpp \ - src/util/ustl-1.0/ubitset.cpp \ - src/util/ustl-1.0/ustdxept.cpp \ - src/util/ustl-1.0/fstream.cpp \ - src/util/ustl-1.0/mistream.cpp \ - src/util/ustl-1.0/sostream.cpp \ - src/util/ustl-1.0/uexception.cpp \ - src/util/ustl-1.0/ustring.cpp \ - src/util/xml/DomExpatAgent.cpp \ - src/util/xml/ExpatWrapper.cpp \ - src/util/xml/XMLDocumentImpl.cpp \ - src/util/xml/XMLElementImpl.cpp \ - src/util/domcore/CharacterDataImpl.cpp \ - src/util/domcore/ElementImpl.cpp \ - src/util/domcore/NodeListImpl.cpp \ - src/util/domcore/DocumentImpl.cpp \ - src/util/domcore/NodeImpl.cpp \ - src/util/domcore/TextImpl.cpp \ - src/util/domcore/DOMException.cpp \ - src/util/domcore/NodeIterator.cpp \ - src/util/crypto/DrmCrypto.cpp \ - src/rights/RoManager.cpp \ - src/rights/Asset.cpp \ - src/rights/Ro.cpp \ - src/rights/OperationPermission.cpp \ - src/rights/Right.cpp \ - src/rights/Constraint.cpp \ - src/drmmanager/DrmManager.cpp \ - src/dcf/DrmDcfCommon.cpp \ - src/dcf/DrmDcfContainer.cpp \ - src/dcf/DrmIStream.cpp \ - src/dcf/DrmRawContent.cpp \ - src/roap/RoapMessageHandler.cpp \ - src/roap/Registration.cpp - -ifeq ($(TARGET_ARCH),arm) - LOCAL_CFLAGS += -fstrict-aliasing -fomit-frame-pointer -endif - -common_CFLAGS := -W -g -DPLATFORM_ANDROID - -common_C_INCLUDES +=\ - $(LOCAL_PATH)/include \ - $(LOCAL_PATH)/src/util/ustl-1.0 \ - external/expat/lib \ - external/openssl \ - external/openssl/include - -LOCAL_SRC_FILES := $(common_SRC_FILES) -LOCAL_CFLAGS += $(common_CFLAGS) -LOCAL_C_INCLUDES += $(common_C_INCLUDES) - -LOCAL_SHARED_LIBRARIES := libexpat libcrypto -LOCAL_MODULE := libdrm2 - -ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86) -LOCAL_CFLAGS += -DUSTL_ANDROID_X86 -endif - -include $(BUILD_STATIC_LIBRARY) diff --git a/media/libdrm/mobile2/include/dcf/DrmDcfCommon.h b/media/libdrm/mobile2/include/dcf/DrmDcfCommon.h deleted file mode 100644 index 9ca7b3f821614b1b0111ef6006941dab930a9879..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/dcf/DrmDcfCommon.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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. - */ - -#ifndef __DCF_COMM_H__ -#define __DCF_COMM_H__ - -#include -#include -#include -#include - -using namespace ustl; - -////DCF box type list -const uint32_t DCF_CONTAINER_BOX = uint32_t('m' << 24 | 'r' << 16 | 'd' << 8 | 'o'); -const uint32_t DCF_USER_TYPE = uint32_t('d' << 24 | 'i' << 16 | 'u' << 8 | 'u'); -const uint32_t DCF_FILE_TYPE = uint32_t('p' << 24 | 'y' << 16 | 't' << 8 | 'f'); -const uint32_t DCF_FILE_BRAND = uint32_t('f' << 24 | 'c' << 16 | 'd' << 8 | 'o'); - - -/** - * The basic box class. - */ -class Box -{ -public: - /** - * constructor for Box, used to parse Box - * \param box Box data - */ - Box(const uint8_t* box); - - /** - * copy constructor for Box - * \param dcfBox Box object used to init a new Box object - */ - Box(const Box& dcfBox); - - /** - * assignment operator for Box - * \param other Box object used to assign to a exist Box object - */ - Box& operator=(const Box& other); - - /** Destructor for Box */ - virtual ~Box(); - - /** - * get the size of Box - * \param none - * \return - * the size - */ - uint64_t getSize(void) const; - - /** - * get the type of Box - * \param none - * \return - * the type - */ - uint32_t getType(void) const; - - /** - * get the user type of Box - * \param none - * \return - * the user type - */ - const uint8_t* getUsertype(void) const; - - /** - * get the length of Box - * \param none - * \return - * the length - */ - virtual uint32_t getLen(void) const; -PRIVATE: - static const uint32_t USER_TYPE_LEN = 16; - - uint32_t mSize; - uint32_t mType; - uint64_t mLargeSize; - uint8_t* mUserType; - uint32_t mBoxLength; -}; - -/** - * The fullBox class. - */ -class FullBox : public Box -{ -public: - /** - * constructor for FullBox, used to parse FullBox - * \param fullBox FullBox data - */ - FullBox(const uint8_t* fullBox); - - /** Destructor for FullBox */ - virtual ~FullBox(){} - - /** - * get the version of FullBox - * \param none - * \return - * the version - */ - uint8_t getVersion(void) const; - - /** - * get the flag of FullBox - * \param none - * \return - * the flag - */ - const uint8_t* getFlag(void) const; - - /** - * get the length of FullBox - * \param none - * \return - * the length - */ - virtual uint32_t getLen(void) const; -PRIVATE: - static const uint32_t FLAG_LEN = 3; - - uint8_t mVersion; - uint8_t mFlag[FLAG_LEN]; - uint32_t mFullBoxLength; -}; - -////// textal header class -class TextualHeader -{ -public: - /** default constructor of DrmInStream */ - TextualHeader(){}; - - /** - * constructor for TextualHeader, used to parse textal header - * \param inData textal header data - */ - TextualHeader(const string& inData); - - /** - * get the name of textal header - * \param none - * \return - * the name - */ - string getName() const; - - /** - * get the value of textal header - * \param none - * \return - * the value - */ - string getValue() const; - - /** - * get the parameter of textal header - * \param none - * \return - * the parameter - */ - string getParam() const; -PRIVATE: - string name; - string value; - string param; -}; - -extern int64_t ntoh_int64(int64_t in); - -#endif diff --git a/media/libdrm/mobile2/include/dcf/DrmDcfContainer.h b/media/libdrm/mobile2/include/dcf/DrmDcfContainer.h deleted file mode 100644 index 14da450ca080470216be384721e15766d6ed3297..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/dcf/DrmDcfContainer.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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. - */ - -#ifndef __DCF_CONTAINER_H__ -#define __DCF_CONTAINER_H__ - -#include -#include -#include -#include - -class DrmInStream; - -/////////dcf container -class DcfContainer : public FullBox -{ -public: - friend class DrmInStream; - - /** default constructor of DcfContainer */ - DcfContainer(istream& inRawData):FullBox(NULL),mConStream(inRawData){} - - /** - * constructor for DcfContainer, used to parse DCF container - * \param data DCF container data - * \param len DCF container data len - * \param off the offset from the start of DCF container - */ - DcfContainer(const uint8_t* data,istream& inRawData,uint64_t conOff); - - /** Destructor for DcfContainer */ - ~DcfContainer(); - - /** - * get the content type of one content - * \param none - * \return - * the content type - */ - string getContentType(void) const; - - /** - * get the encryption method apply to content - * \param none - * \return - * the encryption method - */ - uint8_t getEncryptionMethod(void) const; - - /** - * get the padding scheme apply to content - * \param none - * \return - * the padding scheme - */ - uint8_t getPaddingScheme(void) const; - - /** - * get the length of plain content - * \param none - * \return - * the length of plain content - */ - uint64_t getPlaintextLength(void) const; - - /** - * get the length of content ID - * \param none - * \return - * the length of content ID - */ - uint16_t getContentIDLength(void) const; - - /** - * get the length of rights issuer URL - * \param none - * \return - * the length of rights issuer URL - */ - uint16_t getRightsIssuerURLLength(void) const; - - /** - * get the length of textal header - * \param none - * \return - * the length of textal header - */ - uint16_t getTextualHeadersLength(void) const; - - /** - * get the content ID of one content - * \param none - * \return - * the content ID - */ - string getContentID(void) const; - - /** - * get the rights issuer URL - * \param none - * \return - * the rights issuer URL - */ - string getRightsIssuerURL(void) const; - - /** - * get the preview method - * \param none - * \return - * the preview method - */ - string getPreviewMethod(void) const; - - /** - * get the location of content - * \param none - * \return - * the location of content - */ - string getContentLocation(void) const; - - /** - * get the URL of content - * \param none - * \return - * the URL of content - */ - string getContentURL(void) const; - - /** - * get the customer head - * \param none - * \return - * the customer head - */ - vector getCustomerHead(void) const; - - /** - * get the preview element data - * \param none - * \return - * the DRM Instream of preview element data - */ - DrmInStream getPreviewElementData(void) const; - - /** - * get the plain content - * \param none - * \return - * the DRM Instream of plain content - */ - DrmInStream getDecryptContent(uint8_t* decryptKey) const; - - /** - * get the istream of DCF - * \param none - * \return - * the istream of DCF - */ - istream& getStream(void) const; - -PRIVATE: - static const uint32_t USER_DATA_FLAG = 0x01; - - uint8_t mContentTypeLen; - string mContentType; - uint8_t mEncryptionMethod; - uint8_t mPaddingScheme; - uint64_t mPlaintextLength; - uint16_t mContentIDLength; - uint16_t mRightsIssuerURLLength; - uint16_t mTextualHeadersLength; - string mContentID; - string mRightsIssuerURL; - vector mTextualHeaders; - bool mSilentFirst; - string mSlientMethod; - string mSilentRightsURL; - string mPreviewMethod; - string mPreviewElementURI; - string mPreviewRightsURL; - string mContentURL; - string mContentVersion; - string mContentLocation; - vector mCustomHeader; - bool mHasUserData; - uint64_t mDataLen; - istream& mConStream; - uint64_t mDecOffset; - -PRIVATE: - // parse text header - bool parseTextualHeaders(const uint8_t* data, uint32_t len); - void copy(const DcfContainer& container); - DcfContainer(const DcfContainer& container):FullBox(NULL),mConStream(container.mConStream){} - DcfContainer& operator=(const DcfContainer& other){return *this;} -}; - - -#endif diff --git a/media/libdrm/mobile2/include/dcf/DrmIStream.h b/media/libdrm/mobile2/include/dcf/DrmIStream.h deleted file mode 100644 index 10e264e3c3d2fbea205670e5f676c324ca36a56a..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/dcf/DrmIStream.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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. - */ - -#ifndef __DRM_ISTREAM_H__ -#define __DRM_ISTREAM_H__ - -#include -#include -#include -#include - -using namespace ustl; - -class DcfContainer; - -class DrmInStream -{ -public: - /** default constructor of DrmInStream */ - DrmInStream():mDecryptPos(0){} - - /** - * constructor for DrmInStream, used to read DCF content - * \param encFile DCF container data - * \param len DCF container data len - * \param off the offset from the start of DCF container - */ - DrmInStream(const DcfContainer* container,uint8_t* Key); - - /** - * get the size of DRM Instream - * \param none - * \return - * the size of DRM Instream - */ - uint64_t size() const; - - /** - * read data from DRM Instream - * \param data the buffer to store read data - * \param len how much data need to read - * \return - * the actual len of read data - */ - uint64_t read(uint8_t* data,uint64_t len); - -PRIVATE: - static const uint32_t AES_IV_LEN = 16; - static const uint32_t AES_KEY_LEN = 16; - static const uint32_t AES_BLOCK_LEN = 16; - - const DcfContainer* mDcfCon; - uint64_t mDecryptPos; - uint8_t mAesKey[AES_KEY_LEN]; -}; - - - -#endif - - - - - diff --git a/media/libdrm/mobile2/include/dcf/DrmRawContent.h b/media/libdrm/mobile2/include/dcf/DrmRawContent.h deleted file mode 100644 index 2d433afade8c404e30fff36755b465c8a86c4f23..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/dcf/DrmRawContent.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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. - */ - -#ifndef __DRM_CONTENT_H__ -#define __DRM_CONTENT_H__ - -#include -#include - -/////////////raw content -class DrmRawContent -{ -public: - /** - * constructor for DrmRawContent, used to parse DCF - * \param inRawData input stream of raw data. - */ - DrmRawContent(istream& inRawData); - - /** Destructor for DrmRawContent */ - ~DrmRawContent(); - - /** - * get DCF container - * \param none - * \return - * the DCF container - */ - vector getContents(void) const; - - /** - * get the length of DCF hash - * \param none - * \return - * the length of DCF hash - */ - uint32_t getDcfHashLen() const; - - /** - * get DCF hash - * \param outDcfHash the buffer to store DCF hash - * \return - * none - */ - void getDcfHash(uint8_t* outDcfHash) const; - -PRIVATE: - static const uint32_t DCF_HASH_LEN = 20; - static const uint32_t FIX_HEADER_LEN = 20; - static const uint32_t MAX_PIECE_LEN = (100 * 1024); - - uint8_t mDcfHash[DCF_HASH_LEN]; - vector mContainer; - -PRIVATE: - bool parseDcfHeader(const uint8_t* dcfHead); - DrmRawContent(const DrmRawContent& rawContent){} - DrmRawContent& operator=(const DrmRawContent& other){return *this;} -}; - -#endif diff --git a/media/libdrm/mobile2/include/drmmanager/DrmManager.h b/media/libdrm/mobile2/include/drmmanager/DrmManager.h deleted file mode 100644 index c8bfbc145a6af898bc1b1c976bf913d88a7c6a4d..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/drmmanager/DrmManager.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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. - */ -#ifndef _DRMMANAGER_ -#define _DRMMANAGER_ - -#include -#include -#include -#include -#include -#include - -using namespace ustl; - -/** It should be removed after real DcfContainer is ready */ -#define DcfContainer string -static const int16_t DRM_OK = 1; - -class DrmManager -{ -public: - /** - * Error definition - */ - static const int16_t DRM_MANAGER_BASE = 100; - static const int16_t ERR_DCFSTREAM_NOT_INITIALIZED = DRM_MANAGER_BASE+1; - static const int16_t ERR_WRONG_DCFDATA = DRM_MANAGER_BASE+2; - static const int16_t ERR_WRONG_RIGHTS = DRM_MANAGER_BASE+3; - - /** - * Constructor for DrmManager,used to open local dcf file. - * @param inRawData input stream of raw data. - */ - DrmManager(istream *inRawData); - - /** - * Constructor for DrmManager,used to separate dcf file and trig message when upper - * application downloading one multipart message from CI. - * @param inRawData input stream of raw data. - */ - DrmManager(istream * inRawData, string mimeType); - - /** Destructor for DomExpatAgent. */ - ~DrmManager(); - /** - * Config DRM engine - * Fix me later - */ - bool config(); - - /** - * Consume rights according to specified operation, DrmManager will check. - * @param operationType the type of operation. - * @return the operation result. - */ - int16_t consumeRights(int16_t operationType); - - /** - * Get the list of all dcf containers object reference in the dcf file. - * @param the vector of the dcf objects list returned. - * @return the operation result. - */ - int16_t getListOfDcfObjects(vector **outDcfList); - - /** - * Open one Dcf container to read the decrypted data according to specified - * operation. - * @param oneDcfObject the reference of the DcfContainer. - * @param operationType the type of operation. - * @param decrypted data returned. - * @return the operation result. - */ - int16_t openDecryptedContent(DcfContainer *oneDcfObject, - int16_t operationType, - istream *outDecryptedData); - - /** - * Get the separated Dcf raw data from multipart message. - * @return the ifstream of the dcf raw data which should be stored by upper - * application. - */ - ifstream* getOriginalMediaData(void); - - /** - * Handle DRM2.0 push message - */ - bool handlePushMsg(uint8_t* data, string mimeType); - -PRIVATE: - istream *mDcfStream; /**< the handler of dcf stream. */ - vector mDcfs; /**< all the dcf containers included in one dcf file. */ -}; - -#endif //_DRMMANAGER_ diff --git a/media/libdrm/mobile2/include/rights/Asset.h b/media/libdrm/mobile2/include/rights/Asset.h deleted file mode 100644 index 66696ddcffacf3b3b4544235db5be2bfcc75df44..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/rights/Asset.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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. - */ -#ifndef _ASSET_H -#define _ASSET_H - -#include -#include -#include -#include -using namespace ustl; - -class Asset { -public: - /** - * Constructor for asset. - */ - Asset(); - - /** - * Destructor for asset. - */ - ~Asset(); - - /** - * Test whether asset has parent or not. - * @return true/false to indicate the result. - */ - bool hasParent(); - - /** - * Set id of asset. - * @param id the id of asset. - */ - void setID(const string &id); - - /** - * Get the id of content. - * @return asset id. - */ - const string& getID() const; - - /** - * Set contend id related to asset. - * @param id the id of content. - */ - void setContentID(const string &id); - - /** - * Get content id. - * @return content id. - */ - const string& getContentID() const; - - /** - * Set digest value of DCF. - * @param value the DCF digest value. - */ - void setDCFDigest(const string &value); - - /** - * Get the DCF digest value. - * @return the digest value of DCF. - */ - const string& getDCFDigest() const; - - /** - * Set encrypted key in asset. - * @param the encrypted key. - */ - void setEncryptedKey(const string &key); - - /** - * Get encrypted key. - * @return encypted key. - */ - const string& getEncrytedKey() const; - - /** - * Get cek. - * @return cek. - */ - const char* getCek() const; - - /** - * Set the retrieval method of key. - * @param rm the retrieval method of the key. - */ - void setKeyRetrievalMethod(const string &rm); - - /** - * Set parent content id for asset. - * @param id the parent content id. - */ - void setParentContentID(const string &id); - - /** - * Get the parent content id of the asset. - * @return the parent content id. - */ - const string& getParentContentID() const; - - /** - * Recover the CEK using private key. - */ - void recoverCek(); - -PRIVATE: - string mAssetID; - string mContentID; - string mDigestMethod; - string mDigestValue; - string mEncryptedMethod; - string mEncryptedKey; - string mRetrievalMethod; - string mParentContentID; - string mCek; -}; - -#endif diff --git a/media/libdrm/mobile2/include/rights/Constraint.h b/media/libdrm/mobile2/include/rights/Constraint.h deleted file mode 100644 index bcf5afe58a1f9840575ca82e0086b1e6c287d654..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/rights/Constraint.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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. - */ -#ifndef _CONSTRAINT_H -#define _CONSTRAINT_H - -#include -#include -#include -using namespace ustl; - -struct Context { - string id; - string version; -}; - -const int INIT_VALUE = -1; - -class Constraint { -public: - enum MODE {NONE, MOVE, COPY}; /**< export mode type. */ - - /** - * Construtor for constraint. - */ - Constraint(); - - /** - * Destructor for constraint. - */ - ~Constraint(); - -public: - /** - * Test whether constraint is valid or not - * @param time the specitic time to test. - * @return true/false to indicate the result. - */ - bool isValid(long time) const; - - /** - * Test whether constraint is unconstraint or not - * @return true/false to indicate the result. - */ - bool isUnConstraint() const; - - /** - * Test whether constraint is datetime related or not. - * @return true/false to indicate the result. - */ - bool isDateTimeConstraint() const; - - /** - * Test whether constraint contain interval or not - * @return true/false to indicate the result. - */ - bool isIntervalConstraint() const; - - /** - * Test whether constraint is timed count or not - * @return true/false to indicate the result. - */ - bool isTimedCountConstraint() const; - - /** - * Set the start time value of constraint. - * @param time the specific time value. - */ - void setStartTime(long time); - - /** - * Get the start time. - * @return value of start time. - */ - long getStartTime() const; - - /** - * Set the end time. - * @param time the value of end time. - */ - void setEndTime(long time); - - /** - * Get the end time. - * @param return the value of end time. - */ - long getEndTime() const; - - /** - * Set the accumulated . - * @param time the specific time. - */ - void setAccumulated(long time); - - /** - * Get the accumulated. - * @return the value of accumulated - */ - long getAccumulated() const; - - /** - * Set the count. - * @param count the value of count. - */ - void setCount(int count); - - /** - * Get the count. - * @return value of count. - */ - int getCount() const; - - /** - * Set the value of timer. - * @param timer the value of the timer. - */ - void setTimer(int timer); - - /** - * Get the timer. - * @return value of time. - */ - int getTimer() const; - - /** - * Set the timedCount. - * @param timedCount the value of timedCount. - */ - void setTimedCount(int timedCount); - - /** - * Get the timedCount. - * @return the value of timedCount. - */ - int getTimedCount() const; - - /** - * Set the interval. - * @param interval the value of interval. - */ - void setInterval(int interval); - - /** - * Get the interval. - * @return the value of interval. - */ - int getInterval() const; - - /** - * set export mode. - * @param mode the mode type of export. - */ - void setExportMode(MODE mode); - - /** - * Get the export mode. - * @return the export mode. - */ - MODE getExportMode() const; - - /** - * Consume the constraint. - * @return true/false to indicate whether consume succesfully or not. - */ - bool consume(); - -PRIVATE: - int mCount; /**< the count. */ - int mTimedCount; /**< timed count. */ - int mTimer; /**< timer for timed count. */ - long mStart; /**< start time. */ - long mEnd; /**< end time. */ - int mInterval; /**< interval. */ - long mAccumulated; /**< accumlated. */ - vector mSystemList; /**< system list. */ - MODE mExport; /**< export mode. */ -}; -#endif diff --git a/media/libdrm/mobile2/include/rights/OperationPermission.h b/media/libdrm/mobile2/include/rights/OperationPermission.h deleted file mode 100644 index 28cba7b4564749848c2ef122408b495ae8eaf898..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/rights/OperationPermission.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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. - */ -#ifndef _OPERATIONPERMISSION_H -#define _OPERATIONPERMISSION_H - -#include -#include - -class OperationPermission { -public: - enum OPERATION {NONE, PLAY, DISPLAY, EXECUTE, PRINT, EXPORT, COMMON}; - - /** - * Construtor of OperationPermission. - */ - OperationPermission(); - - /** - * Construtor of OperationPermission. - * @param type the specific operation type. - * @param cst the constraint related with operation permission. - */ - OperationPermission(OPERATION type, Constraint* cst=NULL); - - /** - * Destrutor of OperationPermission. - */ - ~OperationPermission(); - - /** - * Set the type for operation permission. - * @param type the specific type. - */ - void setType(OPERATION type); - - /** - * Get the type of operation permission. - * @return operation type. - */ - OPERATION getType() const; - - /** - * Add constraint for operation permission. - * @param constraint the constraint related with operation permission. - */ - void addConstraint(Constraint* constraint); - - /** - * Add constraint for operation permission. - * @return constraint related with operation permission. - */ - Constraint* getConstraint() const; - -PRIVATE: - OPERATION mType; - Constraint* mConstraint; - -PRIVATE: - /** - * Disable the assignment between OperationPermissions. - */ - OperationPermission& operator=(const OperationPermission &op); - - /** - * Disable copy construtor. - */ - OperationPermission(const OperationPermission &op); -}; - -#endif diff --git a/media/libdrm/mobile2/include/rights/Right.h b/media/libdrm/mobile2/include/rights/Right.h deleted file mode 100644 index 347e4843b4a601203c7e102d645591313375d3af..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/rights/Right.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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. - */ -#ifndef _RIGHT_H -#define _RIGHT_H - -#include -#include -#include -#include -#include -using namespace ustl; - -class Right { -public: - /** - * Constructor for Right. - */ - Right(); - - /** - * Destructor for Right. - */ - ~Right(); - - /** - * Add the asset id related with right into asset name list. - * @param id the id of the asset. - */ - void addAssetID(const string& id); - - /** - * Add a operation permission into right's operation permission list. - * @param op a pointer of operation permission. - */ - void addOperationPermission(OperationPermission* op); - - /** - * Get the constraint related with operation type. - * @param type the specific operation type. - * @return NULL if not found otherwise the constraint pointer. - */ - Constraint* getConstraint(OperationPermission::OPERATION type); - - /** - * Test whether the right has specific operation type or not. - * @param type the specific type. - * @return true/false to indicate the result. - */ - bool checkPermission(OperationPermission::OPERATION type); - -public: - vector mAssetNameList; - -PRIVATE: - vector mOpList; - -PRIVATE: - - /** - * Disable the assignment between rights. - */ - Right& operator=(const Right& right); - - /** - * Disable copy constructor. - */ - Right(const Right& right); - }; - -#endif diff --git a/media/libdrm/mobile2/include/rights/Ro.h b/media/libdrm/mobile2/include/rights/Ro.h deleted file mode 100644 index 0bf0a973c169f59c4cdbc4ac61f1d95b0746db35..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/rights/Ro.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 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. - */ - -#ifndef _RO_H_ -#define _RO_H_ - -#include -#include -#include -#include -#include -using namespace ustl; - -class Asset; -class XMLDocumentImpl; -class XMLElementImpl; -class NodeImpl; - -class Ro { -public: - enum ERRCODE { RO_NULL_STREAM, RO_ERR_BAD_XML, RO_OK, RO_BAD }; - - /** - * Constructor for Ro. - */ - Ro(); - - /** - * Destructor for Ro. - */ - ~Ro(); - - /** - * Set id for Ro. - * @param id the id of Ro. - */ - void setRoID(string &id); - - /** - * Get the id of Ro. - * @return the id of Ro. - */ - const string& getRoID() const; - - /** - * Set version for Ro. - */ - void setRoVersion(string &version); - - /** - * Add a asset into ro's asset list. - * @param asset the pointer of asset. - */ - void addAsset(Asset* asset); - - /** - * Add a right into ro's right list. - * @param right the pointer of right. - */ - void addRight(Right* right); - - /** - * Save the Ro. - */ - bool save(); - - /** - * Verify the Ro. - */ - bool verify(); - - /** - * Parse the ro from stream. - * @param roStream the input ro stream. - * @return RO_OK if parse successfully otherwise return error code. - */ - ERRCODE parse(istringstream *roStream); - - /** - * Check the permission of the content. - * @param type the operation type. - * @param contentID the specific contentID. - * @return true/false to indicate result. - */ - bool checkPermission(OperationPermission::OPERATION type, - const string& contentID); - - /** - * Consume the right related to content. - * @param type the operation type. - * @param contentID the specific contentID. - * @return the status of consume. - */ - ERRCODE consume(OperationPermission::OPERATION type, - const string& contentID); - - /** - * Get CEK of content. - * @param contentID the specific content id. - * @return "" if not found otherwise return CEK. - */ - string getContentCek(const string& contentID); - - /** - * Get Digest value of content. - * @param contentID the specific content id. - * @return "" if not found otherwise return digest value. - */ - string getContentHash(const string& contentID); - -PRIVATE: - /** - * Handle the xml dom document. - * @param doc the pointer to the dom document. - * @return true/false to indicate the result. - */ - bool handleDocument(const XMLDocumentImpl* doc); - - /** - * Handle the xml dom node which contains element. - * @param curNode the dom node which contains element. - * @return true/false to indicate the result. - */ - bool handleRights(const NodeImpl *curNode); - - /** - * Handle the xml dom node which contains the element. - * @param curNode the dom node which contains element. - * @return true/false to indicate the result. - */ - bool handleAgreement(const NodeImpl *curNode); - - /** - * Handle the xml dom node which contains the element. - * @param curNode the dom node which contains element. - * @return true/false to indicate the result. - */ - bool handleAsset(const NodeImpl *curNode); - - /** - * Handle the xml dom node which contains the element. - * @param curNode the dom node which contains element. - * @return true/false to indicate the result. - */ - bool handlePermission(const NodeImpl *curNode); - - /** - * Get the constraint in xml dom node. - * @param curNode the dom node which contains constraint. - * @return the constraint. - */ - Constraint* getConstraint(const NodeImpl *curNode); - - /** - * Convert ISO8601 time to long. - * @param ts the string with ISO8601 time. - * @return the result value. - */ - long convertISO8601DateTimeToLong(const char* ts); - - /** - * Convert ISO8601 period to long. - * @param ts the string with ISO8601 period. - * @return the result value. - */ - long convertISO8601PeriodToLong(const char* ts); - - /** - * Load the rights related with specific contentinto content rights list. - * @param contentID the specific content id. - */ - void loadRights(const string& contentID); - - /** - * Free the current content rights list. - */ - void freeRights(); - -PRIVATE: - /** - * Disable the assignment between rights. - */ - Ro& operator=(const Ro& ro); - - /** - * Disable copy constructor. - */ - Ro(const Ro& ro); - -public: - vector mAssetList; - vector mRightList; - -PRIVATE: - string mRoID; /** the Ro id. */ - string mRoVersion; /** the Ro version. */ - XMLDocumentImpl *mDoc; /**< the xml document handle. */ - vector mContentRightList; /**< the right list to store the result related with specific content. */ - Right* mProperRight; /**< the right to consume. */ -}; -#endif diff --git a/media/libdrm/mobile2/include/rights/RoManager.h b/media/libdrm/mobile2/include/rights/RoManager.h deleted file mode 100644 index 71e9eef2b8077c0b0885c27bbedf17f4dd77c1e5..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/rights/RoManager.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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. - */ -#ifndef _ROMANAGER_H -#define _ROMANAGER_H - -#include -#include -#include - -using namespace ustl; - -class RoManager { - -public: - /** - * Singleton instance function. - * @return the singleton pointer. - */ - static RoManager* Instance(); - - /** - * Destructor for ExpatWrapper. - */ - ~RoManager(); - - /** - * Install Ro from stream. - * @param roStream the input ro stream. - * @return the status of installaltion. - */ - Ro::ERRCODE installRo(istringstream *roStream); - - /** - * Check whether Ro in cache or not. - * @param roID the specific roID. - * @return true/false to indicate result. - */ - bool checkRoInCache(const string& roID); - - /** - * Get the ro. - * @param roID the specific id of ro. - * @return NULL if not found otherwise return ro. - */ - Ro* getRo(const string& roID); - - /** - * Get all the Ro. - * @return ro list. - */ - vector getAllRo(); - - /** - * Get ro which contained rights of specific content. - * @param contentID the specific id of content. - * @return NULL if not fount otherwise the related ro. - */ - Ro* getRoByContentID(const string& contentID); - - /** - * Delete Ro by its id. - * @param roID the specific roID. - * @return true/false to indicate the result. - */ - bool deleteRo(const string& roID); - - -PRIVATE: - /** - * Constructor for RoManager. - */ - RoManager(); - -PRIVATE: - static RoManager* msInstance; /**< singleton instance pointer. */ - vector mRoList; /**< the ro list. */ -}; - -#endif diff --git a/media/libdrm/mobile2/include/roap/Registration.h b/media/libdrm/mobile2/include/roap/Registration.h deleted file mode 100644 index 0beed8edfc315f6eb57b071d7712202ceda14f4a..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/roap/Registration.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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. - */ -#ifndef _REGISTRATION_ -#define _REGISTRATION_ - -#include - -class Registration : public RoapMessageHandler -{ -public: - /** - * Constructor for Registration. - * @param type the address of RI. - */ - Registration(string riAddres); - - /** - * Registration with the RI. - * @return the result of registration. - */ - int16_t registerWithRI(); - - /** - * Create one specified client message based on message template xml file. - * @param type the message type. - * @return the pointer of the document object of the message if successful,otherwise - * return NULL. - */ - XMLDocumentImpl* createClientMsg(int16_t type); -} -#endif _REGISTRATION_ diff --git a/media/libdrm/mobile2/include/roap/RoapMessageHandler.h b/media/libdrm/mobile2/include/roap/RoapMessageHandler.h deleted file mode 100644 index c31047fa503901bbff2440f72652b5571393d050..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/roap/RoapMessageHandler.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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. - */ -#ifndef _ROAPMESSAGEHADLER_ -#define _ROAPMESSAGEHADLER_ - -#include -#include - -class RoapMessageHandler -{ -public: - /** - * define all the client message types. - */ - enum msgType {DeviceHello=1,RegistrationRequest,RORequest}; - - /** - * Constructor for DrmManager,used to open local dcf file. - * @param type the message type. - */ - RoapMessageHandler(); - - /** - * Create one specified client message based on message template xml file. - * @param type the message type. - * @return the pointer of the document object of the message if successful,otherwise - * return NULL. - */ - XMLDocumentImpl* createClientMsg(msgType type); - - /** - * Handle received message from RI. - * @return true if successful, otherwise return false. - */ - bool handlePeerMsg(); - - /** - * Send the client message to RI - */ - int16_t send(); - - /** - * Receive message from RI and parse it - * @return the pointer of the parsed document. - */ - XMLDocumentImpl* receive(); - -PROTECTED: - XMLDocumentImpl * mDoc; -PRIVATE: - int16_t mMsgType; -}; -#endif //_ROAPMESSAGEHADLER_ diff --git a/media/libdrm/mobile2/include/util/crypto/DrmCrypto.h b/media/libdrm/mobile2/include/util/crypto/DrmCrypto.h deleted file mode 100644 index 10e7bc1ff19b1fcbd04ab3a6ee61b4a9d827d0d3..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/crypto/DrmCrypto.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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. - */ - -#ifndef _DRMCRYPTO_H_ -#define _DRMCRYPTO_H_ - -#include -#include -#include -#include -#include - -// AES encrypt mode -typedef enum {AES_128_CBC = 0x01,AES_128_CTR = 0x02}AesMode; - -// aes crypto for decrypt -class AesAgent -{ - public: - AesAgent(const AesMode method,const unsigned char* decryptedKey) - :mode(method),AesKey(decryptedKey){}; - - /** - * decrypt data using AES, now only support 128 bits CBC - * \param iv 128 bits initialization vector/counter - * prefixing the ciphertext - * \param encData encrypted data - * \param encLen the length of encData - * \param decData the buffer to store decrypted data - * \param decLen the actual length of decrypted data - * \return - * >= succeed, the padding length - * < 0 failed - */ - int32_t decContent( unsigned char* iv, - const unsigned char* encData, - const unsigned long encLen, - unsigned char* decData); - static const int32_t AES_DEC_FAILED = -1; - - PRIVATE: - static const uint32_t AES_KEY_BITS = 128; - const AesMode mode; - const unsigned char* AesKey; - - PRIVATE: - // get the actual length of decrypt data - void discardPaddingByte(unsigned char* decryptedBuf,unsigned long* decryptedBufLen); -}; - -// Sha1 crypto for hash -class Sha1Agent -{ - public: - /** - * compute hash using Sha1 - * \param inData the data to be hashed - * \param inLen the length of inData - * \param outHash the hash of inData - * \return none - */ - void computeHash( const unsigned char* inData, - unsigned long inLen, - unsigned char* outHash) const; - - /** - * get the length of SHA1 hash - * \param none - * \return - * the length of SHA1 hash - */ - unsigned long getShaLen(void) const - { - return SHA_DIGEST_LENGTH; - } -}; - -// Hmac-Sha1 crypto for MAC -class HmacSha1Agent -{ - public: - HmacSha1Agent(const unsigned char* Key, int key_len) - :macKey(Key),keyLen(key_len){}; - - /** - * compute MAC using Hmac-Sha1 - * \param inData the data to be MAC - * \param inLen the length of inData - * \param outMac the MAC of inData - * \return none - */ - void computeMac( const unsigned char* inData, - unsigned long inLen, - unsigned char* outMac) const; - - /** - * get the length of HMAC-SHA1 MAC - * \param none - * \return - * the length of HMAC-SHA1 MAC - */ - unsigned long getHmacLen(void) const - { - return SHA_DIGEST_LENGTH; - } - - PRIVATE: - const unsigned char* macKey; - const int keyLen; -}; - -// Rsa crypto for signature,verify signature and key transport -class RsaAgent -{ - public: - RsaAgent(RSA& Key):rsaKey(Key) - { - rsaSize = (unsigned int)RSA_size(&Key); - }; - - // signature algorithm - typedef enum {RSA_PSS,RSA_SHA1}RsaAlg; - - /** - * Do signature using RSA-PSS - * \param rawData the data to be signature - * \param rawLen the length of inData - * \param sigData the buffer to store the signature of rawData - * \param sigAlg signature algorithm - * \return - * true succeed - * false failed - */ - bool signature( const unsigned char* rawData, - const unsigned long rawLen, - unsigned char* sigData, - const RsaAlg sigAlg); - - /** - * get the length of signature - * \param none - * \return - * the length of signature - */ - unsigned int getSigLen(void) const - { - return rsaSize; - } - - /** - * Verify signature using RSA-PSS - * \param sigData the data to be verify - * \param sigLen the length of sigData - * \param rawData the data from which the sigData generated - * \param rawLen the length of rawData - * \param sigAlg signature algorithm - * \return - * true succeed - * false failed - */ - bool sigVerify(unsigned char* sigData, - unsigned long sigLen, - const unsigned char* rawData, - const unsigned long rawLen, - const RsaAlg sigAlg); - - - /** - * Decrypt data using RSA - * \param encData encrypted data - * \param encLen the length of encData - * \param decData the buffer to store decrypted data - * \return - * -1 decrypted failed - * >0 the actual length of decrypted data - */ - int decrypt( const unsigned char* encData, - const unsigned long encLen, - unsigned char* decData); - - /** - * get the length of decrypted data - * \param none - * \return - * the length of decrypted data - */ - unsigned int getDecLen(void) const - { - return rsaSize; - } - - PRIVATE: - RSA& rsaKey; - unsigned int rsaSize; -}; - - -#endif /* _DRMCRYPTO_H_ */ diff --git a/media/libdrm/mobile2/include/util/domcore/CharacterDataImpl.h b/media/libdrm/mobile2/include/util/domcore/CharacterDataImpl.h deleted file mode 100644 index d1ab31e980d2474571e4666ec698a73fc26501e3..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/CharacterDataImpl.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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. - */ -#ifndef __CHARACTER_IMPL__ -#define __CHARACTER_IMPL__ - -#include "NodeImpl.h" -#include "DOMString.h" - -class CharacterDataImpl : public NodeImpl -{ -private: - DOMString* charData; -public: - - /** - * Default Constructor for CharacterDataImpl. - */ - CharacterDataImpl(); - - /** - * Constructor for CharacterDataImpl. - * @param data The specify character data. - */ - CharacterDataImpl(const DOMString* data); - - /** - * The character data of the node that implements this interface. The DOM - * implementation may not put arbitrary limits on the amount of data - * that may be stored in a CharacterData node. However, - * implementation limits may mean that the entirety of a node's data may - * not fit into a single DOMString. In such cases, the user - * may call substringData to retrieve the data in - * appropriately sized pieces. - * @exception DOMException - * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. - * @exception DOMException - * DOMSTRING_SIZE_ERR: Raised when it would return more characters than - * fit in a DOMString variable on the implementation - * platform. - * @return the character data. - */ - const DOMString* getData() const throw (DOMException); - - /** - * The character data of the node that implements this interface. The DOM - * implementation may not put arbitrary limits on the amount of data - * that may be stored in a CharacterData node. However, - * implementation limits may mean that the entirety of a node's data may - * not fit into a single DOMString. In such cases, the user - * may call substringData to retrieve the data in - * appropriately sized pieces. - * @param data the specify character data. - * @exception DOMException - * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. - * @exception DOMException - * DOMSTRING_SIZE_ERR: Raised when it would return more characters than - * fit in a DOMString variable on the implementation - * platform. - */ - void setData(const DOMString* data) throw (DOMException); - - /** - * The number of 16-bit units that are available through data - * and the substringData method below. This may have the - * value zero, i.e., CharacterData nodes may be empty. - * @return the size of characters data. - */ - int getLength() const; - - /** - * Append the string to the end of the character data of the node. Upon - * success, data provides access to the concatenation of - * data and the DOMString specified. - * @param arg The DOMString to append. - * @exception DOMException - * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. - */ - void appendData(const DOMString* arg) throw(DOMException); - - /** Override getNodeValue() method in NodeImpl.h.*/ - const DOMString* getNodeValue() const throw(DOMException); - - /** Override setNodeValue() method in NodeImpl.h */ - void setNodeValue(DOMString* nodeValue) throw(DOMException); - - ~CharacterDataImpl(); -}; -#endif /*__CHARACTER_IMPL__*/ - diff --git a/media/libdrm/mobile2/include/util/domcore/DOMException.h b/media/libdrm/mobile2/include/util/domcore/DOMException.h deleted file mode 100644 index 416519b0208ae2db6259e41f58ab2ec0761262a6..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/DOMException.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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. - */ -#ifndef __DOM_EXCEPTION__ -#define __DOM_EXCEPTION__ - -#include -using namespace ustl; - -/** - * DOM operations only raise exceptions in "exceptional" circumstances, i.e., - * when an operation is impossible to perform (either for logical reasons, because data is lost, - * or because the implementation has become unstable). In general, DOM methods return specific error - * values in ordinary processing situations, such as out-of-bound errors when using NodeList. - *

    Implementations should raise other exceptions under other circumstances. For example, implementations - * should raise an implementation-dependent exception if a null argument is passed. - * Some languages and object systems do not support the concept of exceptions. - * For such systems, error conditions may be indicated using native error reporting mechanisms. - * For some bindings, for example, methods may return error codes similar to those listed in the corresponding - * method descriptions. - */ -class DOMException : public exception { - - private: - short code; - public: - DOMException(short code) - { - this->code = code; - } - public: - - enum ExceptionReason { - /** - * If index or size is negative, or greater than the allowed value - */ - INDEX_SIZE_ERR = 1, - - /** - * If the specified range of text does not fit into a DOMString - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - DOMSTRING_SIZE_ERR = 2, - /** - * If any node is inserted somewhere it doesn't belong - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - HIERARCHY_REQUEST_ERR = 3, - - /** - * If a node is used in a different document than the one that created it - * (that doesn't support it) - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - WRONG_DOCUMENT_ERR = 4, - - /** - * If an invalid or illegal character is specified, such as in a name. See - * production 2 in the XML specification for the definition of a legal - * character, and production 5 for the definition of a legal name - * character. - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - INVALID_CHARACTER_ERR = 5, - - /** - * If data is specified for a node which does not support data - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - NO_DATA_ALLOWED_ERR = 6, - - /** - * If an attempt is made to modify an object where modifications are not - * allowed - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - NO_MODIFICATION_ALLOWED_ERR = 7, - - /** - * If an attempt is made to reference a node in a context where it does - * not exist - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - NOT_FOUND_ERR = 8, - - /** - * If the implementation does not support the requested type of object or - * operation. - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - NOT_SUPPORTED_ERR = 9, - - /** - * If an attempt is made to add an attribute that is already in use - * elsewhere - */ - INUSE_ATTRIBUTE_ERR = 10, - - /** - * If an attempt is made to use an object that is not, or is no longer, - * usable. - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - INVALID_STATE_ERR = 11, - - /** - * If an invalid or illegal string is specified. - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - SYNTAX_ERR = 12, - - /** - * If an attempt is made to modify the type of the underlying object. - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - INVALID_MODIFICATION_ERR = 13, - - /** - * If an attempt is made to create or change an object in a way which is - * incorrect with regard to namespaces. - * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - NAMESPACE_ERR = 14, - - /** - * If a parameter or an operation is not supported by the underlying - * object. - * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html - */ - INVALID_ACCESS_ERR = 15, - }; -public: - /** - * Return the exception reason. - * @return the exception reason. - */ - short getCode() const - { - return code; - } -}; -#endif /*__DOMEXCEPTION__*/ - diff --git a/media/libdrm/mobile2/include/util/domcore/DOMString.h b/media/libdrm/mobile2/include/util/domcore/DOMString.h deleted file mode 100644 index f6f2b14d12c993c99392eb37893485a6923e93ff..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/DOMString.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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. - */ -#ifndef __DOM_STRING_H__ -#define __DOM_STRING_H__ - -#include -using namespace ustl; -typedef string DOMString; - -const DOMString emptyString = DOMString(""); - -#endif /*__DOM_STRING_H_*/ - diff --git a/media/libdrm/mobile2/include/util/domcore/DocumentImpl.h b/media/libdrm/mobile2/include/util/domcore/DocumentImpl.h deleted file mode 100644 index b003e2aefc2d52becb9d5a56b0fb1380c7385a57..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/DocumentImpl.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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. - */ -#ifndef __DOM_DOCUMENT_IMPL__ -#define __DOM_DOCUMENT_IMPL__ -#include "DOMString.h" -#include "NodeImpl.h" -#include "ElementImpl.h" -#include "NodeType.h" -#include "TextImpl.h" -#include "NodeListImpl.h" -#include "DOMException.h" - -class DocumentImpl : public NodeImpl -{ -private: - const static DOMString nodeName; -public: - /** - * Default constructor for DocumentImpl. - */ - DocumentImpl(); - /** - * This is a convenience attribute that allows direct access to the child - * node that is the root element of the document. For HTML documents, - * this is the element with the tagName "HTML". - * @return the pointer to element. - */ - virtual ElementImpl* getDocumentElement() const; - - /** - * Creates an element of the type specified. Note that the instance - * returned implements the Element interface, so attributes - * can be specified directly on the returned object. - *
    In addition, if there are known attributes with default values, - * Attr nodes representing them are automatically created - * and attached to the element. - *
    To create an element with a qualified name and namespace URI, use - * the createElementNS method. - * @param tagName The name of the element type to instantiate. For XML, - * this is case-sensitive. For HTML, the tagName - * parameter may be provided in any case, but it must be mapped to the - * canonical uppercase form by the DOM implementation. - * @return A new Element object with the - * nodeName attribute set to tagName, and - * localName, prefix, and - * namespaceURI set to null. - * @exception DOMException - * INVALID_CHARACTER_ERR: Raised if the specified name contains an - * illegal character. - */ - virtual ElementImpl* createElement(const DOMString* tagName) const throw (DOMException); - - /** - * Creates a Text node given the specified string. - * @param data The data for the node. - * @return The new Text object. - */ - virtual TextImpl* createTextNode(const DOMString* data) const; - - /** - * Returns a NodeList of all the Elements with a - * given tag name in the order in which they are encountered in a - * preorder traversal of the Document tree. - * @param tagname The name of the tag to match on. The special value "*" - * matches all tags. - * @return A new NodeList object containing all the matched - * Elements. - */ - NodeListImpl* getElementsByTagName(const DOMString* tagname) const; - - /** Override getNodeName method in NodeImpl.h.*/ - const DOMString* getNodeName() const; - - /** Override getNodeType method in NodeImpl.h.*/ - NodeType getNodeType() const; - - /** - * - * Event Triggered after loaded the document. - */ - virtual bool onLoad(){return true;} - - /** - * - * Event Triggered when close or switch the document. - */ - virtual bool onUnLoad(){return true;} - - ~DocumentImpl(); -}; -#endif /*__DOM_DOCUMENT_IMPL__*/ diff --git a/media/libdrm/mobile2/include/util/domcore/ElementImpl.h b/media/libdrm/mobile2/include/util/domcore/ElementImpl.h deleted file mode 100644 index 2b0bc45a949fa07fc36aeb91641d33223f4d0a2a..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/ElementImpl.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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. - */ -#ifndef __DOM_ELEMENT_IMPL__ -#define __DOM_ELEMENT_IMPL__ -#include "NodeImpl.h" -#include "NodeListImpl.h" -#include "NodeType.h" - -class ElementImpl : public NodeImpl -{ -public: - - /** - * The name of the element. For example, in: - *

     <elementExample
    -         * id="demo"> ... </elementExample> , 
    - * tagName has - * the value "elementExample". Note that this is - * case-preserving in XML, as are all of the operations of the DOM. The - * HTML DOM returns the tagName of an HTML element in the - * canonical uppercase form, regardless of the case in the source HTML - * document. - * @return the element's tag name. - */ - virtual const DOMString* getTagName() const; - - /** - * Retrieves an attribute value by name. - * @param name The name of the attribute to retrieve. - * @return The Attr value as a string, or the empty string - * if that attribute does not have a specified or default value. - */ - virtual const DOMString* getAttribute(const DOMString* name) const; - - /** - * Adds a new attribute. If an attribute with that name is already present - * in the element, its value is changed to be that of the value - * parameter. This value is a simple string; it is not parsed as it is - * being set. So any markup (such as syntax to be recognized as an - * entity reference) is treated as literal text, and needs to be - * appropriately escaped by the implementation when it is written out. - * In order to assign an attribute value that contains entity - * references, the user must create an Attr node plus any - * Text and EntityReference nodes, build the - * appropriate subtree, and use setAttributeNode to assign - * it as the value of an attribute. - *
    To set an attribute with a qualified name and namespace URI, use - * the setAttributeNS method. - * @param name The name of the attribute to create or alter. - * @param value Value to set in string form. - * @exception DOMException - * INVALID_CHARACTER_ERR: Raised if the specified name contains an - * illegal character. - *
    NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. - */ - virtual void setAttribute(const DOMString* name, const DOMString* value) throw (DOMException); - - /** - * Removes an attribute by name. If the removed attribute is known to have - * a default value, an attribute immediately appears containing the - * default value as well as the corresponding namespace URI, local name, - * and prefix when applicable. - *
    To remove an attribute by local name and namespace URI, use the - * removeAttributeNS method. - * @param name The name of the attribute to remove. - * @exception DOMException - * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. - */ - virtual void removeAttribute(const DOMString* name) throw (DOMException); - - /** - * Returns a NodeList of all descendant Elements - * with a given tag name, in the order in which they are encountered in - * a preorder traversal of this Element tree. - * @param name The name of the tag to match on. The special value "*" - * matches all tags. - * @return A list of matching Element nodes. - */ - NodeListImpl* getElementsByTagName(const DOMString* name) const; - - /** Override getNodeType() method in NodeImpl.h.*/ - virtual bool hasAttributes() const; - - /** Override getNodeName() method in NodeImpl.h.*/ - const DOMString* getNodeName() const; - - /** Override getNodeType() method in NodeImpl.h.*/ - NodeType getNodeType() const; - - /** Defining "click()" method*/ - virtual void click(){} - - /** Defining "blur()" method,*/ - virtual void blur(){} - - /** Defining "focus()" method*/ - virtual void focus(){} - - /** Defining "change()" method*/ - virtual void change(){} - - /** Defining "select()" method*/ - virtual void select(){} - - /** Defining "onClick()" event input,textarea,button, and anchor*/ - virtual bool onClick(){return true;} - - /** Defining "onBlur()" event,for input,textarea,button,anchor and select */ - virtual bool onBlur(){return true;} - - /** Defining "onFocus()" event,for input,textarea,button,anchor and select*/ - virtual bool onFocus(){return true;} - - /** Defining "onChange()" event,for input,textarea and select tag*/ - virtual bool onChange(){return true;} - - /** Defining "onSelect()" event,for textarea and input*/ - virtual bool onSelect(){return true;} - - /** - * when the end tag of one element is found,this method would be called.The basic action is call seCompleted(). - **/ - virtual void endElement() {} - -private: - /** - * Get elements whose name match on name,than keep they into nodeList. - * @param name The tag name of the elements to match on. - * @param nodeList keep all the matched element. - */ - void getElementsByTagName(const DOMString* name,NodeListImpl* nodeList) const; -}; -#endif /*__DOM_ELEMENT_IMPL__*/ - diff --git a/media/libdrm/mobile2/include/util/domcore/NodeImpl.h b/media/libdrm/mobile2/include/util/domcore/NodeImpl.h deleted file mode 100644 index 10423c3b63e01536fd87c7215b1c9ba078a4578c..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/NodeImpl.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * 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. - */ -#ifndef __DOM_NODE_IMPL__ -#define __DOM_NODE_IMPL__ - -#include "DOMException.h" -#include "NodeType.h" -#include "DOMString.h" -class LayoutAttr; -class DocumentImpl; -class NodeImpl { -private: - /** The pointer to first children */ - NodeImpl* firstChild; - - /** The pointer to lastChild children */ - NodeImpl* lastChild; - - /** The pointer to previous sibling children */ - NodeImpl* previousSibling; - - /** The pointer to next sibling children */ - NodeImpl* nextSibling; - - /** The pointer to parent */ - NodeImpl* parent; - - /** Current node's document context */ - const DocumentImpl* document; - - /** - * Add next slibing node - * @param node the node to be add. - */ - void appendNextSibling(NodeImpl* node); - -public: - /** - * Default constuctor. - */ - NodeImpl(): firstChild(NULL),lastChild(NULL),previousSibling(NULL),nextSibling(NULL),parent(NULL),document(NULL) {}; - - /** - * Set parentNode as current node's parent. - * - * @param parentNode The specify parent node. - */ - void setParent(NodeImpl* parentNode); - - /** - * Set the node immediately following node. - * - * @param siblingNode The special node be insert after current node. - */ - void setNextSibling(NodeImpl* siblingNode); - - /** - * Returns the node immediately preceding this node. - * - * @param siblingNode The special node be insert before current node. - */ - void setPreviousSibling(NodeImpl* siblingNode); - - /** - * Set childNode as current node's first children. If current - * node have first child node,it will replace with the childNode. - * - * @param childNode The special node be set as the first children node of current - * node. - */ - void setFirstChild(NodeImpl* childNode); - - /** - * Set childNode as current node's last children. If current - * node have last child node,it will replace with the childNode. - * - * @param childNode The special node be set as the last children node of current - * node. - */ - void setLastChild(NodeImpl* childNode); - - /** - * The name of this node, depending on its type; - * @return the node's name. - */ - virtual const DOMString* getNodeName() const = 0; - - /** - * The value of this node, depending on its type; - * When it is defined to be null, setting it has no effect. - * @return the value of node. - * @exception DOMException - * DOMSTRING_SIZE_ERR: Raised when it would return more characters than - * fit in a DOMString variable on the implementation - * platform. - */ - virtual const DOMString* getNodeValue() const throw (DOMException); - - /** - * Set the node value. - * @param nodeValue the node value - * @exception DOMException - * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly. - */ - virtual void setNodeValue(DOMString* nodeValue) throw (DOMException); - - /** - * A code representing the type of the underlying object, as defined above. - * @return the node's type. - */ - virtual NodeType getNodeType() const = 0; - - /** - * Returns whether this node (if it is an element) has any attributes. - * @return true if this node has any attributes, - * false otherwise. - * @since DOM Level 2 - */ - virtual bool hasAttributes() const; - - /** - * The parent of this node. All nodes, except Attr, - * Document, DocumentFragment, - * Entity, and Notation may have a parent. - * However, if a node has just been created and not yet added to the - * tree, or if it has been removed from the tree, this is - * NULL. - * @return return current node's parent. - */ - NodeImpl* getParentNode() const; - - /** - * The first child of this node. If there is no such node, this returns - * NULL. - * @return current node first children. - */ - NodeImpl* getFirstChild() const; - - /** - * The last child of this node. If there is no such node, this returns - * NULL. - * @return current node last children. - */ - NodeImpl* getLastChild() const; - - /** - * The node immediately preceding this node. If there is no such node, - * this returns NULL. - * @return current node previous sibling children. - */ - NodeImpl* getPreviousSibling() const; - - /** - * The node immediately following this node. If there is no such node, - * this returns NULL. - * @return return current node next sibling children. - */ - NodeImpl* getNextSibling() const; - - /** - * Inserts the node newChild before the existing child node - * refChild. If refChild is NULL, - * insert newChild at the end of the list of children. - *
    If newChild is a DocumentFragment object, - * all of its children are inserted, in the same order, before - * refChild. If the newChild is already in the - * tree, it is first removed. - * @param newChild The node to insert. - * @param refChild The reference node, i.e., the node before which the - * new node must be inserted. - * @return The node being inserted. - * @exception DOMException - * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not - * allow children of the type of the newChild node, or if - * the node to insert is one of this node's ancestors or this node - * itself. - *
    WRONG_DOCUMENT_ERR: Raised if newChild was created - * from a different document than the one that created this node. - *
    NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly or - * if the parent of the node being inserted is readonly. - *
    NOT_FOUND_ERR: Raised if refChild is not a child of - * this node. - */ - NodeImpl* insertBefore(NodeImpl* newChild, NodeImpl* refChild) throw (DOMException); - - /** - * Removes the child node indicated by oldChild from the list - * of children, and returns it. - * @param oldChild The node being removed. - * @return The node removed. - * @exception DOMException - * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. - *
    NOT_FOUND_ERR: Raised if oldChild is not a child of - * this node. - */ - NodeImpl* removeChild(NodeImpl* oldChild) throw (DOMException); - - /** - * Adds the node newChild to the end of the list of children - * of this node. If the newChild is already in the tree, it - * is first removed. - * @param newChild The node to add.If it is a - * DocumentFragment object, the entire contents of the - * document fragment are moved into the child list of this node - * @return The node added. - * @exception DOMException - * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not - * allow children of the type of the newChild node, or if - * the node to append is one of this node's ancestors or this node - * itself. - *
    WRONG_DOCUMENT_ERR: Raised if newChild was created - * from a different document than the one that created this node. - *
    NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly or - * if the previous parent of the node being inserted is readonly. - */ - NodeImpl* appendChild(NodeImpl* newChild) throw (DOMException); - - /** - * Returns whether this node has any children. - * @return true if this node has any children, - * false otherwise. - */ - bool hasChildNodes() const; - - virtual ~NodeImpl() {}; - - /** - * Get the LayoutAttr of this node - * @return the pointer to LayoutAttr - */ - virtual LayoutAttr* getLayoutAttr() const { return NULL;} - - /** - * Set the LayoutAttr of this node - * @param attr the attributes to be set - * @return void - */ - virtual void setLayoutAttr(LayoutAttr* attr) { return;} - - /** - * Set document context. - * @param document The specify document context. - */ - void setDocument(const DocumentImpl* document); - - /** - * Get document context. - * @return the current node's document context. - */ - const DocumentImpl* getDocument() const; -}; -#endif /*__DOM_NODE_IMPL__*/ - diff --git a/media/libdrm/mobile2/include/util/domcore/NodeIterator.h b/media/libdrm/mobile2/include/util/domcore/NodeIterator.h deleted file mode 100644 index 06fda2879fccedf4dea4420452f48f72948fd1de..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/NodeIterator.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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. - */ -#ifndef __DOM_NODE_ITERATOR__ -#define __DOM_NODE_ITERATOR__ -class NodeImpl; -/** - * The Iterator is used to visit DOM_TREE. - * Attention:The Iterator is not safe. - * When the caller using the Iterator to access the tree, - * the underlying data was modified, the next() or prev() may not return the right result. - * means we have a restriction: the Iterator can only be used in the case that the tree structure will - * not be modified before the end of iteration. - */ -class NodeIterator { -private: - NodeImpl* scopeNode;/** The specify the range of iterating */ - NodeImpl* endNode; /** The specify the end position of iterating */ - NodeImpl* curNode; /** The position of current node.*/ - - /** - * Find the specify node's next order node. - * @param node The specify node. - * @return The next order node when success. - * NULL when has an error. - */ - NodeImpl* findNextOrderNode(NodeImpl* node); - - /** - * Find the specify node's previous order node. - * @param node The specify node. - * @return The previous order node when success. - * NULL when has an error. - */ - NodeImpl* findPreviousOrderNode(NodeImpl* node); -public: - /** - * Construct for NodeIterator. - * we must specify start value when we want iterate the DOM_TREE. - * and we also can specify the scope if want restrict the range of iterator. - * (eg: restrict the range of iterating at a subtree).otherwise it will iterate the whole DOM_TREE. - * @param start The start position. - * @param scope The scope of iterating. - * @param end The end position of iterating. - */ - NodeIterator(NodeImpl* start, NodeImpl* scope = NULL, NodeImpl* end = NULL); - - /** - * Get next order node at current position in DOM_TREE. - * @return NULL On there is not node can be get. - * The pointer of node On can get next node. - */ - NodeImpl* next(); - - /** - * Get next order node at current position in DOM_TREE. - * @return NULL On there is not node can be get. - * The pointer of node On can get previous node. - */ - NodeImpl* prev(); -}; -#endif /* __DOM_NODE_ITERATOR__ */ diff --git a/media/libdrm/mobile2/include/util/domcore/NodeListImpl.h b/media/libdrm/mobile2/include/util/domcore/NodeListImpl.h deleted file mode 100644 index 07c0a6a29c519ea7df8fe4ce1de07caa67198242..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/NodeListImpl.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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. - */ -#ifndef __NODE_LIST_IMPL__ -#define __NODE_LIST_IMPL__ - -#include "NodeImpl.h" -#include "Vector.h" -class NodeListImpl { -private: - vector nodeList; -public: - /** - * Add a special node into list. - * @param newNode specify component. - */ - void append(const NodeImpl* newNode); - - /** - * Return The special position node pointer. - * @param index The special position. - * @return The node's pointer on success. - * NULL when out of list's boundary. - */ - const NodeImpl* item(int index) const; - - /** - * Return the length of list. - * @return the length of list. - */ - int getLength() const; - - ~NodeListImpl(); -}; -#endif /*__NODE_LIST_IMPL__ */ - diff --git a/media/libdrm/mobile2/include/util/domcore/NodeType.h b/media/libdrm/mobile2/include/util/domcore/NodeType.h deleted file mode 100644 index 0e51a631bd5e7c97c8918f9685349d8bc03e60a4..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/NodeType.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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. - */ -#ifndef __DOM_NODE_TYPE__ -#define __DOM_NODE_TYPE__ -enum NodeType { - /** - * The node is an Element. - */ - ELEMENT_NODE = 1, - /** - * The node is an Attr. - */ - ATTRIBUTE_NODE = 2, - /** - * The node is a Text node. - */ - TEXT_NODE = 3, - /** - * The node type is CDATASection. - */ - CDATA_SECTION_NODE = 4, - /** - * The node type is an EntityReference. - */ - ENTITY_REFERENCE_NODE = 5, - /** - * The node type is an Entity. - */ - ENTITY_NODE = 6, - /** - * The node type is a ProcessingInstruction. - */ - PROCESSING_INSTRUCTION_NODE = 7, - /** - * The node is a Comment - */ - COMMENT_NODE = 8, - /** - * The node is a Document. - */ - DOCUMENT_NODE = 9, - /** - * The node is a DocumentType. - */ - DOCUMENT_TYPE_NODE = 10, - /** - * The node is a DocumentFragment. - */ - DOCUMENT_FRAGMENT_NODE = 11, - /** - * The node is a Notation. - */ - NOTATION_NODE = 12, -}; -#endif diff --git a/media/libdrm/mobile2/include/util/domcore/TextImpl.h b/media/libdrm/mobile2/include/util/domcore/TextImpl.h deleted file mode 100644 index fc55fcde1891b81e1d6b7e43e5195c79c1001707..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/TextImpl.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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. - */ -#ifndef __DOM_TEXT_IMPL__ -#define __DOM_TEXT_IMPL__ -#include "CharacterDataImpl.h" -class TextImpl:public CharacterDataImpl -{ -private: - const static DOMString nodeName; -public: - /** Text default constructor for TextImpl.*/ - TextImpl(); - - /** - * Constructor for TextImpl - * @param data The specify data to be set. - */ - TextImpl(const DOMString* data); - - /** Override getNodeType method in NodeImpl.h */ - NodeType getNodeType() const; - - /** Override getNodeName method in NodeImpl.h */ - const DOMString* getNodeName() const; -}; -#endif /*__DOM_TEXT_IMPL__*/ - diff --git a/media/libdrm/mobile2/include/util/domcore/Vector.h b/media/libdrm/mobile2/include/util/domcore/Vector.h deleted file mode 100644 index 8ceae3baaca166cce94d5ceccad0d49f951f39c6..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/Vector.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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. - */ -#ifndef __VECTOR_H__ -#define __VECTOR_H__ -#include -using namespace ustl; -#endif /*__VECTOR_H__*/ - diff --git a/media/libdrm/mobile2/include/util/domcore/stack.h b/media/libdrm/mobile2/include/util/domcore/stack.h deleted file mode 100644 index cfcf4e5b20a444f1169e3674fc566610bd9a4a84..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/domcore/stack.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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. - */ -#ifndef __STACK_H__ -#define __STACK_H__ -#include -using namespace ustl; -#endif /*__STACK_H__*/ - diff --git a/media/libdrm/mobile2/include/util/xml/DomExpatAgent.h b/media/libdrm/mobile2/include/util/xml/DomExpatAgent.h deleted file mode 100644 index 9972d5ba98c2b2123ea7923a388d56729045e6e2..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/xml/DomExpatAgent.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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. - */ -#ifndef _DOMEXPATAGENT_ -#define _DOMEXPATAGENT_ - -#include -#include -#include -#include -#include -#include -#include -#include "ExpatWrapper.h" -#include "XMLElementImpl.h" -#include "XMLDocumentImpl.h" -using namespace ustl; - -class DomExpatAgent : public ExpatWrapper { -public: - /** - * Constructor for DomExpatAgent. - * @param xmlDocPtr XMLDocument pointer. - */ - DomExpatAgent(XMLDocumentImpl* xmlDocPtr); - - /** Destructor for DomExpatAgent. */ - ~DomExpatAgent(); - - /** - * Generate XML DOM Document from XML source. - * @param xmlStream the XML source stream. - * @return ture or false to indicate whether generate successfully. - */ - bool generateDocumentFromXML(istringstream *xmlStream); - - /** - * Generate XML stream from XML DOM document. - * @return xml stream. - */ - ostringstream* generateXMLFromDocument(); - - /** - * deal with start element in Expat. - */ - virtual void startElement(const XML_Char *name, - const XML_Char **atts); - - /** - * deal with end element for Expat. - */ - virtual void endElement(const XML_Char *name); - - /** - * deal with data handler for Expat. - */ - virtual void dataHandler(const XML_Char *s, int len); - -PRIVATE: - /** - * Push a xml element with the specific tag name into stack. - * @param name The name of tag. - * @param atts The attributes of related tag. - */ - void pushTag(const DOMString *name, const XML_Char **atts); - - /** - * Append text into top element of stack. - * @param text The data related to the present tag. - */ - void appendText(const DOMString *text); - - /** - * Pop the xml element with the specific tag name. - * @param name The name of tag. - */ - void popTag(const DOMString *name); - - /** - * Traverse the XML DOM document starting from specific element. - * @param root The specific element start to traverse. - */ - void traverse(ElementImpl *root); - -PRIVATE: - vector mStack; /**< the stack to manage the tag. */ - XMLElementImpl* mTopElementPtr; /**< the top element of the stack. */ - XMLDocumentImpl* mXMLDocumentPtr; /**< XML DOM document pointer. */ - ostringstream mXMLostream; /**< xml output stream. */ -}; - -#endif diff --git a/media/libdrm/mobile2/include/util/xml/ExpatWrapper.h b/media/libdrm/mobile2/include/util/xml/ExpatWrapper.h deleted file mode 100644 index 5a2d7fed424eb039738ce4f91c03f8ce7e37e8a0..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/xml/ExpatWrapper.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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. - */ -#ifndef _XML_H_ -#define _XML_H_ - -#include -#include -#include - -using namespace ustl; - -class ExpatWrapper { -public: - /** - * Constructor for ExpatWrapper. - */ - ExpatWrapper(); - - /** - * Destructor for ExpatWrapper. - */ - virtual ~ExpatWrapper(); - - /** - * decode call expat to parse the xml. - * @param buf The buffer to be parsed. - * @param len The length of the buffer. - * @param isFinal The flag to indicate whether the buffer - * is a fragment or whole xml. - */ - int decode(const char* buf, int len, int isFinal); - - /** - * virtual funtion to deal with the start element in expat, need implement by child class. - */ - virtual void startElement(const XML_Char *name, const XML_Char **atts); - - /** - * virtual funtion to deal with the end element in expat, need implement by child class. - */ - virtual void endElement(const XML_Char *name); - - /** - * virtual funtion to deal with the data handler in expat, need implement by child class. - */ - virtual void dataHandler(const XML_Char *s, int len); - -PRIVATE: - /** - * Callback for Expat startElement. - */ - static void startElementCallback(void *userData, const XML_Char *name, const XML_Char **atts); - - /** - * Callback for Expat endElement. - */ - static void endElementCallback(void *userData, const XML_Char *name); - - /** - * Callback for Expat dataHandler. - */ - static void dataHandlerCallback(void *userData, const XML_Char *s, int len); - -PRIVATE: - XML_Parser mParser; /**< The expat parser object. */ -}; - -#endif diff --git a/media/libdrm/mobile2/include/util/xml/XMLDocumentImpl.h b/media/libdrm/mobile2/include/util/xml/XMLDocumentImpl.h deleted file mode 100644 index c29b87d2b561afd15c68c822eb4cdc2920c22ca5..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/xml/XMLDocumentImpl.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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. - */ -#ifndef _XMLDOCUMENTIMPL_H_ -#define _XMLDOCUMENTIMPL_H_ - -#include -#include - -class XMLDocumentImpl : public DocumentImpl { -public: - /** Constructor for XMLDocumentImpl. */ - XMLDocumentImpl(); - - /** Destructor for XMLDocumentImpl. */ - ~XMLDocumentImpl(); - - /** - * Get the first child element of the document. - * @return the first child Element of document. - */ - virtual ElementImpl* getDocumentElement() const; - - /** - * Create a XML element with the specific name. - * @param tagName The specific tag name. - * @return a new xml Element - * @exception DOMException - */ - virtual ElementImpl* createElement(const DOMString* tagName) const throw (DOMException); - - /** - * Create a text node with the specific data. - * @param data The specific data. - * @return a new Text node. - */ - virtual TextImpl* createTextNode(const DOMString* data) const; -}; - -#endif diff --git a/media/libdrm/mobile2/include/util/xml/XMLElementImpl.h b/media/libdrm/mobile2/include/util/xml/XMLElementImpl.h deleted file mode 100644 index a0c95ec757478689ace3d150217a8497a4d428e6..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/include/util/xml/XMLElementImpl.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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. - */ -#ifndef _XMLELEMENTIMPL_H_ -#define _XMLELEMENTIMPL_H_ - -#include -#include -#include -#include -#include -using namespace ustl; - -typedef map DOMStringMap; - -class XMLElementImpl : public ElementImpl { -public: - /** - * Constructor for XMLElementImpl. - * @param tag The name of the tag. - */ - XMLElementImpl(const DOMString *tag); - - /** Destructor for XMLElementImpl. */ - ~XMLElementImpl(); - - /** - * Get the attribute map of the XML element. - * @return DOMStringMap - */ - const DOMStringMap* getAttributeMap() const; - - /** - * Get the tag name of the element. - * return tag name. - */ - virtual const DOMString* getTagName() const; - - /** - * Set the attribute of the element. - * @param name The key of the attribute. - * @param value The value of the attribute. - */ - virtual void setAttribute(const DOMString* name, const DOMString* value) throw (DOMException); - - /** - * Remove the specific attribute. - * @param name The key of the attribute. - * @exception DOMException. - */ - virtual void removeAttribute(const DOMString* name) throw (DOMException); - - /** - * Get the specific attribute. - * @param name The key of the attribute. - * @return the value of the attribute. - */ - virtual const DOMString* getAttribute(const DOMString* name) const; - - /** - * Detect whether element has attributes or not. - * @return true or false to indicate the result. - */ - virtual bool hasAttributes() const; - - /** - * Find the first child node in element by its tag name. - * @param element the specific element to be found. - * @param tag the specific tag name to be searched. - * @return NULL if not found otherwise the child node. - */ - const NodeImpl* findSoloChildNode(const char* tag) const; - - /** - * Get the first text containted in first child of the element. - * @param tag the specific tag name to be searched. - * @return NULL if not found otherwise the text. - */ - const string* getSoloText(const char* tag) const; - - /** - * Get the first child xml element containted in the element. - * @param tag the specific tag name to be searched. - * @return NULL if not found otherwise the element. - */ - const XMLElementImpl* getSoloElement(const char* tag) const; - -PRIVATE: - DOMString mTagName; /**< The tag name. */ - DOMStringMap mAttributeMap; /** The map of attributes. */ -}; - -#endif diff --git a/media/libdrm/mobile2/src/dcf/DrmDcfCommon.cpp b/media/libdrm/mobile2/src/dcf/DrmDcfCommon.cpp deleted file mode 100644 index 0f5e4ac1ef332b589a93fe19792a1717e0246935..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/dcf/DrmDcfCommon.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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. - */ - -#include - -int64_t ntoh_int64(int64_t x) -{ - return (((int64_t)(ntohl((int32_t)((x << 32) >> 32))) << 32) | (uint32_t)ntohl(((int32_t)(x >> 32)))); -} - -/** - * Class: Box - */ -Box::Box(const uint8_t* box):mLargeSize(0),mUserType(NULL) -{ - if(!box) - { - return ; - } - - const uint8_t* p = box; - - /* Get the size value */ - mSize = ntohl(*(uint32_t *)p); - p += sizeof(mSize); - - /* Get the type value */ - mType = *((uint32_t *)p); - p += sizeof(mType); - - if (1 == mSize) - { - mLargeSize = ntoh_int64(*(uint64_t *)p); - p += sizeof(mLargeSize); - } - - if (DCF_USER_TYPE == mType) - { - mUserType = new uint8_t[USER_TYPE_LEN]; - memcpy(mUserType, p, USER_TYPE_LEN); - p += USER_TYPE_LEN; - } - - mBoxLength = p - box; -} - -Box::Box(const Box& other) -{ - mSize = other.mSize; - mType = other.mType; - mLargeSize = other.mLargeSize; - mUserType = NULL; - - if(other.mUserType) - { - mUserType = new uint8_t[USER_TYPE_LEN]; - memcpy(mUserType,other.mUserType,USER_TYPE_LEN); - } -} - -Box& Box::operator=(const Box& other) -{ - if(this == &other) - { - return *this; - } - - if(mUserType) - { - delete []mUserType; - mUserType = NULL; - } - - if(other.mUserType) - { - mUserType = new uint8_t[USER_TYPE_LEN]; - memcpy(mUserType, other.mUserType, USER_TYPE_LEN); - } - - return *this; -} - -Box::~Box() -{ - if(mUserType) - { - delete []mUserType; - mUserType = NULL; - } -} - -uint64_t Box::getSize(void) const -{ - if(1 == mSize) - { - return mLargeSize; - } - - return mSize; -} - -uint32_t Box::getType(void) const -{ - return mType; -} - -const uint8_t* Box::getUsertype(void) const -{ - return mUserType; -} - -uint32_t Box::getLen(void) const -{ - return mBoxLength; -} - - -/** - * Class: FullBox - */ -FullBox::FullBox(const uint8_t* fullBox) : Box(fullBox) -{ - if(!fullBox) - { - return ; - } - - const uint8_t* p = fullBox; - - p += Box::getLen(); - - mVersion = *p; - p++; - - memcpy(mFlag, p,FLAG_LEN); - p += FLAG_LEN; - - mFullBoxLength = p - fullBox; -} - -uint8_t FullBox::getVersion(void) const -{ - return mVersion; -} - -const uint8_t* FullBox::getFlag(void) const -{ - return mFlag; -} - -uint32_t FullBox::getLen(void) const -{ - return mFullBoxLength; -} - -///// class TextualHeader implementation -TextualHeader::TextualHeader(const string& inData) -{ - string::size_type loc1 = inData.find(":", 0); - - if (loc1 != string::npos) - { - name.assign(inData, 0, loc1); - } - - string::size_type loc2 = inData.find(";", loc1 + 1); - - if (loc2 != string::npos) - { - value.assign(inData, loc1 + 1, loc2 - loc1 - 1); - param.assign(inData, loc2 + 1, inData.length() - loc2 - 1); - } - else - { - value.assign(inData, loc1 + 1, inData.length() - loc1 - 1); - } -} - -string TextualHeader::getName() const -{ - return name; -} - -string TextualHeader::getValue() const -{ - return value; -} - -string TextualHeader::getParam() const -{ - return param; -} - diff --git a/media/libdrm/mobile2/src/dcf/DrmDcfContainer.cpp b/media/libdrm/mobile2/src/dcf/DrmDcfContainer.cpp deleted file mode 100644 index 517c930785c24fec68566bf9e4ec5bd0acaaafed..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/dcf/DrmDcfContainer.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - * 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. - */ - -#include - -DcfContainer::DcfContainer(const uint8_t* data,istream& inRawData,uint64_t conOff) - : FullBox(data),mConStream(inRawData) -{ - if(!data) - { - return; - } - - const uint8_t* p = data; - const uint8_t* flag = this->getFlag(); - - if(flag[0] & USER_DATA_FLAG) - { - mHasUserData = true; - } - else - { - mHasUserData = false; - } - - p += this->getLen(); - - FullBox fullBoxDiscrete(p); - - p += fullBoxDiscrete.getLen(); - - mContentTypeLen = *p; - p++; - - mContentType.assign((const char*)p,0,mContentTypeLen); - p += mContentTypeLen; - - // parse common header - FullBox fullBoxComm(p); - p += fullBoxComm.getLen(); - - mEncryptionMethod = *p; - p++; - - mPaddingScheme = *p; - p++; - - mPlaintextLength = ntoh_int64(*((uint64_t *)p)); - p += sizeof(mPlaintextLength); - - mContentIDLength = ntohs(*(uint16_t *)p); - p += sizeof(mContentIDLength); - - mRightsIssuerURLLength = ntohs(*(uint16_t *)p); - p += sizeof(mRightsIssuerURLLength); - - mTextualHeadersLength = ntohs(*(uint16_t *)p); - p += sizeof(mTextualHeadersLength); - - mContentID.assign((const char *)p,0,mContentIDLength); - p += mContentIDLength; - - mRightsIssuerURL.assign((const char *)p,0,mRightsIssuerURLLength); - p += mRightsIssuerURLLength; - - // parse textual header - if (mTextualHeadersLength > 0) - { - if(false == parseTextualHeaders(p,mTextualHeadersLength)) - { - return; - } - - p += mTextualHeadersLength; - } - - ////////////// parser group id - - ///parse content - p = data + this->getLen() + fullBoxDiscrete.getSize(); - FullBox fullBoxContetn(p); - p += fullBoxContetn.getLen(); - mDataLen = ntoh_int64(*((uint64_t *)p)); - p += sizeof(mDataLen); - - mDecOffset = conOff + (p - data); - p += mDataLen; - - /////////////// parser user data -} - -DcfContainer::~DcfContainer() -{ - uint32_t size = mTextualHeaders.size(); - - for(uint32_t i = 0; i < size; i++) - { - delete mTextualHeaders[i]; - } - - mTextualHeaders.clear(); - mCustomHeader.clear(); -} - - -string DcfContainer::getContentType(void) const -{ - return mContentType; -} - -uint8_t DcfContainer::getEncryptionMethod(void) const -{ - return mEncryptionMethod; -} - -uint8_t DcfContainer::getPaddingScheme(void) const -{ - return mPaddingScheme; -} - -uint64_t DcfContainer::getPlaintextLength(void) const -{ - return mPlaintextLength; -} - -uint16_t DcfContainer::getContentIDLength(void) const -{ - return mContentIDLength; -} - -uint16_t DcfContainer::getRightsIssuerURLLength(void) const -{ - return mRightsIssuerURLLength; -} - -uint16_t DcfContainer::getTextualHeadersLength(void) const -{ - return mTextualHeadersLength; -} - -string DcfContainer::getContentID(void) const -{ - return mContentID; -} - -string DcfContainer::getRightsIssuerURL(void) const -{ - return mRightsIssuerURL; -} - -string DcfContainer::getPreviewMethod(void) const -{ - return mSlientMethod; -} - -string DcfContainer::getContentLocation(void) const -{ - return mContentLocation; -} - -string DcfContainer::getContentURL(void) const -{ - return mContentURL; -} - -vector DcfContainer::getCustomerHead(void) const -{ - return mCustomHeader; -} - -istream& DcfContainer::getStream(void) const -{ - return mConStream; -} - -DrmInStream DcfContainer::getPreviewElementData(void) const -{ - // get data based on mPreviewElementURI - //encryptedData = ; - - DrmInStream inStream; - return inStream; -} - -DrmInStream DcfContainer::getDecryptContent(uint8_t* decryptKey) const -{ - DrmInStream inStream(this,decryptKey); - return inStream; -} - -bool DcfContainer::parseTextualHeaders(const uint8_t* data, uint32_t len) -{ - if(!data) - { - return false; - } - - const uint8_t* p = data; - - while (len > (uint32_t)(p - data)) - { - uint32_t l = strlen((const char*)p); - - string str((const char*)p, l); - TextualHeader* tmp = new TextualHeader(str); - - if(!tmp) - { - return false; - } - - mTextualHeaders.push_back(tmp); - - p += l + 1; - } - - uint32_t size = mTextualHeaders.size(); - uint32_t silentpos = 0; - uint32_t previewpos = 0; - - for( uint32_t i = 0; i < size; i++) - { - string tempStr = mTextualHeaders[i]->getName(); - - if(tempStr == "Silent") - { - silentpos = i; - mSlientMethod = mTextualHeaders[i]->getValue(); - mSilentRightsURL = mTextualHeaders[i]->getParam(); - } - else if(tempStr == "Preview") - { - previewpos = i; - mPreviewMethod = mTextualHeaders[i]->getValue(); - - if(mPreviewMethod == "instant") - { - mPreviewElementURI = mTextualHeaders[i]->getParam(); - } - else - { - mPreviewRightsURL = mTextualHeaders[i]->getParam(); - } - } - else if(tempStr == "ContentURL") - { - mContentURL = mTextualHeaders[i]->getValue(); - } - else if(tempStr == "ContentVersion") - { - mContentVersion = mTextualHeaders[i]->getValue(); - } - if(tempStr == "Content-Location") - { - mContentLocation = mTextualHeaders[i]->getValue(); - } - else - { - string str = mTextualHeaders[i]->getName(); - str += ":"; - str += mTextualHeaders[i]->getValue(); - mCustomHeader.push_back(str); - } - } - - if(silentpos < previewpos) - { - mSilentFirst = true; - } - else - { - mSilentFirst = false; - } - - return true; -} - - - - - diff --git a/media/libdrm/mobile2/src/dcf/DrmIStream.cpp b/media/libdrm/mobile2/src/dcf/DrmIStream.cpp deleted file mode 100644 index 1bcc16a39eda5984fae213ba3582151135c16ebc..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/dcf/DrmIStream.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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. - */ - -#include - - -DrmInStream::DrmInStream(const DcfContainer* container,uint8_t* Key) -:mDcfCon(container),mDecryptPos(0) -{ - memcpy(mAesKey,Key,AES_KEY_LEN); -} - -uint64_t DrmInStream::size() const -{ - return mDcfCon->mPlaintextLength; -} - -uint64_t DrmInStream::read(uint8_t* data, uint64_t len) -{ - if(!data) - { - return 0; - } - - if(mDecryptPos >= mDcfCon->mPlaintextLength) - { - return 0; - } - - uint64_t readLen = len; - - // come to the end of decrypted data - if(mDecryptPos + len > mDcfCon->mPlaintextLength) - { - readLen = mDcfCon->mPlaintextLength - mDecryptPos; - } - - uint64_t encLen = mDcfCon->mDataLen; - uint8_t* encData = new uint8_t[encLen]; - - if(!encData) - { - return 0; - } - - mDcfCon->mConStream.seek(mDcfCon->mDecOffset); - mDcfCon->mConStream.read(encData,encLen); - - uint8_t iv[AES_IV_LEN] = {0}; - - memcpy(iv,encData,AES_IV_LEN); - encLen -= AES_IV_LEN; - - if(AES_128_CBC != mDcfCon->mEncryptionMethod) - { - delete []encData; - return 0; - } - - AesAgent drmAesDecrypt(AES_128_CBC,mAesKey); - int32_t padLen = drmAesDecrypt.decContent( iv, - encData + AES_IV_LEN, - encLen, - data); - - delete []encData; - - if(padLen >= 0) - { - return readLen; - } - else - { - return 0; - } -} - - - - - diff --git a/media/libdrm/mobile2/src/dcf/DrmRawContent.cpp b/media/libdrm/mobile2/src/dcf/DrmRawContent.cpp deleted file mode 100644 index 8813e3cc6f97d8f7dd8988c007adcb8c7ccc3f1f..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/dcf/DrmRawContent.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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. - */ - -#include - - -DrmRawContent::DrmRawContent(istream& inRawData) -{ - uint32_t count = inRawData.stream_size(); - - if (count <= MAX_PIECE_LEN) - { - uint8_t* data = new uint8_t[count]; - - if(!data) - { - return; - } - - inRawData.read(data,count); - - const uint8_t* dcf = data; - - //parse DCF file header - if(false == parseDcfHeader(dcf)) - { - delete []data; - return; - } - - dcf = data; - dcf += FIX_HEADER_LEN; - - if(dcf >= (data + count)) - { - return; - } - - // parse container box - FullBox conFullBox(dcf); - - if(DCF_CONTAINER_BOX != conFullBox.getType()) - { - return; - } - - //check whether it is multipart DCF or not - do - { - uint64_t size = conFullBox.getSize(); - - mContainer.push_back(new DcfContainer(dcf,inRawData,dcf-data)); - - dcf += size; - - // come to the end of raw content - if(dcf >= (data + count)) - { - break; - } - - conFullBox = FullBox(dcf); - }while(DCF_CONTAINER_BOX == conFullBox.getType()); - - // compute DCF hash using Sha1Agent - Sha1Agent drmSha1Hash; - drmSha1Hash.computeHash(data,dcf-data,mDcfHash); - - //// parse mutable box - - delete []data; - } -} - -DrmRawContent::~DrmRawContent() -{ - uint32_t size = mContainer.size(); - - for(uint32_t i = 0; i < size; i++) - { - delete mContainer[i]; - } - - mContainer.clear(); -} - -vector DrmRawContent::getContents(void) const -{ - return mContainer; -} - -uint32_t DrmRawContent::getDcfHashLen() const -{ - return DCF_HASH_LEN; -} - -void DrmRawContent::getDcfHash(uint8_t* outDcfHash) const -{ - if(outDcfHash) - { - memcpy(outDcfHash,mDcfHash,DCF_HASH_LEN); - } - - return; -} - -bool DrmRawContent::parseDcfHeader(const uint8_t* dcfHead) -{ - if(!dcfHead) - { - return false; - } - - if(FIX_HEADER_LEN != ntohl(*(uint32_t *)dcfHead)) - { - return false; - } - - dcfHead += 4; - uint32_t type = *(uint32_t *)dcfHead; - - if(DCF_FILE_TYPE != type) - { - return false; - } - - dcfHead += 4; - type = *(uint32_t *)dcfHead; - - if(DCF_FILE_BRAND != type) - { - return false; - } - - dcfHead += 4; - if(2 != ntohl(*(uint32_t *)dcfHead)) - { - return false; - } - - dcfHead += 4; - type = *(uint32_t *)dcfHead; - - if(DCF_FILE_BRAND != type) - { - return false; - } - - dcfHead += 4; - return true; -} diff --git a/media/libdrm/mobile2/src/drmmanager/DrmManager.cpp b/media/libdrm/mobile2/src/drmmanager/DrmManager.cpp deleted file mode 100644 index 599526f6c9dc61e5c8fedb440e437c06c6d61bc1..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/drmmanager/DrmManager.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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. - */ -#include -#include -#include -#include -#include -using namespace ustl; - -/**see DrmManager.h */ -DrmManager::DrmManager(istream * inRawData) -{ - mDcfStream = NULL; - if (inRawData != NULL) - { - mDcfStream = inRawData; - } -} - -/**see DrmManager.h */ -DrmManager::DrmManager(istream * inRawData, string mimeType) -{ - mDcfStream = inRawData; -} - -/**see DrmManager.h */ -int16_t DrmManager::getListOfDcfObjects(vector **outDcfList) -{ - /** call dcf functions to parse the dcf file*/ - if (NULL == mDcfStream) - { - return ERR_DCFSTREAM_NOT_INITIALIZED; - } - if (NULL == outDcfList) - { - return ERR_DCFSTREAM_NOT_INITIALIZED; - } - *outDcfList=&mDcfs; - return DRM_OK; -} - -/**see DrmManager.h */ -int16_t DrmManager::openDecryptedContent(DcfContainer *oneDcfObject, - int16_t operationType, - istream *outDecryptedData) -{ - return 1; -} - -/**see DrmManager.h */ -DrmManager::~DrmManager() -{ - -} diff --git a/media/libdrm/mobile2/src/rights/Asset.cpp b/media/libdrm/mobile2/src/rights/Asset.cpp deleted file mode 100644 index 120b4654d6cbb7abec5efef518795e63fbb129cc..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/rights/Asset.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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. - */ - -#include - -/** see Asset.h */ -Asset::Asset() -{} - -/** see Asset.h */ -Asset::~Asset() -{} - -/** see Asset.h */ -bool Asset::hasParent() -{ - return false; -} - -/** see Asset.h */ -void Asset::setID(const string &id) -{ - mAssetID = id; -} - -/** see Asset.h */ -const string& Asset::getID() const -{ - return mAssetID; -} - -/** see Asset.h */ -void Asset::setContentID(const string &id) -{ - mContentID = id; -} - -/** see Asset.h */ -const string& Asset::getContentID() const -{ - return mContentID; -} - -/** see Asset.h */ -void Asset::setEncryptedKey(const string &key) -{ - mEncryptedKey = key; -} - -/** see Asset.h */ -void Asset::setDCFDigest(const string &value) -{ - mDigestValue = value; -} - -/** see Asset.h */ -const string& Asset::getDCFDigest() const -{ - return mDigestValue; -} - -/** see Asset.h */ -void Asset::setKeyRetrievalMethod(const string &rm) -{ - mRetrievalMethod = rm; -} - -/** see Asset.h */ -void Asset::setParentContentID(const string &id) -{ - mParentContentID = id; -} - -/** see Asset.h */ -const string& Asset::getEncrytedKey() const -{ - return mEncryptedKey; -} - -/** see Asset.h */ -const char* Asset::getCek() const -{ - return NULL; -} - -/** see Asset.h */ -void Asset::recoverCek() -{ -//fix later. - -} - -/** see Asset.h */ -const string& Asset::getParentContentID() const -{ - return mParentContentID; -} diff --git a/media/libdrm/mobile2/src/rights/Constraint.cpp b/media/libdrm/mobile2/src/rights/Constraint.cpp deleted file mode 100644 index 2cb4311962b4337b4d7cc4295c41ed1dc8a96a6d..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/rights/Constraint.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* - * 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. - */ - -#include - -/** see Constraint.h */ -Constraint::Constraint() -{ - mCount = INIT_VALUE; - mTimedCount = INIT_VALUE; - mTimer = INIT_VALUE; - mStart = INIT_VALUE; - mEnd = INIT_VALUE; - mInterval = INIT_VALUE; - mAccumulated = INIT_VALUE; - mExport = NONE; -} - -/** see Constraint.h */ -Constraint::~Constraint() -{} - -/** see Constraint.h */ -bool Constraint::isUnConstraint() const -{ - return (mCount == INIT_VALUE && mTimedCount == INIT_VALUE && - mTimer == INIT_VALUE && mStart == INIT_VALUE && - mEnd == INIT_VALUE && mInterval == INIT_VALUE && - mAccumulated == INIT_VALUE && mExport == NONE && - mSystemList.empty()); -} - -/** see Constraint.h */ -bool Constraint::isDateTimeConstraint() const -{ - return !(mStart == INIT_VALUE && mEnd == INIT_VALUE); -} - -/** see Constraint.h */ -bool Constraint::isIntervalConstraint() const -{ - return !(mInterval == INIT_VALUE); -} - -/** see Constraint.h */ -bool Constraint::isTimedCountConstraint() const -{ - return !(mTimedCount == INIT_VALUE); -} - -/** see Constraint.h */ -bool Constraint::isValid(long time) const -{ - if (isUnConstraint()) - { - return true; - } - - if (isDateTimeConstraint()) - { - if (time < mStart || time > mEnd) - { - return false; - } - } - - if (mInterval == 0 || mCount == 0 || - mTimedCount == 0 || mAccumulated == 0) - { - return false; - } - - return true; -} - -/** see Constraint.h */ -void Constraint::setStartTime(long time) -{ - mStart = time; -} - -/** see Constraint.h */ -long Constraint::getStartTime() const -{ - return mStart; -} - -/** see Constraint.h */ -void Constraint::setEndTime(long time) -{ - mEnd = time; -} - -/** see Constraint.h */ -long Constraint::getEndTime() const -{ - return mEnd; -} - -/** see Constraint.h */ -void Constraint::setAccumulated(long time) -{ - mAccumulated = time; -} - -/** see Constraint.h */ -long Constraint::getAccumulated() const -{ - return mAccumulated; -} - -/** see Constraint.h */ -void Constraint::setCount(int count) -{ - mCount = count; -} - -/** see Constraint.h */ -int Constraint::getCount() const -{ - return mCount; -} - -/** see Constraint.h */ -void Constraint::setTimer(int timer) -{ - mTimer = timer; -} - -/** see Constraint.h */ -int Constraint::getTimer() const -{ - return mTimer; -} - -/** see Constraint.h */ -void Constraint::setTimedCount(int timedCount) -{ - mTimedCount = timedCount; -} - -/** see Constraint.h */ -int Constraint::getTimedCount() const -{ - return mTimedCount; -} - -/** see Constraint.h */ -void Constraint::setInterval(int interval) -{ - mInterval = interval; -} - -/** see Constraint.h */ -int Constraint::getInterval() const -{ - return mInterval; -} - -/** see Constraint.h */ -void Constraint::setExportMode(MODE mode) -{ - mExport = mode; -} - -/** see Constraint.h */ -Constraint::MODE Constraint::getExportMode() const -{ - return mExport; -} - -/** see Constraint.h */ -bool Constraint::consume() -{ - if (isUnConstraint()) - { - return true; - } - - if (mCount > 0) - { - mCount--; - return true; - } - - if (mAccumulated > 0) - { - mAccumulated--; - return true; - } - - if (mTimedCount > 0) - { - - } - return false; -} diff --git a/media/libdrm/mobile2/src/rights/OperationPermission.cpp b/media/libdrm/mobile2/src/rights/OperationPermission.cpp deleted file mode 100644 index fc75fb1bb3bf7728383867f78452bd8fe2e9da4f..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/rights/OperationPermission.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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. - */ - -#include -#include - -/** see OperationPermission.h */ -OperationPermission::OperationPermission() : mConstraint(NULL) -{ - -} - -/** see OperationPermission.h */ -OperationPermission::OperationPermission(OPERATION type, Constraint *cst) : mType(type), mConstraint(cst) -{ - -} - -/** see OperationPermission.h */ -OperationPermission::~OperationPermission() -{ - delete mConstraint; -} - -/** see OperationPermission.h */ -void OperationPermission::setType(OPERATION type) -{ - mType = type; -} - -/** see OperationPermission.h */ -OperationPermission::OPERATION OperationPermission::getType() const -{ - return mType; -} - -/** see OperationPermission.h */ -void OperationPermission::addConstraint(Constraint* constraint) -{ - mConstraint = constraint; -} - -/** see OperationPermission.h */ -Constraint* OperationPermission::getConstraint() const -{ - return mConstraint; -} diff --git a/media/libdrm/mobile2/src/rights/Right.cpp b/media/libdrm/mobile2/src/rights/Right.cpp deleted file mode 100644 index 6be9c70347f293c35122237858485bef41145a8c..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/rights/Right.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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. - */ -#include -#include -#include - -/** see Right.h */ -Right::Right() -{ - -} - -/** see Right.h */ -Right::~Right() -{ - vector::iterator it; - - for (it = mOpList.begin(); it != mOpList.end(); it++) - { - delete(*it); - } - - mOpList.clear(); -} - -/** see Right.h */ -void Right::addAssetID(const string& id) -{ - mAssetNameList.push_back(id); -} - -/** see Right.h */ -void Right::addOperationPermission(OperationPermission* op) -{ - mOpList.push_back(op); -} - -/** see Right.h */ -bool Right::checkPermission(OperationPermission::OPERATION type) -{ - for (vector::iterator it = mOpList.begin(); - it != mOpList.end(); it++) - { - if ((*it)->getType() == type) - { - return true; - } - } - - return false; -} - -/** see Right.h */ -Constraint* Right::getConstraint(OperationPermission::OPERATION type) -{ - for (vector::iterator it = mOpList.begin(); - it != mOpList.end(); it++) - { - if ((*it)->getType() == type) - { - return (*it)->getConstraint(); - } - } - - return NULL; -} diff --git a/media/libdrm/mobile2/src/rights/Ro.cpp b/media/libdrm/mobile2/src/rights/Ro.cpp deleted file mode 100644 index 8141e176bad1517473878bb69390755601a538cf..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/rights/Ro.cpp +++ /dev/null @@ -1,831 +0,0 @@ -/* - * 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. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -using namespace ustl; - -const char *STR_RO_RIGHTS = "o-ex:rights"; -const char *STR_RO_CONTEXT = "o-ex:context"; -const char *STR_RO_AGREEMENT = "o-ex:agreement"; -const char *STR_RO_ASSET = "o-ex:asset"; -const char *STR_RO_INHERIT = "o-ex:inherit"; -const char *STR_RO_DIGEST = "o-ex:digest"; -const char *STR_RO_KEYINFO = "ds:KeyInfo"; -const char *STR_RO_PERMISSION = "o-ex:permission"; -const char *STR_RO_ASSET_ID = "o-ex:id"; -const char *STR_RO_ASSET_IDREF = "o-ex:idref"; -const char *STR_RO_CONTEXT_ID = "o-dd:uid"; -const char *STR_RO_CONTEXT_VERSION = "o-dd:version"; -const char *STR_RO_DIGEST_VALUE = "ds:DigestValue"; -const char *STR_RO_CIPHER_VALUE = "xenc:CipherValue"; -const char *STR_RO_RETRIEVAL_METHOD = "ds:RetrievalMethod"; -const char *STR_RO_PLAY = "o-dd:play"; -const char *STR_RO_DISPLAY = "o-dd:display"; -const char *STR_RO_EXECUTE = "o-dd:execute"; -const char *STR_RO_PRINT = "o-dd:print"; -const char *STR_RO_EXPORT = "o-dd:export"; -const char *STR_RO_CONSTRAINT = "o-ex:constraint"; -const char *STR_RO_COUNT = "o-dd:count"; -const char *STR_RO_TIMEDCOUNT = "o-dd:timed-count"; -const char *STR_RO_TIMER = "oma-dd:timer"; -const char *STR_RO_INTERVAL = "o-dd:interval"; -const char *STR_RO_DATETIME = "o-dd:datetime"; -const char *STR_RO_START = "o-dd:start"; -const char *STR_RO_END = "o-dd:end"; -const char *STR_RO_ACCUMULATED = "o-dd:accumulated"; -const char *STR_RO_INDIVIDUAL = "o-dd:individual"; -const char *STR_RO_SYSTEM = "o-dd:system"; - -/** see Ro.h */ -Ro::Ro() -{ - mDoc = new XMLDocumentImpl(); - mProperRight = NULL; -} - -/** see Ro.h */ -Ro::~Ro() -{ - for (vector::iterator itr = mRightList.begin(); itr != mRightList.end(); itr++) - { - delete(*itr); - } - - mRightList.clear(); - - for (vector::iterator ita = mAssetList.begin(); ita != mAssetList.end(); ita++) - { - delete(*ita); - } - - mAssetList.clear(); - - mProperRight = NULL; - delete mDoc; - -} - -/** see Ro.h */ -void Ro::setRoID(string& id) -{ - mRoID = id; -} - -/** see Ro.h */ -const string& Ro::getRoID() const -{ - return mRoID; -} - -/** see Ro.h */ -void Ro::setRoVersion(string& version) -{ - mRoVersion = version; -} - -/** see Ro.h */ -void Ro::addAsset(Asset* asset) -{ - mAssetList.push_back(asset); -} - -/** see Ro.h */ -void Ro::addRight(Right* right) -{ - mRightList.push_back(right); -} - -/** see Ro.h */ -bool Ro::save() -{ - LOGI("==============Ro save.================="); - - return true; -} - -/** see Ro.h */ -Ro::ERRCODE Ro::parse(istringstream *roStream) -{ - DomExpatAgent xmlAgent(mDoc); - - if (NULL == roStream) - { - LOGI("NULL stream"); - return RO_NULL_STREAM; - } - - if (xmlAgent.generateDocumentFromXML(roStream) == false) - { - LOGI("generate xml doc error"); - return RO_ERR_BAD_XML; - } - - handleDocument(mDoc); - - return RO_OK; -} - -/** see Ro.h */ -bool Ro::handleDocument(const XMLDocumentImpl* doc) -{ - assert(doc != NULL); - - NodeImpl* node = doc->getDocumentElement(); - - return handleRights(node); -} - -/** see Ro.h */ -bool Ro::handleRights(const NodeImpl *curNode) -{ - assert(curNode != NULL); - - NodeImpl *node = curNode->getFirstChild(); - - while (NULL != node) - { - const DOMString* name; - - name = static_cast(node)->getTagName(); - - if (name->compare(STR_RO_CONTEXT) == 0) - { - LOGI("rights context"); - const DOMString *token = NULL; - token = static_cast(node)->getSoloText(STR_RO_CONTEXT_ID); - - if (token) - { - LOGI(*token); - mRoID = *token; - } - - token = static_cast(node)->getSoloText(STR_RO_CONTEXT_VERSION); - if (token) - { - LOGI(*token); - mRoVersion = *token; - } - } - - if (name->compare(STR_RO_AGREEMENT) == 0) - { - - LOGI("rights agreement"); - if (handleAgreement(node) == false) - { - return false; - } - } - - node = node->getNextSibling(); - } - return true; -} - -/** see Ro.h */ -bool Ro::handleAgreement(const NodeImpl *curNode) -{ - assert(curNode != NULL); - - NodeImpl *node = curNode->getFirstChild(); - - while (NULL != node) - { - const DOMString* name; - - name = static_cast(node)->getTagName(); - - if (name->compare(STR_RO_ASSET) == 0) - { - // do something about asset. - LOGI("asset"); - - if (handleAsset(node) == false) - { - return false; - } - } - - if (name->compare(STR_RO_PERMISSION) == 0) - { - // do something about permission. - LOGI("permission"); - - if (handlePermission(node) == false) - { - return false; - } - } - - node = node->getNextSibling(); - } - - return true; -} - -/** see Ro.h */ -bool Ro::handleAsset(const NodeImpl *curNode) -{ - assert(curNode != NULL); - - Asset *asset = new Asset(); - - const XMLElementImpl *curElement = static_cast(curNode); - - if (curElement->hasAttributes()) - { - DOMString assetID(STR_RO_ASSET_ID); - LOGI("asset id:"); - - const DOMString *id = curElement->getAttribute(&assetID); - - if (id) - { - asset->setID(*id); - } - - } - - NodeImpl* node = curNode->getFirstChild(); - - const DOMString *name = NULL; - const string *token = NULL; - - while (NULL != node) - { - curElement = static_cast(node); - name = curElement->getTagName(); - - if (name->compare(STR_RO_CONTEXT) == 0 || - name->compare(STR_RO_INHERIT) == 0) - { - LOGI("asset context"); - - token = curElement->getSoloText(STR_RO_CONTEXT_ID); - if (token) - { - LOGI(*token); - - if (name->compare(STR_RO_CONTEXT) == 0) - { - asset->setContentID(*token); - } - else - { - //parent ID. - asset->setParentContentID(*token); - } - } - } - - if (name->compare(STR_RO_DIGEST) == 0) - { - LOGI("asset digest"); - //digest method is fixed value: - //http://www.w3.org/2000/09/xmldisig#sha1 - token = curElement->getSoloText(STR_RO_DIGEST_VALUE); - if (token) - { - LOGI(*token); - asset->setDCFDigest(*token); - } - } - - if (name->compare(STR_RO_KEYINFO) == 0) - { - LOGI("asset keyinfo"); - - token = curElement->getSoloText(STR_RO_CIPHER_VALUE); - if (token) - { - LOGI(*token); - asset->setEncryptedKey(*token); - } - - const XMLElementImpl *node = curElement->getSoloElement(STR_RO_RETRIEVAL_METHOD); - - if (node) - { - if (node->hasAttributes()) - { - DOMString uri("URI"); - token = node->getAttribute(&uri); - if (token) - { - LOGI(*token); - asset->setKeyRetrievalMethod(*token); - } - } - } - } - - node = node->getNextSibling(); - } - - this->addAsset(asset); - return true; -} - -/** see Ro.h */ -bool Ro::handlePermission(const NodeImpl *curNode) -{ - assert(curNode != NULL); - - Right *right = new Right(); - - const XMLElementImpl *curElement = static_cast(curNode); - - NodeImpl* node = curNode->getFirstChild(); - - while (NULL != node) - { - const DOMString *name = NULL; - NodeListImpl *nodeList = NULL; - - const string *token = NULL; - curElement = static_cast(node); - name = curElement->getTagName(); - - if (name->compare(STR_RO_ASSET) == 0) - { - LOGI("permission asset"); - if (curElement->hasAttributes()) - { - DOMString assetID(STR_RO_ASSET_IDREF); - const DOMString *id = curElement->getAttribute(&assetID); - if (id) - { - right->addAssetID(*id); - LOGI(*id); - } - } - } - - OperationPermission::OPERATION type = OperationPermission::NONE; - - if (name->compare(STR_RO_PLAY) == 0) - { - LOGI("permission play constraint"); - type = OperationPermission::PLAY; - } - - if (name->compare(STR_RO_DISPLAY) == 0) - { - LOGI("permission display costraint"); - type = OperationPermission::DISPLAY; - } - - if (name->compare(STR_RO_EXECUTE) == 0) - { - LOGI("permission execute constraint"); - type = OperationPermission::EXECUTE; - } - - if (name->compare(STR_RO_EXPORT) == 0) - { - LOGI("permission export constraint"); - type = OperationPermission::EXPORT; - } - - if (name->compare(STR_RO_PRINT) == 0) - { - LOGI("permission print constraint"); - type = OperationPermission::PRINT; - } - - Constraint *cst = NULL; - - if (name->compare(STR_RO_CONSTRAINT) == 0) - { - LOGI("permission common constraint"); - type = OperationPermission::COMMON; - } - - cst = getConstraint(curElement); - if (cst) - { - OperationPermission *op = new OperationPermission(type, cst); - right->addOperationPermission(op); - } - - node = node->getNextSibling(); - } - - this->addRight(right); - return true; -} - -/** see Ro.h */ -long Ro::convertISO8601DateTimeToLong(const char* ts) -{ - if (NULL == ts) - { - return -1; - } - - struct tm time; - memset(&time, 0, sizeof(struct tm)); - - strptime(ts, "%FT%T%z", &time); - -//need timezone support: return mktime(&time) - timezone; -//It seems android-sooner doesn't support timezone function. -//line below is just for building, value would be wrong if no timezone minus. - return mktime(&time); -} - -/** see Ro.h */ -long Ro::convertISO8601PeriodToLong(const char* ts) -{ - if (NULL == ts) - { - return -1; - } - - int date, hour, min, sec; - sscanf(ts, "P%dDT%dH%dM%dS", &date, &hour, &min, &sec); - LOGI("%d %d %d %d", date, hour, min, sec); - return (date*24*60*60 + hour*60*60 + min*60 + sec); -} - -/** see Ro.h */ -Constraint* Ro::getConstraint(const NodeImpl* curNode) -{ - assert(curNode != NULL); - - Constraint *constraint = new Constraint(); - - const XMLElementImpl *curElement = static_cast(curNode); - - const string *name = NULL; - const string *token = NULL; - - if ((token = curElement->getSoloText(STR_RO_COUNT))) - { - LOGI(*token); - constraint->setCount(atoi(token->c_str())); - } - - if ((token = curElement->getSoloText(STR_RO_START))) - { - LOGI(*token); - //start Time - constraint->setStartTime(convertISO8601DateTimeToLong(token->c_str())); - } - - if ((token = curElement->getSoloText(STR_RO_END))) - { - LOGI(*token); - //end Time - constraint->setEndTime(convertISO8601DateTimeToLong(token->c_str())); - } - - if ((token = curElement->getSoloText(STR_RO_INTERVAL))) - { - LOGI(*token); - constraint->setInterval(atoi(token->c_str())); - } - - if ((token = curElement->getSoloText(STR_RO_ACCUMULATED))) - { - LOGI(*token); - //Period - constraint->setAccumulated(convertISO8601PeriodToLong(token->c_str())); - } - - if ((token = curElement->getSoloText(STR_RO_TIMEDCOUNT))) - { - LOGI(*token); - constraint->setTimedCount(atoi(token->c_str())); - - const XMLElementImpl *node = curElement->getSoloElement(STR_RO_TIMEDCOUNT); - - if (node) - { - if (node->hasAttributes()) - { - DOMString timer(STR_RO_TIMER); - token = node->getAttribute(&timer); - if (token) - { - LOGI(*token); - constraint->setTimer(atoi(token->c_str())); - } - } - } - - } - - return constraint; -} - -/** see Ro.h */ -void Ro::loadRights(const string& contentID) -{ - for (vector::iterator it = this->mRightList.begin(); - it != this->mRightList.end(); it++) - { - if ((*it)->mAssetNameList.empty()) - { - mContentRightList.push_back(*it); - } - else - { - for (vector::iterator ita = this->mAssetList.begin(); - ita != this->mAssetList.end(); ita++) - { - for (vector::iterator its = (*it)->mAssetNameList.begin(); - its != (*it)->mAssetNameList.end(); its++) - { - if ((*its).compare((*ita)->getID()) == 0) - { - if (contentID.compare((*ita)->getContentID()) == 0) - { - LOGI("find content right"); - mContentRightList.push_back(*it); - } - } - } - } - } - - - } - -} - -/** see Ro.h */ -void Ro::freeRights() -{ - mContentRightList.clear(); -} - -/** see Ro.h */ -bool Ro::checkPermission(OperationPermission::OPERATION type, - const string& contentID) -{ - loadRights(contentID); - - for (vector::iterator it = mContentRightList.begin(); it != mContentRightList.end(); it++) - { - if ((*it)->checkPermission(type)) - { - freeRights(); - return true; - } - - } - freeRights(); - return false; -} - -/** see Ro.h */ -Ro::ERRCODE Ro::consume(OperationPermission::OPERATION type, - const string& contentID) -{ - loadRights(contentID); - - //check in mRightList - vector::iterator it; - vector tmpList; - vector retList; - Constraint *constraint = NULL; - long ealiestEnd = -1; - bool hasCommonConstraint = false; - bool hasUnconstraint = false; - bool hasDateTimeConstraint = false; - bool hasTimedCountConstraint = false; - bool hasIntervalConstraint = false; - - - //apply the RO rule, if do not satisfy the constraint, . - //proper right select process - - for (it = mContentRightList.begin(); it != mContentRightList.end(); it++) - { - if ((*it)->checkPermission(type)) - { - constraint = (*it)->getConstraint(OperationPermission::COMMON); - if (constraint) - { - if (!constraint->isValid(time(NULL))) - { - continue; - } - - hasCommonConstraint = true; - tmpList.push_back(*it); - } - - constraint = (*it)->getConstraint(type); - assert(constraint != NULL); - - if (!constraint->isValid(time(NULL))) - { - continue; - } - - if (constraint->isUnConstraint()) - { - //use uncontrainted firstly. - hasUnconstraint = true; - tmpList.push_back(*it); - break; - } - - if (constraint->isDateTimeConstraint()) - { - //use datetime constraint in high priority. - //if contain multipe constraints, use the earliest expire time. - hasDateTimeConstraint = true; - tmpList.push_back(*it); - continue; - } - - if (constraint->isTimedCountConstraint()) - { - //illegal Operation when time counted - if (type == OperationPermission::PRINT || - type == OperationPermission::EXPORT) - { - continue; - } - - hasTimedCountConstraint = true; - tmpList.push_back(*it); - continue; - } - - if (constraint->isIntervalConstraint()) - { - hasIntervalConstraint = true; - tmpList.push_back(*it); - continue; - } - - tmpList.push_back(*it); - } - } - - - for (it = tmpList.begin(); it != tmpList.end(); it++) - { - if (hasUnconstraint == true) - { - //delete other constraint - constraint = (*it)->getConstraint(type); - if (constraint) - { - if (constraint->isUnConstraint()) - { - retList.push_back(*it); - break; - } - } - continue; - } - - if (hasDateTimeConstraint == true) - { - //delete other constraint - constraint = (*it)->getConstraint(type); - if (constraint) - { - if (constraint->isDateTimeConstraint()) - { - long tt = constraint->getEndTime(); - - if (ealiestEnd == -1) - { - ealiestEnd = tt; - retList.push_back(*it); - } - else if (ealiestEnd > tt) - { - ealiestEnd = tt; - retList.pop_back(); - retList.push_back(*it); - } - } - } - continue; - } - - if (hasIntervalConstraint == true) - { - //delete other constraint - constraint = (*it)->getConstraint(type); - if (constraint) - { - if (constraint->isIntervalConstraint()) - { - retList.push_back(*it); - } - } - continue; - } - - if (hasTimedCountConstraint == true) - { - constraint = (*it)->getConstraint(type); - if (constraint) - { - if (constraint->isTimedCountConstraint()) - { - retList.push_back(*it); - } - } - continue; - } - - retList.push_back(*it); - } - - if (retList.size() == 0) - { - freeRights(); - return RO_BAD; - } - - LOGI("Proper right has %d", retList.size()); - - assert(retList.size() == 1); - - mProperRight = retList[0]; - constraint = retList[0]->getConstraint(OperationPermission::COMMON); - if (constraint) - { - if (constraint->consume() == false) - { - freeRights(); - return RO_BAD; - } - } - - constraint = retList[0]->getConstraint(type); - if (constraint) - { - if (constraint->consume() == false) - { - freeRights(); - return RO_BAD; - } - } - - //update the constraint - freeRights(); - return RO_OK; -} - -/** see Ro.h */ -string Ro::getContentCek(const string& contentID) -{ - for (vector::iterator it = mAssetList.begin(); - it != mAssetList.end(); it++) - { - if (contentID.compare((*it)->getContentID()) == 0) - { - return (*it)->getCek(); - } - } - - return ""; -} - -/** see Ro.h */ -string Ro::getContentHash(const string& contentID) -{ - for (vector::iterator it = mAssetList.begin(); - it != mAssetList.end(); it++) - { - if (contentID.compare((*it)->getContentID()) == 0) - { - return (*it)->getDCFDigest(); - } - } - - return ""; -} diff --git a/media/libdrm/mobile2/src/rights/RoManager.cpp b/media/libdrm/mobile2/src/rights/RoManager.cpp deleted file mode 100644 index a115d21f1f33a46abbdf06c44034ad1d53ae45f4..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/rights/RoManager.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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. - */ - -#include -#include - -using namespace ustl; - -RoManager* RoManager::msInstance = NULL; - -/** see RoManager.h */ -RoManager* RoManager::Instance() -{ - if (NULL == msInstance) - { - msInstance = new RoManager(); - } - - return msInstance; -} - -/** see RoManager.h */ -RoManager::RoManager() -{ -//load the ro list from local system. -} - -/** see RoManager.h */ -RoManager::~RoManager() -{ - msInstance = NULL; - - for (vector::iterator it = mRoList.begin(); - it != mRoList.end(); it++) - { - delete (*it); - } - - mRoList.clear(); -} - -/** see RoManager.h */ -Ro::ERRCODE RoManager::installRo(istringstream *roStream) -{ - Ro *ro = new Ro(); - - Ro::ERRCODE ret = ro->parse(roStream); - - if (Ro::RO_OK == ret) - { - ro->save(); - - mRoList.push_back(ro); - } - - return ret; -} - -/** see RoManager.h */ -Ro* RoManager::getRoByContentID(const string& contentID) -{ - for (vector::iterator it = mRoList.begin(); - it != mRoList.end(); it++) - { - for (vector::iterator ita = (*it)->mAssetList.begin(); - ita != (*it)->mAssetList.end(); ita++) - { - if (contentID.compare((*ita)->getContentID()) == 0) - { - return *it; - } - } - } - - return NULL; -} - -/** see RoManager.h */ -Ro* RoManager::getRo(const string& roID) -{ - for (vector::iterator it = mRoList.begin(); - it != mRoList.end(); it++) - { - if (roID.compare((*it)->getRoID()) == 0) - { - return (*it); - } - } - - return NULL; -} - -/** see RoManager.h */ -vector RoManager::getAllRo() -{ - return mRoList; -} - -/** see RoManager.h */ -bool RoManager::deleteRo(const string& roID) -{ - return true; -} - -/** see RoManager.h */ -bool RoManager::checkRoInCache(const string& roID) -{ - return true; -} - diff --git a/media/libdrm/mobile2/src/roap/Registration.cpp b/media/libdrm/mobile2/src/roap/Registration.cpp deleted file mode 100644 index 9d6f459ad89282e21723bb39b2c290797efb0edb..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/roap/Registration.cpp +++ /dev/null @@ -1 +0,0 @@ -/**/ diff --git a/media/libdrm/mobile2/src/roap/RoapMessageHandler.cpp b/media/libdrm/mobile2/src/roap/RoapMessageHandler.cpp deleted file mode 100644 index 9d190ee2c88a9f2653bce070ca87dcee74846a17..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/roap/RoapMessageHandler.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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. - */ -#include -#include -#include -#include -#include -#include -using namespace ustl; - -/**see RoapMessageHandler.h */ -RoapMessageHandler::RoapMessageHandler() -{ - mDoc = NULL; -} - -/**see RoapMessageHandler.h */ -XMLDocumentImpl* RoapMessageHandler::createClientMsg(RoapMessageHandler::msgType type) -{ - /* load template from files temporarily, FIX ME later */ - string msgTemplate; - switch (type) - { - case RoapMessageHandler::DeviceHello: - msgTemplate.append("deviceHello.xml"); - break; - case RoapMessageHandler::RegistrationRequest: - msgTemplate.append("deviceHello.xml"); - break; - case RoapMessageHandler::RORequest: - msgTemplate.append("deviceHello.xml"); - break; - default: - return NULL; - } - ifstream xmlStream(msgTemplate.c_str()); - XMLDocumentImpl* xmlDoc = new XMLDocumentImpl(); - DomExpatAgent domExpatAgent1(xmlDoc); - if (domExpatAgent1.generateDocumentFromXML(&xmlStream)) - { - return xmlDoc; - } - else - { - delete(xmlDoc); - return NULL; - } -} - diff --git a/media/libdrm/mobile2/src/util/crypto/DrmCrypto.cpp b/media/libdrm/mobile2/src/util/crypto/DrmCrypto.cpp deleted file mode 100644 index fbbefb8fce257dac17b772818b590677e82ab664..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/crypto/DrmCrypto.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * 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. - */ - -#include -#include - -using namespace ustl; - -void AesAgent::discardPaddingByte( unsigned char* decryptedBuf,unsigned long* decryptedBufLen) -{ - if(!decryptedBuf) - { - return; - } - - int i; - unsigned long tmpLen = *decryptedBufLen; - - // Check whether the last several bytes are padding or not - for ( i = 1; i < decryptedBuf[tmpLen - 1]; i++) - { - if (decryptedBuf[tmpLen - 1 - i] != decryptedBuf[tmpLen - 1]) - break; - } - - // They are padding bytes - if (i == decryptedBuf[tmpLen - 1]) - { - *decryptedBufLen = tmpLen - i; - } - - return; -} - -int32_t AesAgent::decContent( unsigned char* iv, - const unsigned char* encData, - unsigned long encLen, - unsigned char* decData) -{ - if(AES_128_CBC == mode) - { - AES_KEY key; - AES_set_decrypt_key(AesKey,AES_KEY_BITS,&key); - - uint8_t *tmpBuf = new uint8_t[encLen]; - - AES_cbc_encrypt( encData, - tmpBuf, - encLen, - &key, - iv, - AES_DECRYPT); - - unsigned long tempLen = encLen; - discardPaddingByte(tmpBuf,&tempLen); - - memcpy(decData, tmpBuf, tempLen); - - delete []tmpBuf; - return encLen - tempLen; - } - else - { - return AES_DEC_FAILED; - } -} - -void Sha1Agent::computeHash( const unsigned char* inData, - unsigned long inLen, - unsigned char* outHash) const -{ - EVP_Digest(inData,inLen,outHash,NULL,EVP_sha1(),NULL); - return; -} - -void HmacSha1Agent::computeMac( const unsigned char* inData, - unsigned long inLen, - unsigned char* outData) const -{ - HMAC(EVP_sha1(),macKey,keyLen,inData,inLen,outData,NULL); - return; -} - -bool RsaAgent::signature( const unsigned char* rawData, - unsigned long rawLen, - unsigned char* sigData, - RsaAlg sigAlg) -{ - switch(sigAlg) - { - case RSA_PSS: - { - unsigned char mHash[SHA_DIGEST_LENGTH]; - Sha1Agent sha1; - sha1.computeHash(rawData,rawLen,mHash); - - unsigned char EM[rsaSize]; - if( 0 == RSA_padding_add_PKCS1_PSS( &rsaKey, - EM, - mHash, - EVP_sha1(), - SHA_DIGEST_LENGTH)) - { - return false; - } - - if(0 > RSA_private_encrypt( SHA_DIGEST_LENGTH, - EM, - sigData, - &rsaKey, - RSA_PKCS1_PADDING)) - { - return false; - } - else - { - return true; - } - } - break; - case RSA_SHA1: - { - unsigned char mHash[SHA_DIGEST_LENGTH]; - Sha1Agent sha1; - sha1.computeHash(rawData,rawLen,mHash); - - if(0 != RSA_sign( NID_sha1WithRSA, - mHash, - SHA_DIGEST_LENGTH, - sigData, - &rsaSize, - &rsaKey)) - { - return true; - } - else - { - return false; - } - } - break; - default: - return false; - } - - return false; -} - -bool RsaAgent::sigVerify( unsigned char* sigData, - unsigned long sigLen, - const unsigned char* rawData, - unsigned long rawLen, - RsaAlg sigAlg) -{ - if( sigAlg == RSA_PSS) - { - unsigned char decSigData[rsaSize]; - - if(0 > RSA_public_decrypt(sigLen, - sigData, - decSigData, - &rsaKey, - RSA_PKCS1_PADDING)) - { - return false; - } - else - { - unsigned char mHash[SHA_DIGEST_LENGTH]; - Sha1Agent sha1; - sha1.computeHash(rawData,rawLen,mHash); - - if( 0 == RSA_verify_PKCS1_PSS( &rsaKey, - mHash, - EVP_sha1(), - decSigData, - -1)) - { - return true; - } - else - { - return false; - } - } - } - else if(sigAlg == RSA_SHA1) - { - unsigned char mHash[SHA_DIGEST_LENGTH]; - Sha1Agent sha1; - sha1.computeHash(rawData,rawLen,mHash); - - if(0 != RSA_verify( NID_sha1WithRSA, - mHash, - SHA_DIGEST_LENGTH, - sigData, - sigLen, - &rsaKey)) - { - return true; - } - else - { - return false; - } - } - else - { - return false; - } -} - -int RsaAgent::decrypt( const unsigned char* encData, - unsigned long encLen, - unsigned char* decData) -{ - return RSA_private_decrypt( encLen, - encData, - decData, - &rsaKey, - RSA_PKCS1_PADDING); -} diff --git a/media/libdrm/mobile2/src/util/domcore/CharacterDataImpl.cpp b/media/libdrm/mobile2/src/util/domcore/CharacterDataImpl.cpp deleted file mode 100644 index 0fe699a3a6bb8b6c0ce92bc4d4619e642cac7c9d..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/domcore/CharacterDataImpl.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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. - */ -#include - -/** see CharacterDataImpl.h */ -const DOMString* CharacterDataImpl::getData() const throw (DOMException) -{ - return charData; -} - -/** see CharacterDataImpl.h */ -CharacterDataImpl::CharacterDataImpl():charData(NULL) -{ -} - -/** see CharacterDataImpl.h*/ -CharacterDataImpl::CharacterDataImpl(const DOMString* data):charData(NULL) -{ - if (data != NULL) - charData = new DOMString(*data); -} - -/** see CharacterDataImpl.h */ -void CharacterDataImpl::setData(const DOMString* data) throw (DOMException) -{ - - if (charData != NULL) - delete charData; - - if (data == NULL) - charData = NULL; - else - charData = new DOMString(*data); -} - -/** see CharacterDataImpl.h */ -int CharacterDataImpl::getLength() const -{ - return charData != NULL ? charData->length() : 0; -} - -/** see CharacterDataImpl.h */ -void CharacterDataImpl::appendData(const DOMString* arg) throw(DOMException) -{ - if (arg != NULL) { - if (charData != NULL) - charData->append(*arg); - else - charData = new DOMString(*arg); - } -} - -/** see CharacterDataImpl.h */ -const DOMString* CharacterDataImpl::getNodeValue() const throw(DOMException) -{ - return getData(); -} - -/** see CharacterDataImpl.h */ -void CharacterDataImpl::setNodeValue(DOMString* nodeValue) throw(DOMException) -{ - setData(nodeValue); -} - -/** see CharacterDataImpl.h */ -CharacterDataImpl::~CharacterDataImpl() -{ - delete charData; -} - diff --git a/media/libdrm/mobile2/src/util/domcore/DOMException.cpp b/media/libdrm/mobile2/src/util/domcore/DOMException.cpp deleted file mode 100644 index da9d3cedd7deff59650cfa32facc82c69bdd0392..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/domcore/DOMException.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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. - */ diff --git a/media/libdrm/mobile2/src/util/domcore/DocumentImpl.cpp b/media/libdrm/mobile2/src/util/domcore/DocumentImpl.cpp deleted file mode 100644 index ebf46fba93bac53b1fa744cbf5bc3522b0596369..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/domcore/DocumentImpl.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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. - */ -#include - -const DOMString DocumentImpl::nodeName = "#DOCUMENT"; - -/** see DocumentImpl.h */ -DocumentImpl::DocumentImpl() -{ - -} - -/** see DocumentImpl.h */ -ElementImpl* DocumentImpl::getDocumentElement() const -{ - return NULL; -} - -/** see DocumentImpl.h */ -ElementImpl* DocumentImpl::createElement(const DOMString* tagName) const throw (DOMException) -{ - return NULL; -} - -/** see DocumentImpl.h */ -TextImpl* DocumentImpl::createTextNode(const DOMString* data) const -{ - TextImpl* text = new TextImpl(data); - - if (text != NULL) - text->setDocument(this); - - return text; -} - -/** see DocumentImpl.h */ -NodeListImpl* DocumentImpl::getElementsByTagName(const DOMString* tagname) const -{ - ElementImpl* element = getDocumentElement(); - NodeListImpl* list = NULL; - - if (element != NULL) - list = element->getElementsByTagName(tagname); - - return list; -} - -/** see DocumentImpl.h */ -const DOMString* DocumentImpl::getNodeName() const -{ - return &nodeName; -} - -/** see DocumentImpl.h */ -NodeType DocumentImpl::getNodeType() const -{ - return DOCUMENT_NODE; -} - -/** see DocumentImpl.h */ -DocumentImpl::~DocumentImpl() -{ - -} - diff --git a/media/libdrm/mobile2/src/util/domcore/ElementImpl.cpp b/media/libdrm/mobile2/src/util/domcore/ElementImpl.cpp deleted file mode 100644 index df48831e25de84c1ba90c5838b3450b910f9ae3f..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/domcore/ElementImpl.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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. - */ -#include - -/** see ElementImpl.h */ -NodeType ElementImpl::getNodeType() const -{ - return ELEMENT_NODE; -} - -/** see ElementImpl.h */ -const DOMString* ElementImpl::getNodeName() const -{ - return getTagName(); -} - -/** see ElementImpl.h */ -const DOMString* ElementImpl::getTagName() const -{ - return NULL; -} - -/** see ElementImpl.h */ -void ElementImpl::setAttribute(const DOMString* name, const DOMString* value) throw (DOMException) -{ - -} - -/** see ElementImpl.h */ -void ElementImpl::removeAttribute(const DOMString* name) throw (DOMException) -{ - -} - -/** see ElementImpl.h */ -const DOMString* ElementImpl::getAttribute(const DOMString* name) const -{ - return NULL; -} - -/** see ElementImpl.h */ -void ElementImpl::getElementsByTagName(const DOMString* name, NodeListImpl* nodeList) const -{ - NodeImpl* node = getFirstChild(); - - if (node == NULL || name == NULL || nodeList == NULL) - return; - - do { - - if (node->getNodeType() == ELEMENT_NODE) { - ElementImpl* elementNode = static_cast(node); - if (*elementNode->getTagName() == *name) - /* if current is element node and tag name is equal to name,put it into nodeList */ - nodeList->append(node); - /* - * visit DOM tree recursively, - * get all Elements node whose tage name is equal to name. - */ - elementNode->getElementsByTagName(name, nodeList); - } - - /* set current node's next sibling node as current node.*/ - node = node->getNextSibling(); - } while(node != NULL); -} - -/** see ElementImpl.h */ -NodeListImpl* ElementImpl::getElementsByTagName(const DOMString* name) const -{ - NodeListImpl* nodeList = new NodeListImpl(); - - if (nodeList == NULL || name == NULL) - return NULL; - - getElementsByTagName(name,nodeList); - - return nodeList; -} - -/** see ElementImpl.h */ -bool ElementImpl::hasAttributes() const -{ - return false; -} diff --git a/media/libdrm/mobile2/src/util/domcore/NodeImpl.cpp b/media/libdrm/mobile2/src/util/domcore/NodeImpl.cpp deleted file mode 100644 index 183c55ef1a43e9bde1c6fabb91d008f05a9f97a8..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/domcore/NodeImpl.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* - * 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. - */ -#include -#include - -/** see NodeImpl.h. */ -void NodeImpl::setParent(NodeImpl* parentNode) -{ - this->parent = parentNode; -} - -/** see NodeImpl.h. */ -void NodeImpl::setNextSibling(NodeImpl* siblingNode) -{ - this->nextSibling = siblingNode; -} -/** see NodeImpl.h. */ -void NodeImpl::setPreviousSibling(NodeImpl* siblingNode) -{ - this->previousSibling = siblingNode; -} - -/** see NodeImpl.h. */ -void NodeImpl::setFirstChild(NodeImpl* childNode) -{ - this->firstChild = childNode; -} - -/** see NodeImpl.h. */ -void NodeImpl::setLastChild(NodeImpl* childNode) -{ - this->lastChild = childNode; -} - -/** see NodeImpl.h. */ -NodeImpl* NodeImpl::getParentNode() const -{ - return parent; -} - -/** see NodeImpl.h. */ -NodeImpl* NodeImpl::getFirstChild() const -{ - return firstChild; -} - -/** see NodeImpl.h. */ -NodeImpl* NodeImpl::getLastChild() const -{ - return lastChild; -} - -/** see NodeImpl.h. */ -NodeImpl* NodeImpl::getPreviousSibling() const -{ - return previousSibling; -} - -/** see NodeImpl.h. */ -NodeImpl* NodeImpl::getNextSibling() const -{ - return nextSibling; -} - -/** see NodeImpl.h. */ -NodeImpl* NodeImpl::insertBefore(NodeImpl* newChild, NodeImpl* refChild) throw (DOMException) -{ - if (newChild == NULL) - #if PLATFORM_ANDROID - return NULL; - #else - throw DOMException(DOMException::WRONG_DOCUMENT_ERR); - #endif - if (refChild == NULL || refChild->getParentNode() != this) - #if PLATFORM_ANDROID - return NULL; - #else - throw DOMException(DOMException::NOT_FOUND_ERR); - #endif - - NodeImpl* parentNode = newChild->getParentNode(); - - if (parentNode != NULL) - parentNode->removeChild(newChild); - - NodeImpl* prevSiblingNode = refChild->getPreviousSibling(); - - if (prevSiblingNode != NULL) - prevSiblingNode->appendNextSibling(newChild); - else - setFirstChild(newChild); - - newChild->appendNextSibling(refChild); - newChild->setParent(this); - - return newChild; -} - -/** see NodeImpl.h. */ -NodeImpl* NodeImpl::removeChild(NodeImpl* oldChild) throw (DOMException) -{ - - if (oldChild == NULL || oldChild->getParentNode() != this ) - #if PLATFORM_ANDROID - return NULL; - #else - throw DOMException(DOMException::NOT_FOUND_ERR); - #endif - - NodeImpl* parentNode = oldChild->getParentNode(); - NodeImpl* nextSiblingNode = oldChild->getNextSibling(); - NodeImpl* prevSiblingNode = oldChild->getPreviousSibling(); - - if (prevSiblingNode == NULL && nextSiblingNode != NULL) { - /* - * children's previous sibling node == NULL and next sibling node != - * NULL, means the children node is the first node of its parent. - * so set the children's next sibling node as the first node of its parent. - */ - parentNode->setFirstChild(nextSiblingNode); - nextSiblingNode->setPreviousSibling(NULL); - - } else if (prevSiblingNode != NULL && nextSiblingNode == NULL) { - /* - * children's previous sibling node != NULL and next sibling node == - * NULL, means the child node is the last node of parent.so set the - * last node of children's parent as children's previous sibling node. - */ - prevSiblingNode->setNextSibling(NULL); - parentNode->setLastChild(prevSiblingNode); - - } else if (prevSiblingNode != NULL && nextSiblingNode != NULL) { - /* - * children's previous sibling node != NULL and next sibling node != - * NULL,means the node is neither first child nor last children of its parent. - */ - prevSiblingNode->appendNextSibling(nextSiblingNode); - - } else if (prevSiblingNode == NULL && nextSiblingNode == NULL) { - /* - * this means it's only one children node of its parent. - * so adjust the first child and last child to NULL when remove the children node. - */ - this->setFirstChild(NULL); - this->setLastChild(NULL); - } - - oldChild->setParent(NULL); - oldChild->setNextSibling(NULL); - oldChild->setPreviousSibling(NULL); - - return oldChild; -} - -/** see NodeImpl.h. */ -void NodeImpl::appendNextSibling(NodeImpl* node) -{ - if (node == NULL) - return; - - setNextSibling(node); - node->setPreviousSibling(this); -} - -/** see NodeImpl.h. */ -NodeImpl* NodeImpl::appendChild(NodeImpl* newChild) throw (DOMException) -{ - if (newChild == NULL) - #if PLATFORM_ANDROID - return NULL; - #else - throw DOMException(DOMException::WRONG_DOCUMENT_ERR); - #endif - /* If newChild have parent,remove it from its parent at first.*/ - NodeImpl* parent = newChild->getParentNode(); - if (parent != NULL) - parent->removeChild(newChild); - - if (getFirstChild() == NULL && getLastChild() == NULL) { - /* There are not any nodes in current node.*/ - setFirstChild(newChild); - } else if (getLastChild() != NULL) { - getLastChild()->appendNextSibling(newChild); - } - - newChild->setParent(this); - setLastChild(newChild); - - - return newChild; -} - -/** see NodeImpl.h. */ -bool NodeImpl::hasChildNodes() const -{ - return getFirstChild() != NULL; -} - -/** see NodeImpl.h. */ -const DOMString* NodeImpl::getNodeValue() const throw (DOMException) -{ - return NULL; -} - -/** see NodeImpl.h. */ -void NodeImpl::setNodeValue(DOMString* nodeValue) throw (DOMException) -{ -} - -/** see NodeImpl.h. */ -bool NodeImpl::hasAttributes() const -{ - return false; -} - -/** see NodeImpl.h */ -const DocumentImpl* NodeImpl::getDocument() const -{ - return document; -} - -/** see NodeImpl.h */ -void NodeImpl::setDocument(const DocumentImpl* document) -{ - this->document = document; -} diff --git a/media/libdrm/mobile2/src/util/domcore/NodeIterator.cpp b/media/libdrm/mobile2/src/util/domcore/NodeIterator.cpp deleted file mode 100644 index fe136692d2e01e6e5814bdc71151e3f22dd62deb..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/domcore/NodeIterator.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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. - */ -#include -#include - -/** see NodeIterator.h */ -NodeIterator::NodeIterator(NodeImpl* start,NodeImpl* scope,NodeImpl* end): scopeNode(scope),endNode(end),curNode(start) -{ -} - -/** see NodeIterator.h */ -NodeImpl* NodeIterator::findNextOrderNode(NodeImpl* node) -{ - if (node == endNode) - return NULL; - - if (node != NULL) { - if (node->hasChildNodes() == true) { - node = node->getFirstChild(); - }else if (node == scopeNode && node->hasChildNodes() == false) { - node = NULL; - } else if (node->getNextSibling() != NULL) { - node = node->getNextSibling(); - } else { - while (node != scopeNode && node != NULL && node->getNextSibling() == NULL) { - node = node->getParentNode(); - } - if (node == scopeNode) - node = NULL; - if (node != NULL) - node = node->getNextSibling(); - } - } - if (node == endNode || node == scopeNode) - node = NULL; - - return node; -} - -/** see NodeIterator.h */ -NodeImpl* NodeIterator::next() -{ - NodeImpl* node = NULL; - - node = findNextOrderNode(curNode); - - if (node != NULL) - curNode = node; - - return node; -} - -/** see NodeIterator.h */ -NodeImpl* NodeIterator::prev() -{ - NodeImpl* node; - - node = findPreviousOrderNode(curNode); - - if (node != NULL) - curNode = node; - - return node; -} - -/** see NodeIterator.h */ -NodeImpl* NodeIterator::findPreviousOrderNode(NodeImpl* node) -{ - if (node == NULL || node == endNode) - return NULL; - - if (node->getPreviousSibling() != NULL) { - node = node->getPreviousSibling(); - while(node != NULL && node->hasChildNodes() == true) - node = node->getLastChild(); - } else { - if (node == scopeNode) - node = NULL; - else - node = node->getParentNode(); - } - - if (node == scopeNode || node == endNode) - return NULL; - - return node; -} - diff --git a/media/libdrm/mobile2/src/util/domcore/NodeListImpl.cpp b/media/libdrm/mobile2/src/util/domcore/NodeListImpl.cpp deleted file mode 100644 index 710d62d49f2bea6cc3a2df93f869b64a8a5bbe33..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/domcore/NodeListImpl.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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. - */ -#include - -/** see NodeListImpl.h*/ -void NodeListImpl::append(const NodeImpl* newNode) -{ - if (newNode == NULL) - return; - - nodeList.push_back(newNode); -} - -/** see NodeListImpl.h*/ -const NodeImpl* NodeListImpl::item(int index) const -{ - int size = nodeList.size(); - - if (size == 0 || index > size - 1 || index < 0) - return NULL; - - return nodeList.at(index); -} - -/** see NodeListImpl.h*/ -int NodeListImpl::getLength() const -{ - return nodeList.size(); -} - -/** see NodeListImpl.h*/ -NodeListImpl::~NodeListImpl() -{ - nodeList.clear(); -} diff --git a/media/libdrm/mobile2/src/util/domcore/TextImpl.cpp b/media/libdrm/mobile2/src/util/domcore/TextImpl.cpp deleted file mode 100644 index 5e421d50fbab09d476e89261afe6e9cfe6314bdd..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/domcore/TextImpl.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - */ -#include - -const DOMString TextImpl::nodeName = "#TEXT"; - -/** see TextImpl.h */ -TextImpl::TextImpl() -{ -} - -/** see TextImpl.h */ -TextImpl::TextImpl(const DOMString* data):CharacterDataImpl(data) -{ -} - -/** see TextImpl.h */ -NodeType TextImpl::getNodeType() const -{ - return TEXT_NODE; -} - -/** see TextImpl.h */ -const DOMString* TextImpl::getNodeName() const -{ - return &nodeName; -} - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.cpp deleted file mode 100644 index ae6646394f17cf329e95aaa86dc796231981bf1a..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.cpp +++ /dev/null @@ -1,160 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2006 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// bktrace.cc -// - -#include "bktrace.h" -#include "sostream.h" -#include "mistream.h" -#include "uassert.h" -#if linux && __GNUC__ && !defined(HAVE_ANDROID_OS) - #include -#else - static inline int backtrace (void**, int) { return (0); } - static inline char** backtrace_symbols (void* const*, int) { return (NULL); } -#endif -#if __GNUC__ >= 3 && !PLATFORM_ANDROID - #include -#endif - -namespace ustl { - -/// Default constructor. The backtrace is obtained here. -CBacktrace::CBacktrace (void) -: m_Symbols (NULL), - m_nFrames (0), - m_SymbolsSize (0) -{ -#if !PLATFORM_ANDROID - try { -#endif - m_nFrames = backtrace (VectorBlock (m_Addresses)); - GetSymbols(); -#if !PLATFORM_ANDROID - } catch (...) {} -#endif -} - -/// Copy constructor. -CBacktrace::CBacktrace (const CBacktrace& v) -: m_Symbols (NULL), - m_nFrames (0), - m_SymbolsSize (0) -{ - operator= (v); -} - -/// Copy operator. -const CBacktrace& CBacktrace::operator= (const CBacktrace& v) -{ - memcpy (m_Addresses, v.m_Addresses, sizeof(m_Addresses)); - m_Symbols = strdup (v.m_Symbols); - m_nFrames = v.m_nFrames; - m_SymbolsSize = v.m_SymbolsSize; - return (*this); -} - -/// Converts a string returned by backtrace_symbols into readable form. -static size_t ExtractAbiName (const char* isym, char* nmbuf) -{ - // Prepare the demangled name, if possible - size_t nmSize = 0; - if (isym) { - // Copy out the name; the strings are: "file(function+0x42) [0xAddress]" - const char* mnStart = strchr (isym, '('); - if (++mnStart == (const char*)(1)) - mnStart = isym; - const char* mnEnd = strchr (isym, '+'); - const char* isymEnd = isym + strlen (isym); - if (!mnEnd) - mnEnd = isymEnd; - nmSize = min (size_t (distance (mnStart, mnEnd)), 256U); - memcpy (nmbuf, mnStart, nmSize); - } - nmbuf[nmSize] = 0; - // Demangle - demangle_type_name (nmbuf, 256U, &nmSize); - return (nmSize); -} - -/// Tries to get symbol information for the addresses. -void CBacktrace::GetSymbols (void) -{ - auto_ptr symbols (backtrace_symbols (m_Addresses, m_nFrames)); - if (!symbols.get()) - return; - char nmbuf [256]; - size_t symSize = 1; - for (uoff_t i = 0; i < m_nFrames; ++ i) - symSize += ExtractAbiName (symbols.get()[i], nmbuf) + 1; - if (!(m_Symbols = (char*) calloc (symSize, 1))) - return; - for (uoff_t i = 0; m_SymbolsSize < symSize - 1; ++ i) { - size_t sz = ExtractAbiName (symbols.get()[i], nmbuf); - memcpy (m_Symbols + m_SymbolsSize, nmbuf, sz); - m_SymbolsSize += sz + 1; - m_Symbols [m_SymbolsSize - 1] = '\n'; - } -} - -/// Default destructor. -CBacktrace::~CBacktrace (void) -{ - free_nullok (m_Symbols); -} - -#if SIZE_OF_LONG == 8 - #define ADDRESS_FMT "%16p " -#else - #define ADDRESS_FMT "%8p " -#endif - -/// Prints the backtrace to \p os. -void CBacktrace::text_write (ostringstream& os) const -{ - const char *ss = m_Symbols, *se; - for (uoff_t i = 0; i < m_nFrames; ++ i) { - os.format (ADDRESS_FMT, m_Addresses[i]); - se = strchr (ss, '\n') + 1; - os.write (ss, distance (ss, se)); - ss = se; - } -} - -/// Reads the object from stream \p is. -void CBacktrace::read (istream& is) -{ - assert (is.aligned (alignof (m_Addresses[0])) && "Backtrace object contains pointers and must be void* aligned"); - is >> m_nFrames >> m_SymbolsSize; - free_nullok (m_Symbols); - m_Symbols = (char*) malloc (m_SymbolsSize + 1); - is.read (m_Symbols, m_SymbolsSize); - m_Symbols [m_SymbolsSize] = 0; - is.align(); - is.read (m_Addresses, m_nFrames * sizeof(void*)); -} - -/// Writes the object to stream \p os. -void CBacktrace::write (ostream& os) const -{ - assert (os.aligned (alignof (m_Addresses[0])) && "Backtrace object contains pointers and must be void* aligned"); - os << m_nFrames << m_SymbolsSize; - os.write (m_Symbols, m_SymbolsSize); - os.align(); - os.write (m_Addresses, m_nFrames * sizeof(void*)); -} - -/// Returns the size of the written object. -size_t CBacktrace::stream_size (void) const -{ - return (Align (stream_size_of (m_nFrames) + - stream_size_of (m_SymbolsSize) + - m_nFrames * sizeof(void*) + - m_SymbolsSize)); -} - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.h b/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.h deleted file mode 100644 index 7b8c0ea09ea9cfb7d92cd0f249f1e921b645fade..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.h +++ /dev/null @@ -1,55 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2006 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// bktrace.h -// - -#ifndef BKTRACE_H_63ABB1E4388CEDD975DBE58B57DE474F -#define BKTRACE_H_63ABB1E4388CEDD975DBE58B57DE474F - -#include "ulimits.h" - -namespace ustl { - -class ostringstream; -class istream; -class ostream; - -/// \class CBacktrace bktrace.h ustl.h -/// -/// \brief Stores the backtrace from the point of construction. -/// -/// The backtrace, or callstack, is the listing of functions called to -/// reach the construction of this object. This is useful for debugging, -/// to print the location of an error. To get meaningful output you'll -/// need to use a debug build with symbols and with frame pointers. For -/// GNU ld you will also need to link with the -rdynamic option to see -/// actual function names instead of __gxx_personality0+0xF4800. -/// -class CBacktrace { -public: - CBacktrace (void); - CBacktrace (const CBacktrace& v); - ~CBacktrace (void); - const CBacktrace& operator= (const CBacktrace& v); - void text_write (ostringstream& os) const; - void read (istream& is); - void write (ostream& os) const; - size_t stream_size (void) const; -private: - void GetSymbols (void); -private: - void* m_Addresses [64]; ///< Addresses of each function on the stack. - char* m_Symbols; ///< Symbols corresponding to each address. - uint32_t m_nFrames; ///< Number of addresses in m_Addresses. - uint32_t m_SymbolsSize; ///< Size of m_Symbols. -}; - -} // namespace ustl - -ALIGNOF(ustl::CBacktrace, sizeof(void*)) - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/bsconf.h b/media/libdrm/mobile2/src/util/ustl-1.0/bsconf.h deleted file mode 100644 index 79b4af1a24d9cc4ca75ba97975426ae390c45b1c..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/bsconf.h +++ /dev/null @@ -1,173 +0,0 @@ -/* This file is part of bsconf - a configure replacement. - * - * This is the configuration file used by bsconf.c to specify information - * specific to your project that it needs to substitute into files listed - * in g_Files. Being a configuration file, this file can be used or - * modified entirely without restriction. You should change all values - * appropriately to the name of your project and its requirements. The - * bsconf license does not apply to this file. It can and should be - * treated as a template for the creation of your own configuration file. - * - * All substituted variable names are given without enclosing @@. For - * example: "CC" will match "@CC@" in config.h.in and replace it with - * "gcc" in config.h. -*/ - -#include "uassert.h" - -#define BSCONF_VERSION 0x03 - -#define PACKAGE_NAME "ustl" -#define LIB_MAJOR "1" -#define LIB_MINOR "0" -#define LIB_BUILD "0" - -#define PACKAGE_VERSION LIB_MAJOR "." LIB_MINOR -#define PACKAGE_TARNAME PACKAGE_NAME -#define PACKAGE_STRING PACKAGE_NAME " " PACKAGE_VERSION -#define PACKAGE_BUGREPORT "Mike Sharov " - -static cpchar_t g_Files [] = { - "Config.mk", - "config.h", - "ustl.spec" -}; - -/* Values substitute @VARNAME@ */ -static cpchar_t g_EnvVars [] = { - "CC", - "LD", - "CXX", - "CPP", - "HOME", - "CXXFLAGS", - "LDFLAGS", - "CPPFLAGS", - "LDFLAGS", - "CFLAGS" -}; - -/* VARIABLE PROGRAM HOW TO CALL IF NOT FOUND */ -static cpchar_t g_ProgVars [] = { - "CC", "gcc", "gcc", "@CC@", - "CC", "cc", "cc", "gcc", - "CXX", "g++", "g++", "@CXX@", - "CXX", "c++", "c++", "g++", - "LD", "ld", "ld", "ld", - "AR", "ar", "ar", "echo", - "RANLIB", "ranlib", "ranlib", "touch", - "DOXYGEN", "doxygen", "doxygen", "echo", - "INSTALL", "install", "install -c", "cp" -}; - -/* NAME IF NOT FOUND IF FOUND */ -static cpchar_t g_Headers [] = { - "assert.h", "#undef HAVE_ASSERT_H", "#define HAVE_ASSERT_H 1", - "ctype.h", "#undef HAVE_CTYPE_H", "#define HAVE_CTYPE_H 1", - "errno.h", "#undef HAVE_ERRNO_H", "#define HAVE_ERRNO_H 1", - "fcntl.h", "#undef HAVE_FCNTL_H", "#define HAVE_FCNTL_H 1", - "float.h", "#undef HAVE_FLOAT_H", "#define HAVE_FLOAT_H 1", - "inttypes.h", "#undef HAVE_INTTYPES_H", "#define HAVE_INTTYPES_H 1", - "limits.h", "#undef HAVE_LIMITS_H", "#define HAVE_LIMITS_H 1", - "locale.h", "#undef HAVE_LOCALE_H", "#define HAVE_LOCALE_H 1", - "malloc.h", "#undef HAVE_MALLOC_H", "#define HAVE_MALLOC_H 1", - "alloca.h", "#undef HAVE_ALLOCA_H", "#define HAVE_ALLOCA_H 1", - "memory.h", "#undef HAVE_MEMORY_H", "#define HAVE_MEMORY_H 1", - "signal.h", "#undef HAVE_SIGNAL_H", "#define HAVE_SIGNAL_H 1", - "stdarg.h", "#undef HAVE_STDARG_H", "#define HAVE_STDARG_H 1", - "stddef.h", "#undef HAVE_STDDEF_H", "#define HAVE_STDDEF_H 1", - "stdint.h", "#undef HAVE_STDINT_H", "#define HAVE_STDINT_H 1", - "stdio.h", "#undef HAVE_STDIO_H", "#define HAVE_STDIO_H 1", - "stdlib.h", "#undef HAVE_STDLIB_H", "#define HAVE_STDLIB_H 1", - "string.h", "#undef HAVE_STRING_H", "#define HAVE_STRING_H 1", - "strings.h", "#undef HAVE_STRINGS_H", "#define HAVE_STRINGS_H 1", - "sys/stat.h", "#undef HAVE_SYS_STAT_H", "#define HAVE_SYS_STAT_H 1", - "sys/types.h", "#undef HAVE_SYS_TYPES_H", "#define HAVE_SYS_TYPES_H 1", - "sys/wait.h", "#undef HAVE_SYS_WAIT_H", "#define HAVE_SYS_WAIT_H 1", - "time.h", "#undef HAVE_TIME_H", "#define HAVE_TIME_H 1", - "unistd.h", "#undef HAVE_UNISTD_H", "#define HAVE_UNISTD_H 1", - "math.h", "#undef HAVE_MATH_H", "#define HAVE_MATH_H 1", - "stdlib.h", "#undef HAVE_STDLIB_H", "#define HAVE_STDLIB_H 1" -}; - -/* NAME IF NOT FOUND IF FOUND */ -static cpchar_t g_Libs [] = { - "supc++", "", "-lsupc++", -#if __GNUC__ >= 4 - "gcc", "-lgcc_s", "-lgcc_s", - "gcc_eh", "", "", -#elif __GNUC__ >= 3 - "gcc", "-lgcc_s", "-lgcc", - "gcc_eh", "-lgcc_s", "-lgcc_eh", -#else - "gcc", "", "-lgcc", - "gcc_eh", "", "", -#endif - "SystemStubs", "", "-lSystemStubs", /* For MacOS 10.4+ */ - "c", "", "-lc" -}; - -/* NAME IF NOT FOUND IF FOUND */ -static cpchar_t g_Functions [] = { - "atexit", "#undef HAVE_ATEXIT", "#define HAVE_ATEXIT 1", - "malloc", "#undef HAVE_MALLOC\n", "#define HAVE_MALLOC 1\n", - "memchr", "#undef HAVE_MEMCHR", "#define HAVE_MEMCHR 1", - "memmove", "#undef HAVE_MEMMOVE", "#define HAVE_MEMMOVE 1", - "memset", "#undef HAVE_MEMSET", "#define HAVE_MEMSET 1", - "ptrdiff_t", "#undef HAVE_PTRDIFF_T", "#define HAVE_PTRDIFF_T 1", - "strerror", "#undef HAVE_STRERROR", "#define HAVE_STRERROR 1", - "strsignal", "#undef HAVE_STRSIGNAL", "#define HAVE_STRSIGNAL 1", - "strtol", "#undef HAVE_STRTOL", "#define HAVE_STRTOL 1", -#if __GNUC__ >= 3 - "round", "#undef HAVE_ROUND", "#define HAVE_ROUND 1", -#endif - "strrchr", "#undef HAVE_STRRCHR", "#define HAVE_STRRCHR 1", - "__va_copy", "#undef HAVE_VA_COPY", "#define HAVE_VA_COPY 1" -}; - -/* NAME WITHOUT TEXT WITH TEXT */ -static cpchar_t g_Components [] = { - "shared", "#BUILD_SHARED\t= 1", "BUILD_SHARED\t= 1 ", - "static", "#BUILD_STATIC\t= 1", "BUILD_STATIC\t= 1 ", - "debug", "#DEBUG\t\t= 1", "DEBUG\t\t= 1 ", - "bounds", "#undef WANT_STREAM_BOUNDS_CHECKING", "#define WANT_STREAM_BOUNDS_CHECKING 1 ", - "fastcopy", "#undef WANT_UNROLLED_COPY", "#define WANT_UNROLLED_COPY 1 ", -#if __GNUC__ >= 3 && (__i386__ || __x86_64__) && !sun - "mmx", "#undef WANT_MMX", "#define WANT_MMX 1 ", -#endif - "libstdc++", "#define WITHOUT_LIBSTDCPP 1", "#undef WITHOUT_LIBSTDCPP", - "libstdc++", "NOLIBSTDCPP\t= -nodefaultlibs ", "#NOLIBSTDCPP\t= -nodefaultlibs" -}; - -/* Parallel to g_Components */ -static SComponentInfo g_ComponentInfos [VectorSize(g_Components) / 3] = { - { 1, "Builds the shared library (if supported by the OS)" }, - { 0, "Builds the static library" }, - { 0, "Compiles the library with debugging information" }, - { 1, "Disable runtime bounds checking on stream reads/writes" }, - { 1, "Disable specializations for copy/fill" }, -#if __GNUC__ >= 3 && (__i386__ || __x86_64__) && !sun - { 1, "Disable use of MMX/SSE/3dNow! instructions" }, -#endif -#if __GNUC__ >= 3 - { 0, "Link with libstdc++" }, - { 0, "" } -#else - { 1, "" }, - { 1, "" } -#endif -}; - -/* Substitutes names like @PACKAGE_NAME@ with the second field */ -static cpchar_t g_CustomVars [] = { - "PACKAGE_NAME", PACKAGE_NAME, - "PACKAGE_VERSION", PACKAGE_VERSION, - "PACKAGE_TARNAME", PACKAGE_TARNAME, - "PACKAGE_STRING", PACKAGE_STRING, - "PACKAGE_BUGREPORT", PACKAGE_BUGREPORT, - "LIBNAME", PACKAGE_NAME, - "LIB_MAJOR", LIB_MAJOR, - "LIB_MINOR", LIB_MINOR, - "LIB_BUILD", LIB_BUILD -}; - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.cpp deleted file mode 100644 index 7250e9f3edd93918773cdec8716f6a01ee09a764..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// cmemlink.cc -// -// See cmemlink.h for documentation. -// - -#include "cmemlink.h" -#include "ofstream.h" -#include "strmsize.h" -#include "ualgo.h" -#include "uassert.h" - -#if PLATFORM_ANDROID -#include -#undef CPU_HAS_MMX -#endif - -namespace ustl { - -/// \brief Attaches the object to pointer \p p of size \p n. -/// -/// If \p p is NULL and \p n is non-zero, bad_alloc is thrown and current -/// state remains unchanged. -/// -void cmemlink::link (const void* p, size_type n) -{ - if (!p && n) -#if PLATFORM_ANDROID - printf("bad alloc\n"); -#else /* !PLATFORM_ANDROID */ - throw bad_alloc (n); -#endif - unlink(); - relink (p, n); -} - -/// Writes the object to stream \p os -void cmemlink::write (ostream& os) const -{ - const written_size_type sz (size()); - assert (sz == size() && "No support for writing memblocks larger than 4G"); - os << sz; - os.write (cdata(), sz); - os.align (alignof (sz)); -} - -/// Writes the object to stream \p os -void cmemlink::text_write (ostringstream& os) const -{ - os.write (begin(), readable_size()); -} - -/// Returns the number of bytes required to write this object to a stream. -cmemlink::size_type cmemlink::stream_size (void) const -{ - const written_size_type sz (size()); - return (Align (stream_size_of (sz) + sz, alignof(sz))); -} - -/// Writes the data to file \p "filename". -void cmemlink::write_file (const char* filename, int mode) const -{ - fstream f; - f.exceptions (fstream::allbadbits); - f.open (filename, fstream::out | fstream::trunc, mode); - f.write (cdata(), readable_size()); - f.close(); -} - -/// swaps the contents with \p l -void cmemlink::swap (cmemlink& l) -{ -#if CPU_HAS_MMX && SIZE_OF_POINTER == 4 - asm ( - "movq %0, %%mm0\n\t" - "movq %2, %%mm1\n\t" - "movq %%mm0, %2\n\t" - "movq %%mm1, %0" - : "=m"(m_Data), "=m"(m_Size), "=m"(l.m_Data), "=m"(l.m_Size) - : - : "mm0", "mm1", "st", "st(1)"); - simd::reset_mmx(); -#elif CPU_HAS_SSE && SIZE_OF_POINTER == 8 - asm ( - "movups %0, %%xmm0\n\t" - "movups %2, %%xmm1\n\t" - "movups %%xmm0, %2\n\t" - "movups %%xmm1, %0" - : "=m"(m_Data), "=m"(m_Size), "=m"(l.m_Data), "=m"(l.m_Size) - : - : "xmm0", "xmm1"); -#else - ::ustl::swap (m_Data, l.m_Data); - ::ustl::swap (m_Size, l.m_Size); -#endif -} - -/// Compares to memory block pointed by l. Size is compared first. -bool cmemlink::operator== (const cmemlink& l) const -{ - return (l.m_Size == m_Size && - (l.m_Data == m_Data || 0 == memcmp (l.m_Data, m_Data, m_Size))); -} - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.h b/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.h deleted file mode 100644 index 46a93881d803a3c54caca4e3a2e6d9a41709b1aa..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.h +++ /dev/null @@ -1,101 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// cmemlink.h -// - -#ifndef CMEMLINK_H_7CFAB32C5C6732ED29B34EF00EA40A12 -#define CMEMLINK_H_7CFAB32C5C6732ED29B34EF00EA40A12 - -#include "ualgobase.h" - -/// The ustl namespace contains all ustl classes and algorithms. -namespace ustl { - -class istream; -class ostream; -class ostringstream; - -/// \class cmemlink cmemlink.h ustl.h -/// \ingroup MemoryManagement -/// -/// \brief A read-only pointer to a sized block of memory. -/// -/// Use this class the way you would a const pointer to an allocated unstructured block. -/// The pointer and block size are available through member functions and cast operator. -/// -/// Example usage: -/// -/// \code -/// void* p = malloc (46721); -/// cmemlink a, b; -/// a.link (p, 46721); -/// assert (a.size() == 46721)); -/// b = a; -/// assert (b.size() == 46721)); -/// assert (b.DataAt(34) == a.DataAt(34)); -/// assert (0 == memcmp (a, b, 12)); -/// \endcode -/// -class cmemlink { -public: - typedef char value_type; - typedef const value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type reference; - typedef value_type const_reference; - typedef size_t size_type; - typedef uint32_t written_size_type; - typedef ptrdiff_t difference_type; - typedef const_pointer const_iterator; - typedef const_iterator iterator; - typedef const cmemlink& rcself_t; -public: - inline cmemlink (void) : m_Data (NULL), m_Size (0) { } - inline cmemlink (const void* p, size_type n) : m_Data (const_pointer(p)), m_Size (n) { assert (p || !n); } - inline cmemlink (const cmemlink& l) : m_Data (l.m_Data), m_Size (l.m_Size) {} - inline virtual ~cmemlink (void) {} - void link (const void* p, size_type n); - OVERLOAD_POINTER_AND_SIZE_T_V2(link, const void*) - inline void link (const cmemlink& l) { link (l.begin(), l.size()); } - inline void link (const void* first, const void* last) { link (first, distance (first, last)); } - inline void relink (const void* p, size_type n); - inline virtual void unlink (void) { m_Data = NULL; m_Size = 0; } - inline rcself_t operator= (const cmemlink& l) { link (l); return (*this); } - bool operator== (const cmemlink& l) const; - void swap (cmemlink& l); - inline size_type size (void) const { return (m_Size); } - inline size_type max_size (void) const { return (size()); } - inline size_type readable_size (void) const { return (size()); } - inline bool empty (void) const { return (!size()); } - inline const_pointer cdata (void) const { return (m_Data); } - inline iterator begin (void) const { return (iterator (cdata())); } - inline iterator iat (size_type i) const { assert (i <= size()); return (begin() + i); } - inline iterator end (void) const { return (iat (size())); } - inline void resize (size_type n) { m_Size = n; } - inline void read (istream&) { assert (!"ustl::cmemlink is a read-only object."); } - void write (ostream& os) const; - size_type stream_size (void) const; - void text_write (ostringstream& os) const; - void write_file (const char* filename, int mode = 0644) const; -private: - const_pointer m_Data; ///< Pointer to the data block (const) - size_type m_Size; ///< size of the data block -}; - -/// A fast alternative to link which can be used when relinking to the same block (i.e. when it is resized) -inline void cmemlink::relink (const void* p, size_type n) -{ - m_Data = reinterpret_cast(p); - m_Size = n; -} - -/// Use with cmemlink-derived classes to link to a static array -#define static_link(v) link (VectorBlock(v)) - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/config.h b/media/libdrm/mobile2/src/util/ustl-1.0/config.h deleted file mode 100644 index e6e4b7f4fd7df86ac0ee74287211b57053417285..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/config.h +++ /dev/null @@ -1,296 +0,0 @@ -// config.h -// -// Autogenerated from config.h.in by bsconf. -// - -#ifndef CONFIG_H_01E33670634DAAC779EE5FF41CCBB36F -#define CONFIG_H_01E33670634DAAC779EE5FF41CCBB36F - -#include "uassert.h" - -#if PLATFORM_ANDROID - -#include - -// Byte order macros, converted in utypes.h -#define USTL_LITTLE_ENDIAN __LITTLE_ENDIAN -#define USTL_BIG_ENDIAN __BIG_ENDIAN -#define USTL_BYTE_ORDER __BYTE_ORDER - -#if !defined NDEBUG -#define NDEBUG -#endif -#else /* !PLATFORM_ANDROID */ -// Byte order macros, converted in utypes.h -#define USTL_LITTLE_ENDIAN 4321 -#define USTL_BIG_ENDIAN 1234 -#define USTL_BYTE_ORDER USTL_LITTLE_ENDIAN -#endif - -// Define to the one symbol short name of this package. -#define USTL_NAME "ustl" -// Define to the full name and version of this package. -#define USTL_STRING "ustl 1.0" -// Define to the version of this package. -#define USTL_VERSION 0x100 -// Define to the address where bug reports for this package should be sent. -#define USTL_BUGREPORT "Mike Sharov " - -/// Define to 1 if you want stream operations to throw exceptions on -/// insufficient data or insufficient space. All these errors should -/// be preventable in output code; the input code should verify the -/// data in a separate step. It slows down stream operations a lot, -/// but it's your call. By default only debug builds throw. -/// -#undef WANT_STREAM_BOUNDS_CHECKING - -#if !defined(WANT_STREAM_BOUNDS_CHECKING) && !defined(NDEBUG) - #define WANT_STREAM_BOUNDS_CHECKING 1 -#endif - -/// Define to 1 if you want to build without libstdc++ -#define WITHOUT_LIBSTDCPP 1 - -/// Define GNU extensions if unavailable. -#ifndef __GNUC__ - /// GCC (and some other compilers) define '__attribute__'; ustl is using this - /// macro to alert the compiler to flag inconsistencies in printf/scanf-like - /// function calls. Just in case '__attribute__' isn't defined, make a dummy. - /// - #ifndef __attribute__ - #define __attribute__(p) - #endif -#endif -#if defined(__GNUC__) && __GNUC__ >= 4 - #define DLL_EXPORT __attribute__((visibility("default"))) - #define DLL_LOCAL __attribute__((visibility("hidden"))) -#else - #define DLL_EXPORT - #define DLL_LOCAL -#endif -#if defined(__GNUC__) && __GNUC__ >= 3 && __i386__ - /// GCC 3+ supports the prefetch directive, which some CPUs use to improve caching - #define prefetch(p,rw,loc) __builtin_prefetch(p,rw,loc) -#else - #define prefetch(p,rw,loc) -#endif -#if !defined(__GNUC__) || __GNUC__ < 3 - /// __alignof__ returns the recommended alignment for the type - #define __alignof__(v) min(sizeof(v), sizeof(void*)) -#endif - -/// Define to 1 if you have the `atexit' function. -#define HAVE_ATEXIT 1 - -/// Define to 1 if you have the header file. -#define HAVE_ASSERT_H 1 - -/// Define to 1 if you have the header file. -#define HAVE_CTYPE_H 1 - -/// Define to 1 if you have the header file. -#define HAVE_ERRNO_H 1 - -/// Define to 1 if you have the header file. -#define HAVE_FCNTL_H 1 - -/// Define to 1 if you have the header file. -#define HAVE_FLOAT_H 1 - -/// Define to 1 if you have the header file. -#define HAVE_INTTYPES_H 1 - -/// Define to 1 if you have the header file. -#define HAVE_LIMITS_H 1 - -/// Define to 1 if you have the header file. -#define HAVE_LOCALE_H 1 - -/// Define to 1 if your system has a working `malloc' function. -#define HAVE_MALLOC 1 - -// Define to 1 if you have the header file. -#undef HAVE_MALLOC_H - -// Define to 1 if you have the header file. -#define HAVE_ALLOCA_H 1 - -// Define to 1 if you have the `memchr' function. -#define HAVE_MEMCHR 1 - -// Define to 1 if you have the `memmove' function. -#define HAVE_MEMMOVE 1 - -// Define to 1 if you have the header file. -#define HAVE_MEMORY_H 1 - -// Define to 1 if you have the `memset' function. -#define HAVE_MEMSET 1 - -// Define to 1 if the system has the type `ptrdiff_t'. -#define HAVE_PTRDIFF_T 1 - -// Define to 1 if you have the header file. -#define HAVE_SIGNAL_H 1 - -// Define to 1 if you have the __va_copy function -#define HAVE_VA_COPY 1 - -// Define to 1 if `stat' has the bug that it succeeds when given the -// zero-length file name argument. -/* #undef HAVE_STAT_EMPTY_STRING_BUG */ - -// Define to 1 if you have the header file. -#define HAVE_STDARG_H 1 - -// Define to 1 if you have the header file. -#define HAVE_STDDEF_H 1 - -// Define to 1 if you have the header file. -#define HAVE_STDINT_H 1 - -// Define to 1 if you have the header file. -#define HAVE_STDIO_H 1 - -// Define to 1 if you have the header file. -#define HAVE_STDLIB_H 1 - -// Define to 1 if you have the `strerror' function. -#define HAVE_STRERROR 1 - -// Define to 1 if you have the header file. -#define HAVE_STRINGS_H 1 - -// Define to 1 if you have the header file. -#define HAVE_STRING_H 1 - -// Define to 1 if you have the `strrchr' function. -#define HAVE_STRRCHR 1 - -// Define to 1 if you have the `strsignal' function. -#undef HAVE_STRSIGNAL - -// Define to 1 if you have the `strtol' function. -#define HAVE_STRTOL 1 - -// Define to 1 if you have the header file. -#define HAVE_SYS_STAT_H 1 - -// Define to 1 if you have the header file. -#define HAVE_SYS_TYPES_H 1 - -// Define to 1 if you have that is POSIX.1 compatible. -#define HAVE_SYS_WAIT_H 1 - -// Define to 1 if you have the header file. -#define HAVE_TIME_H 1 - -// Define to 1 if you have the header file. -#define HAVE_UNISTD_H 1 - -// Define to 1 if you have the header file. -#define HAVE_MATH_H 1 - -// Define to 1 if you have the rintf function. Will use rint otherwise. -#undef HAVE_RINTF - -// STDC_HEADERS is defined to 1 on sane systems. -#if defined(HAVE_ASSERT_H) && defined(HAVE_CTYPE_H) &&\ - defined(HAVE_ERRNO_H) && defined(HAVE_FLOAT_H) &&\ - defined(HAVE_LIMITS_H) && defined(HAVE_LOCALE_H) &&\ - defined(HAVE_MATH_H) && defined(HAVE_SIGNAL_H) &&\ - defined(HAVE_STDARG_H) && defined(HAVE_STDDEF_H) &&\ - defined(HAVE_STDIO_H) && defined(HAVE_STDLIB_H) &&\ - defined(HAVE_STRING_H) && defined(HAVE_TIME_H) -#define STDC_HEADERS 1 -#endif - -// STDC_HEADERS is defined to 1 on unix systems. -#if defined(HAVE_FCNTL_H) && defined(HAVE_SYS_STAT_H) && defined(HAVE_UNISTD_H) -#define STDUNIX_HEADERS 1 -#endif - -// Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. -#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 - -// Define to 1 if your compiler treats char as a separate type along with -// signed char and unsigned char. This will create overloads for char. -#define HAVE_THREE_CHAR_TYPES 1 - -// Define as the return type of signal handlers (`int' or `void'). -#define RETSIGTYPE void - -// Define to 1 if you have 64 bit types available -#define HAVE_INT64_T 1 - -// Define to 1 if you have the long long type -#undef HAVE_LONG_LONG - -// Define to 1 if you want unrolled specializations for fill and copy -#define WANT_UNROLLED_COPY 1 - -// Define to 1 if you want to use MMX/SSE/3dNow! processor instructions -#undef WANT_MMX - -// Define to byte sizes of types -#define SIZE_OF_CHAR 1 -#define SIZE_OF_SHORT 2 -#define SIZE_OF_INT 4 -#define SIZE_OF_LONG 4 -#define SIZE_OF_LONG_LONG 8 -#define SIZE_OF_POINTER 4 -#define SIZE_OF_SIZE_T 4 -#define SIZE_OF_BOOL SIZE_OF_LONG -#if SIZE_OF_SIZE_T == SIZE_OF_LONG -#define SIZE_T_IS_LONG 1 -#else -#define SIZE_T_IS_LONG 0 -#endif - -// Extended CPU capabilities -#undef CPU_HAS_FPU -#undef CPU_HAS_EXT_DEBUG -#undef CPU_HAS_TIMESTAMPC -#undef CPU_HAS_MSR -#undef CPU_HAS_CMPXCHG8 -#undef CPU_HAS_APIC -#undef CPU_HAS_SYSCALL -#undef CPU_HAS_MTRR -#undef CPU_HAS_CMOV -#undef CPU_HAS_FCMOV -#if WANT_MMX -#undef CPU_HAS_MMX -#undef CPU_HAS_FXSAVE -#undef CPU_HAS_SSE -#undef CPU_HAS_SSE2 -#undef CPU_HAS_SSE3 -#undef CPU_HAS_EXT_3DNOW -#undef CPU_HAS_3DNOW -#endif - -// GCC vector extensions -#if defined(CPU_HAS_MMX) || defined(CPU_HAS_SSE) - #define HAVE_VECTOR_EXTENSIONS 1 -#endif - -#if CPU_HAS_SSE && defined(__GNUC__) - #define __sse_align __attribute__((aligned(16))) -#else - #define __sse_align -#endif - -// Define to empty if `const' does not conform to ANSI C. -/* #define const */ - -// Define as `__inline' if that's what the C compiler calls it, or to nothing -// if it is not supported. -/* #define inline __inline */ - -// Define to `long' if does not define. -/* typedef long off_t; */ - -// Define to `unsigned' if does not define. -/* typedef long size_t; */ - -#endif // CONFIG_H_01E33670634DAAC779EE5FF41CCBB36F - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/fstream.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/fstream.cpp deleted file mode 100644 index 06b9691b13760d0f531086937c2e602247ba0780..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/fstream.cpp +++ /dev/null @@ -1,282 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// file.cc -// - -#include "fstream.h" -#include "uassert.h" -#include "uexception.h" -#include "uutility.h" - -#include -#include -#include -#include -#include -#include - -#if PLATFORM_ANDROID -#include -#endif - -namespace ustl { - -/// Default constructor. -fstream::fstream (void) -: ios_base (), - m_fd (-1), - m_Filename () -{ -} - -/// Opens \p filename in \p mode. -fstream::fstream (const char* filename, openmode mode) -: ios_base (), - m_fd (-1), - m_Filename () -{ - open (filename, mode); -} - -/// Attaches to \p nfd of \p filename. -fstream::fstream (int nfd, const char* filename) -: ios_base (), - m_fd (-1), - m_Filename () -{ - attach (nfd, filename); -} - -/// Destructor. Closes if still open, but without throwing. -fstream::~fstream (void) throw() -{ - clear (goodbit); - exceptions (goodbit); - close(); - assert (!(rdstate() & badbit) && "close failed in the destructor! This may lead to loss of user data. Please call close() manually and either enable exceptions or check the badbit."); -} - -/// Sets state \p s and throws depending on the exception setting. -void fstream::set_and_throw (iostate s, const char* op) -{ - if (ios_base::set_and_throw (s)) -#if PLATFORM_ANDROID - printf("file_exception\n"); -#else /* !PLATFORM_ANDROID */ - throw file_exception (op, name()); -#endif -} - -/// Attaches to the given \p nfd. -void fstream::attach (int nfd, const char* filename) -{ - assert (filename && "Don't do that"); - clear (goodbit); - if (nfd < 0 && ios_base::set_and_throw (badbit)) -#if PLATFORM_ANDROID - printf("file exception\n"); -#else /* !PLATFORM_ANDROID */ - throw file_exception ("open", filename); -#endif - close(); - m_fd = nfd; - m_Filename = filename; -} - -/// Detaches from the current fd. -void fstream::detach (void) -{ - m_fd = -1; - m_Filename.clear(); -} - -/// Converts openmode bits into libc open flags. -/*static*/ int fstream::om_to_flags (openmode m) -{ - static const int s_OMFlags [nombits] = { - 0, // in - O_CREAT, // out - O_APPEND, // app - O_APPEND, // ate - 0, // binary - O_TRUNC, // trunc - O_NONBLOCK, // nonblock - 0, // nocreate - O_NOCTTY // noctty - }; - int flags = (m - 1) & O_ACCMODE; // in and out - for (uoff_t i = 0; i < VectorSize(s_OMFlags); ++ i) - if (m & (1 << i)) - flags |= s_OMFlags[i]; - if (m & nocreate) - flags &= ~O_CREAT; - return (flags); -} - -/// \brief Opens \p filename in the given mode. -/// \warning The string at \p filename must exist until the object is closed. -void fstream::open (const char* filename, openmode mode, mode_t perms) -{ - int nfd = ::open (filename, om_to_flags(mode), perms); - attach (nfd, filename); -} - -/// Closes the file and throws on error. -void fstream::close (void) -{ - if (m_fd >= 0 && ::close(m_fd)) - set_and_throw (badbit | failbit, "close"); - detach(); -} - -/// Moves the current file position to \p n. -off_t fstream::seek (off_t n, seekdir whence) -{ - off_t p = lseek (m_fd, n, whence); - if (p < 0) - set_and_throw (failbit, "seek"); - return (p); -} - -/// Returns the current file position. -off_t fstream::pos (void) const -{ - return (lseek (m_fd, 0, SEEK_CUR)); -} - -/// Reads \p n bytes into \p p. -off_t fstream::read (void* p, off_t n) -{ - off_t br (0); - while (br < n && good()) - br += readsome (advance (p, br), n - br); - return (br); -} - -/// Reads at most \p n bytes into \p p, stopping when it feels like it. -off_t fstream::readsome (void* p, off_t n) -{ - ssize_t brn; - do { brn = ::read (m_fd, p, n); } while (brn < 0 && errno == EINTR); - if (brn > 0) - return (brn); - if (brn < 0 && errno != EAGAIN) - set_and_throw (failbit, "read"); - if (!brn && ios_base::set_and_throw (eofbit | failbit)) -#if PLATFORM_ANDROID - printf("stream_bounds_exception\n"); -#else /* !PLATFORM_ANDROID */ - throw stream_bounds_exception ("read", name(), pos(), n, 0); -#endif - return (0); -} - -/// Writes \p n bytes from \p p. -off_t fstream::write (const void* p, off_t n) -{ - off_t btw (n); - while (btw) { - const off_t bw (n - btw); - ssize_t bwn = ::write (m_fd, advance(p,bw), btw); - if (bwn > 0) - btw -= bwn; - else if (!bwn) { - if (ios_base::set_and_throw (eofbit | failbit)) -#if PLATFORM_ANDROID - printf("stream_bounds_exception\n"); -#else /* !PLATFORM_ANDROID */ - throw stream_bounds_exception ("write", name(), pos() - bw, n, bw); -#endif - break; - } else if (errno != EINTR) { - if (errno != EAGAIN) - set_and_throw (failbit, "write"); - break; - } - } - return (n - btw); -} - -/// Returns the file size. -off_t fstream::size (void) const -{ - struct stat st; - st.st_size = 0; - stat (st); - return (st.st_size); -} - -/// Synchronizes the file's data and status with the disk. -void fstream::sync (void) -{ - if (fsync (m_fd)) - set_and_throw (failbit, "sync"); -} - -/// Get the stat structure. -void fstream::stat (struct stat& rs) const -{ - if (fstat (m_fd, &rs)) -#if PLATFORM_ANDROID - printf("file_exception\n"); -#else - throw file_exception ("stat", name()); -#endif -} - -/// Calls the given ioctl. Use IOCTLID macro to pass in both \p name and \p request. -int fstream::ioctl (const char* rname, int request, long argument) -{ - int rv = ::ioctl (m_fd, request, argument); - if (rv < 0) - set_and_throw (failbit, rname); - return (rv); -} - -/// Calls the given fcntl. Use FCNTLID macro to pass in both \p name and \p request. -int fstream::fcntl (const char* rname, int request, long argument) -{ - int rv = ::fcntl (m_fd, request, argument); - if (rv < 0) - set_and_throw (failbit, rname); - return (rv); -} - -/// Memory-maps the file and returns a link to it. -memlink fstream::mmap (off_t n, off_t offset) -{ - void* result = ::mmap (NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, offset); - if (result == MAP_FAILED) - set_and_throw (failbit, "mmap"); - return (memlink (result, n)); -} - -/// Unmaps a memory-mapped area. -void fstream::munmap (memlink& l) -{ - if (::munmap (l.data(), l.size())) - set_and_throw (failbit, "munmap"); - l.unlink(); -} - -/// Synchronizes a memory-mapped area. -void fstream::msync (memlink& l) -{ - if (::msync (l.data(), l.size(), MS_ASYNC | MS_INVALIDATE)) - set_and_throw (failbit, "msync"); -} - -void fstream::set_nonblock (bool v) -{ - int curf = fcntl (FCNTLID (F_GETFL)); - if (curf < 0) return; - if (v) curf |= O_NONBLOCK; - else curf &= ~O_NONBLOCK; - fcntl (FCNTLID (F_SETFL), curf); -} - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/fstream.h b/media/libdrm/mobile2/src/util/ustl-1.0/fstream.h deleted file mode 100644 index cf60bbde416d7f1193f06a2dad9680962aad6447..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/fstream.h +++ /dev/null @@ -1,78 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// fstream.h -// - -#ifndef FSTREAM_H_056E10F70EAD416443E3B36A2D6B5FA3 -#define FSTREAM_H_056E10F70EAD416443E3B36A2D6B5FA3 - -#include "uios.h" -#include "ustring.h" - -struct stat; - -namespace ustl { - -/// \class fstream fstream.h ustl.h -/// -/// \brief Implements file operations. -/// -/// This is not implemented as a stream, but rather as a base for one. You -/// should use ifstream or ofstream if you want flow operators. Otherwise -/// this only implements functions for binary i/o. -/// -class fstream : public ios_base { -public: - fstream (void); - explicit fstream (const char* filename, openmode mode = in | out); - explicit fstream (int nfd, const char* filename = string::empty_string); - ~fstream (void) throw(); - void open (const char* filename, openmode mode, mode_t perms = 0644); - void attach (int nfd, const char* filename = string::empty_string); - void detach (void); - void close (void); - void sync (void); - off_t read (void* p, off_t n); - off_t readsome (void* p, off_t n); - off_t write (const void* p, off_t n); - off_t size (void) const; - off_t seek (off_t n, seekdir whence = beg); - off_t pos (void) const; - void stat (struct stat& rs) const; - int ioctl (const char* rname, int request, long argument = 0); - inline int ioctl (const char* rname, int request, int argument) { return (fstream::ioctl (rname, request, long(argument))); } - inline int ioctl (const char* rname, int request, void* argument) { return (fstream::ioctl (rname, request, intptr_t(argument))); } - int fcntl (const char* rname, int request, long argument = 0); - inline int fcntl (const char* rname, int request, int argument) { return (fstream::fcntl (rname, request, long(argument))); } - inline int fcntl (const char* rname, int request, void* argument) { return (fstream::fcntl (rname, request, intptr_t(argument))); } - memlink mmap (off_t n, off_t offset = 0); - void munmap (memlink& l); - void msync (memlink& l); - void set_nonblock (bool v = true); - inline int fd (void) const { return (m_fd); } - inline bool is_open (void) const { return (fd() >= 0); } - inline off_t tellg (void) const { return (pos()); } - inline off_t tellp (void) const { return (pos()); } - inline void seekg (off_t n, seekdir whence = beg) { seek (n, whence); } - inline void seekp (off_t n, seekdir whence = beg) { seek (n, whence); } - inline void flush (void) { sync(); } - inline const string& name (void) const { return (m_Filename); } -private: - DLL_LOCAL static int om_to_flags (openmode m); - DLL_LOCAL void set_and_throw (iostate s, const char* op); -private: - int m_fd; ///< Currently open file descriptor. - string m_Filename; ///< Currently open filename. -}; - -/// Argument macro for fstream::ioctl. Use like fs.ioctl (IOCTLID (TCGETS), &ts). -#define IOCTLID(r) "ioctl("#r")", r -#define FCNTLID(r) "fcntl("#r")", r - -} - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/memblock.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/memblock.cpp deleted file mode 100644 index 721433e10172e06f0dc3be6c0e6fd49b9266961d..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/memblock.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// memblock.cc -// -// Allocated memory block. -// - -#include "fstream.h" -#include "mistream.h" -#include "memblock.h" -#include "ualgo.h" -#include "uassert.h" -#include "umemory.h" - -#include - -namespace ustl { - -/// Allocates 0 bytes for the internal block. -memblock::memblock (void) -: memlink (), - m_Capacity (0) -{ -} - -/// Allocates \p n bytes for the internal block. -memblock::memblock (size_type n) -: memlink (), - m_Capacity (0) -{ - resize (n); -} - -/// links to \p p, \p n. Data can not be modified and will not be freed. -memblock::memblock (const void* p, size_type n) -: memlink (), - m_Capacity (0) -{ - assign (p, n); -} - -/// Links to what \p b is linked to. -memblock::memblock (const cmemlink& b) -: memlink (), - m_Capacity (0) -{ - assign (b); -} - -/// Links to what \p b is linked to. -memblock::memblock (const memlink& b) -: memlink (), - m_Capacity (0) -{ - assign (b); -} - -/// Links to what \p b is linked to. -memblock::memblock (const memblock& b) -: memlink (), - m_Capacity (0) -{ - assign (b); -} - -/// Frees internal data, if appropriate -/// Only if the block was allocated using resize, or linked to using Manage, -/// will it be freed. Also, Derived classes should call DestructBlock from -/// their destructor, because upstream virtual functions are unavailable at -/// this point and will not be called automatically. -/// -memblock::~memblock (void) -{ - if (!is_linked()) - deallocate(); -} - -/// resizes the block to \p newSize bytes, reallocating if necessary. -void memblock::resize (size_type newSize, bool bExact) -{ - if (m_Capacity < newSize + minimumFreeCapacity()) - reserve (newSize, bExact); - memlink::resize (newSize); -} - -/// Frees internal data. -void memblock::deallocate (void) throw() -{ - if (m_Capacity) { - assert (cdata() && "Internal error: space allocated, but the pointer is NULL"); - assert (data() && "Internal error: read-only block is marked as allocated space"); - free (data()); - } - unlink(); -} - -/// Assumes control of the memory block \p p of size \p n. -/// The block assigned using this function will be freed in the destructor. -void memblock::manage (void* p, size_type n) -{ - assert (p || !n); - assert (!m_Capacity && "Already managing something. deallocate or unlink first."); - link (p, n); - m_Capacity = n; -} - -/// "Instantiate" a linked block by allocating and copying the linked data. -void memblock::copy_link (void) -{ - const cmemlink l (*this); - if (is_linked()) - unlink(); - assign (l); -} - -/// Copies data from \p p, \p n. -void memblock::assign (const void* p, size_type n) -{ - assert ((p != (const void*) cdata() || size() == n) && "Self-assignment can not resize"); - resize (n); - copy (p, n); -} - -/// \brief Reallocates internal block to hold at least \p newSize bytes. -/// -/// Additional memory may be allocated, but for efficiency it is a very -/// good idea to call reserve before doing byte-by-byte edit operations. -/// The block size as returned by size() is not altered. reserve will not -/// reduce allocated memory. If you think you are wasting space, call -/// deallocate and start over. To avoid wasting space, use the block for -/// only one purpose, and try to get that purpose to use similar amounts -/// of memory on each iteration. -/// -void memblock::reserve (size_type newSize, bool bExact) -{ - if ((newSize += minimumFreeCapacity()) <= m_Capacity) - return; - void* oldBlock (is_linked() ? NULL : data()); - if (!bExact) - newSize = Align (newSize, c_PageSize); - pointer newBlock = (pointer) realloc (oldBlock, newSize); - if (!newBlock) -#if PLATFORM_ANDROID - printf("bad_alloc\n"); -#else - throw bad_alloc (newSize); -#endif - if (!oldBlock && cdata()) - copy_n (cdata(), min (size() + 1, newSize), newBlock); - link (newBlock, size()); - m_Capacity = newSize; -} - -/// Swaps the contents with \p l -void memblock::swap (memblock& l) -{ - memlink::swap (l); - ::ustl::swap (m_Capacity, l.m_Capacity); -} - -/// Shifts the data in the linked block from \p start to \p start + \p n. -memblock::iterator memblock::insert (iterator start, size_type n) -{ - const uoff_t ip = start - begin(); - assert (ip <= size()); - resize (size() + n, false); - memlink::insert (iat(ip), n); - return (iat (ip)); -} - -/// Shifts the data in the linked block from \p start + \p n to \p start. -memblock::iterator memblock::erase (iterator start, size_type n) -{ - const uoff_t ep = start - begin(); - assert (ep + n <= size()); - memlink::erase (start, n); - memlink::resize (size() - n); - return (iat (ep)); -} - -/// Unlinks object. -void memblock::unlink (void) -{ - memlink::unlink(); - m_Capacity = 0; -} - -/// Reads the object from stream \p s -void memblock::read (istream& is) -{ - written_size_type n; - is >> n; - is.verify_remaining ("read", "ustl::memblock", n); - resize (n); - is.read (data(), writable_size()); - is.align (alignof (n)); -} - -/// Reads the entire file \p "filename". -void memblock::read_file (const char* filename) -{ - fstream f; - f.exceptions (fstream::allbadbits); - f.open (filename, fstream::in); - const off_t fsize (f.size()); - reserve (fsize); - f.read (data(), fsize); - f.close(); - resize (fsize); -} - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/memblock.h b/media/libdrm/mobile2/src/util/ustl-1.0/memblock.h deleted file mode 100644 index d85ea0e205463099cdf6bb7819a60b1ae77f7397..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/memblock.h +++ /dev/null @@ -1,74 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// memblock.h -// - -#ifndef MEMBLOCK_H_7ED63A891164CC43578E63664D52A196 -#define MEMBLOCK_H_7ED63A891164CC43578E63664D52A196 - -#include "memlink.h" - -namespace ustl { - -/// \class memblock memblock.h ustl.h -/// \ingroup MemoryManagement -/// -/// \brief Allocated memory block. -/// -/// Adds memory management capabilities to memlink. Uses malloc and realloc to -/// maintain the internal pointer, but only if allocated using members of this class, -/// or if linked to using the Manage() member function. Managed memory is automatically -/// freed in the destructor. -/// -class memblock : public memlink { -public: - static const size_type c_PageSize = 64; ///< The default minimum allocation unit. -public: - memblock (void); - memblock (const void* p, size_type n); - explicit memblock (size_type n); - explicit memblock (const cmemlink& b); - explicit memblock (const memlink& b); - memblock (const memblock& b); - virtual ~memblock (void); - virtual void unlink (void); - inline void assign (const cmemlink& l) { assign (l.cdata(), l.readable_size()); } - inline const memblock& operator= (const cmemlink& l) { assign (l); return (*this); } - inline const memblock& operator= (const memlink& l) { assign (l); return (*this); } - inline const memblock& operator= (const memblock& l) { assign (l); return (*this); } - void assign (const void* p, size_type n); - void swap (memblock& l); - void reserve (size_type newSize, bool bExact = true); - void resize (size_type newSize, bool bExact = true); - iterator insert (iterator start, size_type size); - iterator erase (iterator start, size_type size); - inline void clear (void) { resize (0); } - inline bool is_linked (void) const { return (!m_Capacity && cdata()); } - inline size_type max_size (void) const { return (is_linked() ? memlink::max_size() : SIZE_MAX); } - inline size_type capacity (void) const { return (m_Capacity); } - inline void manage (memlink& l) { manage (l.begin(), l.size()); } - void deallocate (void) throw(); - void manage (void* p, size_type n); - void copy_link (void); - void read (istream& is); - void read_file (const char* filename); -protected: - inline virtual size_type minimumFreeCapacity (void) const { return (0); } -private: - size_type m_Capacity; ///< Number of bytes allocated by Resize. -}; - -/// Reads object \p l from stream \p is -inline istream& operator>> (istream& is, memblock& l) -{ - l.read (is); - return (is); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/memlink.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/memlink.cpp deleted file mode 100644 index bed6601f263c2ae4013d917abba9eed56be4ab19..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/memlink.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// memlink.cc -// -// A pointer to a sized block of memory. -// - -#include "mistream.h" -#include "uassert.h" -#include "ustdxept.h" - -#if PLATFORM_ANDROID -#include -#endif - -namespace ustl { - -/// Reads the object from stream \p s -void memlink::read (istream& is) -{ - written_size_type n; - is >> n; - is.verify_remaining ("read", "ustl::memlink", n); - if (n > size()) -#if PLATFORM_ANDROID - printf("length error\n"); -#else - throw length_error ("memlink can not increase the size of the linked storage for reading"); -#endif - resize (n); - is.read (data(), n); - is.align (alignof (n)); -} - -/// Copies data from \p p, \p n to the linked block starting at \p start. -void memlink::copy (iterator start, const void* p, size_type n) -{ - assert (data() || !n); - assert (p || !n); - assert (start >= begin() && start + n <= end()); - if (p) - copy_n (const_iterator(p), n, start); -} - -/// Fills the linked block with the given pattern. -/// \arg start Offset at which to start filling the linked block -/// \arg p Pointer to the pattern. -/// \arg elSize Size of the pattern. -/// \arg elCount Number of times to write the pattern. -/// Total number of bytes written is \p elSize * \p elCount. -/// -void memlink::fill (iterator start, const void* p, size_type elSize, size_type elCount) -{ - assert (data() || !elCount || !elSize); - assert (start >= begin() && start + elSize * elCount <= end()); - if (elSize == 1) - fill_n (start, elCount, *reinterpret_cast(p)); - else while (elCount--) - start = copy_n (const_iterator(p), elSize, start); -} - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/memlink.h b/media/libdrm/mobile2/src/util/ustl-1.0/memlink.h deleted file mode 100644 index 25d99289fc1f81419fade6b1e40002f3bfaae9e0..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/memlink.h +++ /dev/null @@ -1,115 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// memlink.h - -#ifndef MEMLINK_H_798D25827C8E322D2D7E734B169FF5FC -#define MEMLINK_H_798D25827C8E322D2D7E734B169FF5FC - -#include "cmemlink.h" -#include "ualgo.h" -#include "uassert.h" - -namespace ustl { - -/// \class memlink memlink.h ustl.h -/// \ingroup MemoryManagement -/// -/// \brief Wrapper for pointer to block with size. -/// -/// Use this class the way you would a pointer to an allocated unstructured block. -/// The pointer and block size are available through member functions and cast operator. -/// -/// Example usage: -/// \code -/// void* p = malloc (46721); -/// memlink a, b; -/// a.link (p, 46721); -/// assert (a.size() == 46721)); -/// b = a; -/// assert (b.size() == 46721)); -/// assert (b.begin() + 34 == a.begin + 34); -/// assert (0 == memcmp (a, b, 12)); -/// a.fill (673, b, 42, 67); -/// b.erase (87, 12); -/// \endcode -/// -class memlink : public cmemlink { -public: - typedef value_type* pointer; - typedef cmemlink::pointer const_pointer; - typedef cmemlink::const_iterator const_iterator; - typedef pointer iterator; - typedef const memlink& rcself_t; -public: - inline memlink (void) : cmemlink() {} - inline memlink (void* p, size_type n) : cmemlink (p, n) {} - inline memlink (const void* p, size_type n) : cmemlink (p, n) {} - inline memlink (rcself_t l) : cmemlink (l) {} - inline explicit memlink (const cmemlink& l) : cmemlink (l) {} - inline pointer data (void) { return (const_cast(cdata())); } - inline iterator begin (void) { return (iterator (data())); } - inline iterator iat (size_type i) { assert (i <= size()); return (begin() + i); } - inline iterator end (void) { return (iat (size())); } - inline const_iterator begin (void) const { return (cmemlink::begin()); } - inline const_iterator end (void) const { return (cmemlink::end()); } - inline const_iterator iat (size_type i) const { return (cmemlink::iat (i)); } - size_type writable_size (void) const { return (size()); } - inline rcself_t operator= (const cmemlink& l) { cmemlink::operator= (l); return (*this); } - inline rcself_t operator= (rcself_t l) { cmemlink::operator= (l); return (*this); } - inline void link (const void* p, size_type n) { cmemlink::link (p, n); } - inline void link (void* p, size_type n) { cmemlink::link (p, n); } - inline void link (const cmemlink& l) { cmemlink::link (l); } - inline void link (memlink& l) { cmemlink::link (l); } - OVERLOAD_POINTER_AND_SIZE_T_V2(link, void*) - OVERLOAD_POINTER_AND_SIZE_T_V2(link, const void*) - inline void link (const void* first, const void* last) { link (first, distance (first, last)); } - inline void link (void* first, void* last) { link (first, distance (first, last)); } - inline void relink (const void* p, size_type n) { cmemlink::relink (p, n); } - inline void relink (void* p, size_type n) { cmemlink::relink (p, n); } - inline void copy (const cmemlink& l) { copy (begin(), l.cdata(), l.size()); } - inline void copy (const void* p, size_type n) { copy (begin(), p, n); } - void copy (iterator offset, const void* p, size_type n); - inline void swap (memlink& l) { cmemlink::swap (l); } - void fill (iterator start, const void* p, size_type elsize, size_type elCount = 1); - inline void insert (iterator start, size_type size); - inline void erase (iterator start, size_type size); - void read (istream& is); -}; - -/// Shifts the data in the linked block from \p start to \p start + \p n. -/// The contents of the uncovered bytes is undefined. -inline void memlink::insert (iterator start, size_type n) -{ - assert (data() || !n); - assert (cmemlink::begin() || !n); - assert (start >= begin() && start + n <= end()); - rotate (start, end() - n, end()); -} - -/// Shifts the data in the linked block from \p start + \p n to \p start. -/// The contents of the uncovered bytes is undefined. -inline void memlink::erase (iterator start, size_type n) -{ - assert (data() || !n); - assert (cmemlink::begin() || !n); - assert (start >= begin() && start + n <= end()); - rotate (start, start + n, end()); -} - -/// Reads object \p l from stream \p is -inline istream& operator>> (istream& is, memlink& l) -{ - l.read (is); - return (is); -} - -/// Use with memlink-derived classes to allocate and link to stack space. -#define alloca_link(m,n) (m).link (alloca (n), (n)) - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/mistream.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/mistream.cpp deleted file mode 100644 index ad9982894f58783e7ccf5239c59e767394c9dea9..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/mistream.cpp +++ /dev/null @@ -1,242 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// mstream.cpp -// -// Helper classes to read and write packed binary streams. -// - -#include "mistream.h" -#include "sostream.h" -#include "ualgo.h" -#include "uassert.h" -#include "ustring.h" - -#if PLATFORM_ANDROID -#include -#endif - -namespace ustl { - -//-------------------------------------------------------------------- - -/// \brief Constructs a stream attached to nothing. -/// A stream attached to nothing is not usable. Call Link() functions -/// inherited from cmemlink to attach to some memory block. -/// -istream::istream (void) -: cmemlink (), - m_Pos (0) -{ -} - -/// Attaches the stream to a block at \p p of size \p n. -istream::istream (const void* p, size_type n) -: cmemlink (p, n), - m_Pos (0) -{ -} - -/// Attaches to the block pointed to by \p source. -istream::istream (const cmemlink& source) -: cmemlink (source), - m_Pos (0) -{ -} - -/// Attaches to the block pointed to by source of size source.pos() -istream::istream (const ostream& source) -: cmemlink (source.begin(), source.pos()), - m_Pos (0) -{ -} - -/// Swaps contents with \p is -void istream::swap (istream& is) -{ - cmemlink::swap (is); - ::ustl::swap (m_Pos, is.m_Pos); -} - -/// Checks that \p n bytes are available in the stream, or else throws. -void istream::verify_remaining (const char* op, const char* type, size_t n) const -{ - if (remaining() < n) -#if PLATFORM_ANDROID - printf("stream bounds exception\n"); -#else - throw stream_bounds_exception (op, type, pos(), n, remaining()); -#endif -} - -/// Reads \p n bytes into \p buffer. -void istream::read (void* buffer, size_type n) -{ -#ifdef WANT_STREAM_BOUNDS_CHECKING - verify_remaining ("read", "binary data", n); -#else - assert (remaining() >= n && "Reading past end of buffer. Make sure you are reading the right format."); -#endif - copy_n (ipos(), n, reinterpret_cast(buffer)); - m_Pos += n; -} - -/// Reads a null-terminated string into \p str. -void istream::read_strz (string& str) -{ - const_iterator zp = find (ipos(), end(), string::c_Terminator); - if (zp == end()) - zp = ipos(); - const size_type strl = distance (ipos(), zp); - str.resize (strl); - copy (ipos(), zp, str.begin()); - m_Pos += strl + 1; -} - -/// Reads at most \p n bytes into \p s. -istream::size_type istream::readsome (void* s, size_type n) -{ - if (remaining() < n) - underflow (n); - const size_type ntr (min (n, remaining())); - read (s, ntr); - return (ntr); -} - -/// Writes all unread bytes into \p os. -void istream::write (ostream& os) const -{ - os.write (ipos(), remaining()); -} - -/// Writes the object to stream \p os. -void istream::text_write (ostringstream& os) const -{ - os.write (ipos(), remaining()); -} - -/// Links to \p p of size \p n -void istream::unlink (void) -{ - cmemlink::unlink(); - m_Pos = 0; -} - -//-------------------------------------------------------------------- - -/// \brief Constructs a stream attached to nothing. -/// A stream attached to nothing is not usable. Call Link() functions -/// inherited from memlink to attach to some memory block. -/// -ostream::ostream (void) -: memlink (), - m_Pos (0) -{ -} - -/// Attaches the stream to a block at \p p of size \p n. -ostream::ostream (void* p, size_type n) -: memlink (p, n), - m_Pos (0) -{ -} - -/// Attaches to the block pointed to by \p source. -ostream::ostream (const memlink& source) -: memlink (source), - m_Pos (0) -{ -} - -/// Links to \p p of size \p n -void ostream::unlink (void) -{ - memlink::unlink(); - m_Pos = 0; -} - -/// Checks that \p n bytes are available in the stream, or else throws. -void ostream::verify_remaining (const char* op, const char* type, size_t n) const -{ - if (remaining() < n) -#if PLATFORM_ANDROID - printf("stream bounds exception\n"); -#else - throw stream_bounds_exception (op, type, pos(), n, remaining()); -#endif -} - -/// Aligns the write pointer on \p grain. The skipped bytes are zeroed. -void ostream::align (size_type grain) -{ - const size_t r = pos() % grain; - size_t nb = grain - r; - if (!r) nb = 0; -#ifdef WANT_STREAM_BOUNDS_CHECKING - verify_remaining ("align", "padding", nb); -#else - assert (remaining() >= nb && "Buffer overrun. Check your stream size calculations."); -#endif - fill_n (ipos(), nb, '\x0'); - m_Pos += nb; -} - -/// Writes \p n bytes from \p buffer. -void ostream::write (const void* buffer, size_type n) -{ -#ifdef WANT_STREAM_BOUNDS_CHECKING - verify_remaining ("write", "binary data", n); -#else - assert (remaining() >= n && "Buffer overrun. Check your stream size calculations."); -#endif - copy_n (const_iterator(buffer), n, ipos()); - m_Pos += n; -} - -/// Writes \p str as a null-terminated string. -void ostream::write_strz (const char* str) -{ - write (str, strlen(str)); - iwrite (string::c_Terminator); -} - -/// Writes all available data from \p is. -void ostream::read (istream& is) -{ - is.write (*this); - is.seek (is.size()); -} - -/// Writes all written data to \p os. -void ostream::text_write (ostringstream& os) const -{ - os.write (begin(), pos()); -} - -/// Inserts an empty area of \p size, at \p start. -void ostream::insert (iterator start, size_type s) -{ - memlink::insert (start, s); - m_Pos += s; -} - -/// Erases an area of \p size, at \p start. -void ostream::erase (iterator start, size_type s) -{ - m_Pos -= s; - memlink::erase (start, s); -} - -/// Swaps with \p os -void ostream::swap (ostream& os) -{ - memlink::swap (os); - ::ustl::swap (m_Pos, os.m_Pos); -} - -//-------------------------------------------------------------------- - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/mistream.h b/media/libdrm/mobile2/src/util/ustl-1.0/mistream.h deleted file mode 100644 index 0a7aee752fcf36f8b9701a0fdfdc5d09e6dbf127..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/mistream.h +++ /dev/null @@ -1,293 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// mistream.h -// -#ifndef MISTREAM_H_103AEF1F266C04AA1A817D38705983DA -#define MISTREAM_H_103AEF1F266C04AA1A817D38705983DA - -#include "memlink.h" -#include "uexception.h" -#include "strmsize.h" -#include "uassert.h" -#include "utf8.h" -#include "uios.h" -#ifdef WANT_STREAM_BOUNDS_CHECKING - #include -#endif - -namespace ustl { - -class ostream; -class memlink; -class string; - -/// \class istream mistream.h ustl.h -/// \ingroup BinaryStreams -/// -/// \brief Helper class to read packed binary streams. -/// -/// This class contains a set of functions to read integral types from an -/// unstructured memory block. Unpacking binary file data can be done this -/// way, for instance. aligning the data is your responsibility, and can -/// be accomplished by proper ordering of reads and by calling the align() -/// function. Unaligned access is usually slower by orders of magnitude and, -/// on some architectures, such as PowerPC, can cause your program to crash. -/// Therefore, all read functions have asserts to check alignment. -/// Overreading the end of the stream will also cause a crash (an assert in -/// debug builds). Oh, and don't be intimidated by the size of the inlines -/// here. In the assembly code the compiler will usually chop everything down -/// to five instructions each. -/// -/// Alignment rules for your objects: -/// - Assume your writes start off 4-byte aligned. -/// - After completion, \ref istream::align the stream to at least 4. -/// - If data portability between 32bit and 64bit platforms is important -/// (it often is not, in config files and the like), ensure you are always -/// using fixed-size types and are aligning to a fixed grain. Avoid writing -/// 8-byte types, and if you do, manually align before doing so. -/// - Non-default alignment is allowed if you plan to frequently write this -/// object in array form and alignment would be costly. For example, an -/// array of uint16_t-sized objects may leave the stream uint16_t aligned -/// as long as you know about it and will default-align the stream after -/// writing the array (note: \ref vector will already do this for you) -/// -/// Example code: -/// \code -/// memblock b; -/// b.read_file ("test.file"); -/// ostream is (b); -/// is >> boolVar >> ios::talign(); -/// is >> intVar >> floatVar; -/// is.read (binaryData, binaryDataSize); -/// is.align(); -/// \endcode -/// -class istream : public cmemlink, public ios_base { -public: - istream (void); - istream (const void* p, size_type n); - explicit istream (const cmemlink& source); - explicit istream (const ostream& source); - inline iterator end (void) const { return (cmemlink::end()); } - inline void link (const void* p, size_type n) { cmemlink::link (p, n); } - inline void link (const cmemlink& l) { cmemlink::link (l.cdata(), l.readable_size()); } - inline void link (const void* f, const void* l) { cmemlink::link (f, l); } - OVERLOAD_POINTER_AND_SIZE_T_V2(link, const void*) - inline void relink (const void* p, size_type n) { cmemlink::relink (p, n); m_Pos = 0; } - inline void relink (const cmemlink& l) { relink (l.cdata(), l.readable_size()); } - virtual void unlink (void); - inline virtual size_type underflow (size_type = 1) { return (remaining()); } - inline uoff_t pos (void) const { return (m_Pos); } - inline const_iterator ipos (void) const { return (begin() + pos()); } - inline size_type remaining (void) const { return (size() - pos()); } - inline void seek (uoff_t newPos); - inline void iseek (const_iterator newPos); - inline void skip (size_type nBytes); - inline bool aligned (size_type grain = c_DefaultAlignment) const; - void verify_remaining (const char* op, const char* type, size_t n) const; - inline size_type align_size (size_type grain = c_DefaultAlignment) const; - inline void align (size_type grain = c_DefaultAlignment); - void swap (istream& is); - void read (void* buffer, size_type size); - inline void read (memlink& buf) { read (buf.begin(), buf.writable_size()); } - void read_strz (string& str); - size_type readsome (void* s, size_type n); - inline void read (istream&) { } - void write (ostream& os) const; - void text_write (ostringstream& os) const; - inline size_t stream_size (void) const { return (remaining()); } - template - inline void iread (T& v); - inline void ungetc (void) { seek (pos() - 1); } - inline off_t tellg (void) const { return (pos()); } - inline void seekg (off_t p, seekdir d = beg); -private: - uoff_t m_Pos; ///< The current read position. -}; - -//---------------------------------------------------------------------- - -template -inline size_t required_stream_size (T, const Stream&) { return (1); } -template -inline size_t required_stream_size (T v, const istream&) { return (stream_size_of(v)); } - -template -inline bool stream_at_eof (const Stream& stm) { return (stm.eof()); } -template <> -inline bool stream_at_eof (const istream&) { return (false); } - -/// \class istream_iterator -/// \ingroup BinaryStreamIterators -/// -/// \brief An iterator over an istream to use with uSTL algorithms. -/// -template -class istream_iterator { -public: - typedef T value_type; - typedef ptrdiff_t difference_type; - typedef const value_type* pointer; - typedef const value_type& reference; - typedef size_t size_type; -public: - istream_iterator (void) : m_pis (NULL), m_v() {} - explicit istream_iterator (Stream& is) : m_pis (&is), m_v() { Read(); } - istream_iterator (const istream_iterator& i) : m_pis (i.m_pis), m_v (i.m_v) {} - /// Reads and returns the next value. - inline const T& operator* (void) { return (m_v); } - inline istream_iterator& operator++ (void) { Read(); return (*this); } - inline istream_iterator& operator-- (void) { m_pis->seek (m_pis->pos() - 2 * stream_size_of(m_v)); return (operator++()); } - inline istream_iterator operator++ (int) { istream_iterator old (*this); operator++(); return (old); } - inline istream_iterator operator-- (int) { istream_iterator old (*this); operator--(); return (old); } - inline istream_iterator& operator+= (size_type n) { while (n--) operator++(); return (*this); } - inline istream_iterator& operator-= (size_type n) { m_pis->seek (m_pis->pos() - (n + 1) * stream_size_of(m_v)); return (operator++()); } - inline istream_iterator operator- (size_type n) const { istream_iterator result (*this); return (result -= n); } - inline difference_type operator- (const istream_iterator& i) const { return (distance (i.m_pis->pos(), m_pis->pos()) / stream_size_of(m_v)); } - inline bool operator== (const istream_iterator& i) const { return ((!m_pis && !i.m_pis) || (m_pis && i.m_pis && m_pis->pos() == i.m_pis->pos())); } - inline bool operator< (const istream_iterator& i) const { return (!i.m_pis || (m_pis && m_pis->pos() < i.m_pis->pos())); } -private: - void Read (void) - { - if (!m_pis) - return; - const size_t rs (required_stream_size (m_v, *m_pis)); - if (m_pis->remaining() < rs && m_pis->underflow (rs) < rs) { - m_pis = NULL; - return; - } - *m_pis >> m_v; - if (stream_at_eof (*m_pis)) - m_pis = NULL; - } -private: - Stream* m_pis; ///< The host stream. - T m_v; ///< Last read value; cached to be returnable as a const reference. -}; - -//---------------------------------------------------------------------- - -/// Sets the current read position to \p newPos -inline void istream::seek (uoff_t newPos) -{ -#ifdef WANT_STREAM_BOUNDS_CHECKING - if (newPos > size()) - throw stream_bounds_exception ("seekg", "byte", pos(), newPos - pos(), size()); -#else - assert (newPos <= size()); -#endif - m_Pos = newPos; -} - -/// Sets the current read position to \p newPos -inline void istream::iseek (const_iterator newPos) -{ - seek (distance (begin(), newPos)); -} - -/// Sets the current write position to \p p based on \p d. -inline void istream::seekg (off_t p, seekdir d) -{ - switch (d) { - case beg: seek (p); break; - case cur: seek (pos() + p); break; - case ios_base::end: seek (size() - p); break; - } -} - -/// Skips \p nBytes without reading them. -inline void istream::skip (size_type nBytes) -{ - seek (pos() + nBytes); -} - -/// Returns the number of bytes to skip to be aligned on \p grain. -inline istream::size_type istream::align_size (size_type grain) const -{ - return (Align (pos(), grain) - pos()); -} - -/// Returns \c true if the read position is aligned on \p grain -inline bool istream::aligned (size_type grain) const -{ - assert (uintptr_t(begin()) % grain == 0 && "Streams should be attached aligned at the maximum element grain to avoid bus errors."); - return (pos() % grain == 0); -} - -/// aligns the read position on \p grain -inline void istream::align (size_type grain) -{ - seek (Align (pos(), grain)); -} - -/// Reads type T from the stream via a direct pointer cast. -template -inline void istream::iread (T& v) -{ - assert (aligned (alignof (T()))); -#ifdef WANT_STREAM_BOUNDS_CHECKING - verify_remaining ("read", typeid(v).name(), sizeof(T)); -#else - assert (remaining() >= sizeof(T)); -#endif - v = *reinterpret_cast(ipos()); - m_Pos += sizeof(T); -} - -#define ISTREAM_OPERATOR(type) \ -inline istream& operator>> (istream& is, type& v) { is.iread(v); return (is); } - -template -ISTREAM_OPERATOR(T*) -ISTREAM_OPERATOR(int8_t) -ISTREAM_OPERATOR(uint8_t) -ISTREAM_OPERATOR(int16_t) -ISTREAM_OPERATOR(uint16_t) -ISTREAM_OPERATOR(int32_t) -ISTREAM_OPERATOR(uint32_t) -ISTREAM_OPERATOR(float) -ISTREAM_OPERATOR(double) -ISTREAM_OPERATOR(wchar_t) -#if SIZE_OF_BOOL == SIZE_OF_CHAR -ISTREAM_OPERATOR(bool) -#else -inline istream& operator>> (istream& is, bool& v) -{ uint8_t v8; is.iread (v8); v = v8; return (is); } -#endif -#if HAVE_THREE_CHAR_TYPES -ISTREAM_OPERATOR(char) -#endif -#if HAVE_INT64_T -ISTREAM_OPERATOR(int64_t) -ISTREAM_OPERATOR(uint64_t) -#endif -#if SIZE_OF_LONG == SIZE_OF_INT -ISTREAM_OPERATOR(long) -ISTREAM_OPERATOR(unsigned long) -#endif -#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8) -ISTREAM_OPERATOR(long long) -ISTREAM_OPERATOR(unsigned long long) -#endif - -//---------------------------------------------------------------------- - -typedef istream_iterator istream_iterator_for_utf8; -typedef utf8in_iterator utf8istream_iterator; - -/// Returns a UTF-8 adaptor reading from \p is. -inline utf8istream_iterator utf8in (istream& is) -{ - istream_iterator_for_utf8 si (is); - return (utf8istream_iterator (si)); -} - -//---------------------------------------------------------------------- - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/mostream.h b/media/libdrm/mobile2/src/util/ustl-1.0/mostream.h deleted file mode 100644 index fb04196a16c677748ff30cacbe6dd6572da4c1a7..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/mostream.h +++ /dev/null @@ -1,260 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// mostream.h - -#ifndef MOSTREAM_H_24A8C5397E0848216573E5670930FC9A -#define MOSTREAM_H_24A8C5397E0848216573E5670930FC9A - -#include "memlink.h" -#include "uassert.h" -#include "uexception.h" -#include "utf8.h" -#include "uios.h" -#include - -namespace ustl { - -class istream; -class string; - -/// \class ostream mostream.h ustl.h -/// \ingroup BinaryStreams -/// -/// \brief Helper class to write packed binary streams. -/// -/// This class contains a set of functions to write integral types into an -/// unstructured memory block. Packing binary file data can be done this -/// way, for instance. aligning the data is your responsibility, and can -/// be accomplished by proper ordering of writes and by calling \ref ostream::align. -/// Unaligned access is usually slower by orders of magnitude and, -/// on some architectures, such as PowerPC, can cause your program to crash. -/// Therefore, all write functions have asserts to check alignment. -/// See \ref istream documentation for rules on designing your data format. -/// Overwriting the end of the stream will also cause a crash (an assert in -/// debug builds). Oh, and don't be intimidated by the size of the inlines -/// here. In the assembly code the compiler will usually chop everything down -/// to five instructions each. -/// -/// Example code: -/// \code -/// memblock b; -/// ostream os (b); -/// os << boolVar << ios::talign(); -/// os << intVar << floatVar; -/// os.write (binaryData, binaryDataSize); -/// os.align(); -/// b.resize (os.pos()); -/// b.write_file ("test.file"); -/// \endcode -/// -class ostream : public memlink, public ios_base { -public: - ostream (void); - ostream (void* p, size_type n); - explicit ostream (const memlink& source); - inline iterator end (void) { return (memlink::end()); } - inline const_iterator end (void) const { return (memlink::end()); } - inline void seek (uoff_t newPos); - inline void iseek (const_iterator newPos); - inline void skip (size_type nBytes); - inline uoff_t pos (void) const { return (m_Pos); } - inline iterator ipos (void) { return (begin() + pos()); } - inline const_iterator ipos (void) const { return (begin() + pos()); } - inline size_type remaining (void) const; - inline bool aligned (size_type grain = c_DefaultAlignment) const; - void verify_remaining (const char* op, const char* type, size_t n) const; - inline size_type align_size (size_type grain = c_DefaultAlignment) const; - void align (size_type grain = c_DefaultAlignment); - void write (const void* buffer, size_type size); - inline void write (const cmemlink& buf); - void write_strz (const char* str); - void read (istream& is); - inline void write (ostream& os) const { os.write (begin(), pos()); } - void text_write (ostringstream& os) const; - inline size_t stream_size (void) const { return (pos()); } - void insert (iterator start, size_type size); - void erase (iterator start, size_type size); - void swap (ostream& os); - template - inline void iwrite (const T& v); - inline virtual size_type overflow (size_type = 1){ return (remaining()); } - virtual void unlink (void); - inline void link (void* p, size_type n) { memlink::link (p, n); } - inline void link (memlink& l) { memlink::link (l.data(), l.writable_size()); } - inline void link (void* f, void* l) { memlink::link (f, l); } - OVERLOAD_POINTER_AND_SIZE_T_V2(link, void*) - inline void relink (void* p, size_type n) { memlink::relink (p, n); m_Pos = 0; } - inline void relink (memlink& l) { relink (l.data(), l.writable_size()); } - inline void seekp (off_t p, seekdir d = beg); - inline off_t tellp (void) const { return (pos()); } -protected: - inline void SetPos (uoff_t newPos) { m_Pos = newPos; } -private: - uoff_t m_Pos; ///< Current write position. -}; - -//---------------------------------------------------------------------- - -/// \class ostream_iterator mostream.h ustl.h -/// \ingroup BinaryStreamIterators -/// -/// \brief An iterator over an ostream to use with uSTL algorithms. -/// -template -class ostream_iterator { -public: - typedef T value_type; - typedef ptrdiff_t difference_type; - typedef value_type* pointer; - typedef value_type& reference; - typedef ostream::size_type size_type; -public: - inline explicit ostream_iterator (Stream& os) - : m_Os (os) {} - inline ostream_iterator (const ostream_iterator& iter) - : m_Os (iter.m_Os) {} - /// Writes \p v into the stream. - inline ostream_iterator& operator= (const T& v) - { m_Os << v; return (*this); } - inline ostream_iterator& operator* (void) { return (*this); } - inline ostream_iterator& operator++ (void) { return (*this); } - inline ostream_iterator operator++ (int) { return (*this); } - inline ostream_iterator& operator+= (size_type n) { m_Os.skip (n); return (*this); } - inline bool operator== (const ostream_iterator& i) const - { return (m_Os.pos() == i.m_Os.pos()); } - inline bool operator< (const ostream_iterator& i) const - { return (m_Os.pos() < i.m_Os.pos()); } -private: - Stream& m_Os; -}; - -//---------------------------------------------------------------------- - -typedef ostream_iterator ostream_iterator_for_utf8; -typedef utf8out_iterator utf8ostream_iterator; - -/// Returns a UTF-8 adaptor writing to \p os. -inline utf8ostream_iterator utf8out (ostream& os) -{ - ostream_iterator_for_utf8 si (os); - return (utf8ostream_iterator (si)); -} - -//---------------------------------------------------------------------- - -/// Move the write pointer to \p newPos -inline void ostream::seek (uoff_t newPos) -{ -#ifdef WANT_STREAM_BOUNDS_CHECKING - if (newPos > size()) - throw stream_bounds_exception ("seekp", "byte", pos(), newPos - pos(), size()); -#else - assert (newPos <= size()); -#endif - SetPos (newPos); -} - -/// Sets the current write position to \p newPos -inline void ostream::iseek (const_iterator newPos) -{ - seek (distance (begin(), const_cast(newPos))); -} - -/// Sets the current write position to \p p based on \p d. -inline void ostream::seekp (off_t p, seekdir d) -{ - switch (d) { - case beg: seek (p); break; - case cur: seek (pos() + p); break; - case ios_base::end: seek (size() - p); break; - } -} - -/// Skips \p nBytes without writing anything. -inline void ostream::skip (size_type nBytes) -{ - seek (pos() + nBytes); -} - -/// Returns number of bytes remaining in the write buffer. -inline ostream::size_type ostream::remaining (void) const -{ - return (size() - pos()); -} - -/// Returns \c true if the write pointer is aligned on \p grain -inline bool ostream::aligned (size_type grain) const -{ - assert (uintptr_t(begin()) % grain == 0 && "Streams should be attached aligned at the maximum element grain to avoid bus errors."); - return (pos() % grain == 0); -} - -/// Returns the number of bytes to skip to be aligned on \p grain. -inline ostream::size_type ostream::align_size (size_type grain) const -{ - return (Align (pos(), grain) - pos()); -} - -/// Writes the contents of \p buf into the stream as a raw dump. -inline void ostream::write (const cmemlink& buf) -{ - write (buf.begin(), buf.size()); -} - -/// Writes type T into the stream via a direct pointer cast. -template -inline void ostream::iwrite (const T& v) -{ - assert (aligned (alignof (v))); -#ifdef WANT_STREAM_BOUNDS_CHECKING - verify_remaining ("write", typeid(v).name(), sizeof(T)); -#else - assert (remaining() >= sizeof(T)); -#endif - *reinterpret_cast(ipos()) = v; - SetPos (pos() + sizeof(T)); -} - -#define OSTREAM_OPERATOR(type) \ -inline ostream& operator<< (ostream& os, type v) { os.iwrite(v); return (os); } - -template -OSTREAM_OPERATOR(T*) -OSTREAM_OPERATOR(int8_t) -OSTREAM_OPERATOR(uint8_t) -OSTREAM_OPERATOR(int16_t) -OSTREAM_OPERATOR(uint16_t) -OSTREAM_OPERATOR(int32_t) -OSTREAM_OPERATOR(uint32_t) -OSTREAM_OPERATOR(float) -OSTREAM_OPERATOR(double) -OSTREAM_OPERATOR(wchar_t) -#if SIZE_OF_BOOL == SIZE_OF_CHAR -OSTREAM_OPERATOR(bool) -#else -inline ostream& operator<< (ostream& os, bool v) -{ os.iwrite (uint8_t(v)); return (os); } -#endif -#if HAVE_THREE_CHAR_TYPES -OSTREAM_OPERATOR(char) -#endif -#if HAVE_INT64_T -OSTREAM_OPERATOR(int64_t) -OSTREAM_OPERATOR(uint64_t) -#endif -#if SIZE_OF_LONG == SIZE_OF_INT -OSTREAM_OPERATOR(long) -OSTREAM_OPERATOR(unsigned long) -#endif -#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8) -OSTREAM_OPERATOR(long long) -OSTREAM_OPERATOR(unsigned long long) -#endif - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.cpp deleted file mode 100644 index 0948a4d35cc0ef9b76186630c7546899775fe8d3..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ofstream.cc -// - -#include "ofstream.h" -#include "ustring.h" -#include "uexception.h" -#include -#include -#include -#include - -namespace ustl { - -//---------------------------------------------------------------------- - -ifstream cin (STDIN_FILENO); -ofstream cout (STDOUT_FILENO); -ofstream cerr (STDERR_FILENO); - -//---------------------------------------------------------------------- - -/// Default constructor. -ofstream::ofstream (void) -: ostringstream (), - m_File () -{ - reserve (255); -} - -/// Constructs a stream for writing to \p Fd. -ofstream::ofstream (int Fd) -: ostringstream (), - m_File (Fd) -{ - clear (m_File.rdstate()); - reserve (255); -} - -/// Constructs a stream for writing to \p filename. -ofstream::ofstream (const char* filename, openmode mode) -: ostringstream (), - m_File (filename, mode) -{ - clear (m_File.rdstate()); -} - -/// Default destructor. -ofstream::~ofstream (void) -{ -#if PLATFORM_ANDROID - flush(); -#else /* !PLATFORM_ANDROID */ - try { flush(); } catch (...) {} -#endif -} - -/// Flushes the buffer to the file. -void ofstream::flush (void) -{ - while (pos() && overflow (remaining())); - m_File.sync(); - clear (m_File.rdstate()); -} - -/// Seeks to \p p based on \p d. -void ofstream::seekp (off_t p, seekdir d) -{ - flush(); - m_File.seekp (p, d); - clear (m_File.rdstate()); -} - -/// Called when more buffer space (\p n bytes) is needed. -ofstream::size_type ofstream::overflow (size_type n) -{ - if (eof() || (n > remaining() && n < capacity() - pos())) - return (ostringstream::overflow (n)); - size_type bw = m_File.write (cdata(), pos()); - clear (m_File.rdstate()); - erase (begin(), bw); - if (remaining() < n) - ostringstream::overflow (n); - return (remaining()); -} - -//---------------------------------------------------------------------- - -/// Constructs a stream to read from \p Fd. -ifstream::ifstream (int Fd) -: istringstream (), - m_Buffer (255), - m_File (Fd) -{ - link (m_Buffer.data(), 0U); -} - -/// Constructs a stream to read from \p filename. -ifstream::ifstream (const char* filename, openmode mode) -: istringstream (), - m_Buffer (255), - m_File (filename, mode) -{ - clear (m_File.rdstate()); - link (m_Buffer.data(), 0U); -} - -/// Reads at least \p n more bytes and returns available bytes. -ifstream::size_type ifstream::underflow (size_type n) -{ - if (eof()) - return (istringstream::underflow (n)); - - const ssize_t freeSpace = m_Buffer.size() - pos(); - const ssize_t neededFreeSpace = max (n, m_Buffer.size() / 2); - const size_t oughtToErase = Align (max (0, neededFreeSpace - freeSpace)); - const size_t nToErase = min (pos(), oughtToErase); - m_Buffer.memlink::erase (m_Buffer.begin(), nToErase); - const uoff_t oldPos (pos() - nToErase); - - size_type br = oldPos; - if (m_Buffer.size() - br < n) { - m_Buffer.resize (br + neededFreeSpace); - link (m_Buffer.data(), 0U); - } - cout.flush(); - - while (br - oldPos < n && m_File.good()) - br += m_File.readsome (m_Buffer.begin() + br, m_Buffer.size() - br); - clear (m_File.rdstate()); - - m_Buffer[br] = string::c_Terminator; - link (m_Buffer.data(), br); - seek (oldPos); - return (remaining()); -} - -/// Flushes the input. -void ifstream::sync (void) -{ - istringstream::sync(); - underflow (0U); - m_File.sync(); - clear (m_File.rdstate()); -} - -/// Seeks to \p p based on \p d. -void ifstream::seekg (off_t p, seekdir d) -{ - m_Buffer.clear(); - link (m_Buffer); - m_File.seekg (p, d); - clear (m_File.rdstate()); -} - -//---------------------------------------------------------------------- - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.h b/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.h deleted file mode 100644 index 77808331584cd1a320c531094bc01a39bbbf81ed..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.h +++ /dev/null @@ -1,82 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ofstream.h -// - -#ifndef FDOSTREAM_H_5E27FC3D530BF3CA04D6C73F5700EECC -#define FDOSTREAM_H_5E27FC3D530BF3CA04D6C73F5700EECC - -#include "sistream.h" -#include "sostream.h" -#include "fstream.h" - -namespace ustl { - -/// \class ofstream fdostream.h ustl.h -/// \ingroup DeviceStreams -/// \brief A string stream that writes to an fd. Implements cout and cerr. -class ofstream : public ostringstream { -public: - ofstream (void); - explicit ofstream (int Fd); - explicit ofstream (const char* filename, openmode mode = out); - virtual ~ofstream (void); - inline void open (const char* filename, openmode mode = out) { m_File.open (filename, mode); clear (m_File.rdstate()); } - inline void close (void) { m_File.close(); clear (m_File.rdstate()); } - inline bool is_open (void) const { return (m_File.is_open()); } - inline iostate exceptions (iostate v) { ostringstream::exceptions(v); return (m_File.exceptions(v)); } - inline void setstate (iostate v) { ostringstream::setstate(v); m_File.setstate(v); } - inline void clear (iostate v = goodbit) { ostringstream::clear(v); m_File.clear(v); } - inline off_t tellp (void) const { return (m_File.tellp() + ostringstream::tellp()); } - inline int fd (void) const { return (m_File.fd()); } - inline void stat (struct stat& rs) const { m_File.stat (rs); } - inline void set_nonblock (bool v = true) { m_File.set_nonblock (v); } - inline int ioctl (const char* rname, int request, long argument = 0) { return (m_File.ioctl (rname, request, argument)); } - inline int ioctl (const char* rname, int request, int argument) { return (m_File.ioctl (rname, request, argument)); } - inline int ioctl (const char* rname, int request, void* argument) { return (m_File.ioctl (rname, request, argument)); } - void seekp (off_t p, seekdir d = beg); - void flush (void); - virtual size_type overflow (size_type n = 1); -private: - fstream m_File; -}; - -/// \class ifstream fdostream.h ustl.h -/// \ingroup DeviceStreams -/// \brief A string stream that reads from an fd. Implements cin. -class ifstream : public istringstream { -public: - ifstream (void); - explicit ifstream (int Fd); - explicit ifstream (const char* filename, openmode mode = in); - inline void open (const char* filename, openmode mode = in) { m_File.open (filename, mode); clear (m_File.rdstate()); } - inline void close (void) { m_File.close(); clear (m_File.rdstate()); } - inline bool is_open (void) const { return (m_File.is_open()); } - inline iostate exceptions (iostate v) { istringstream::exceptions(v); return (m_File.exceptions(v)); } - inline void setstate (iostate v) { istringstream::setstate(v); m_File.setstate(v); } - inline void clear (iostate v = goodbit) { istringstream::clear(v); m_File.clear(v); } - inline off_t tellg (void) const { return (m_File.tellg() - remaining()); } - inline int fd (void) const { return (m_File.fd()); } - inline void stat (struct stat& rs) const { m_File.stat (rs); } - inline void set_nonblock (bool v = true) { m_File.set_nonblock (v); } - inline int ioctl (const char* rname, int request, long argument = 0) { return (m_File.ioctl (rname, request, argument)); } - inline int ioctl (const char* rname, int request, int argument) { return (m_File.ioctl (rname, request, argument)); } - inline int ioctl (const char* rname, int request, void* argument) { return (m_File.ioctl (rname, request, argument)); } - void seekg (off_t p, seekdir d = beg); - void sync (void); - virtual size_type underflow (size_type n = 1); -private: - string m_Buffer; - fstream m_File; -}; - -extern ofstream cout, cerr; -extern ifstream cin; - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/simd.h b/media/libdrm/mobile2/src/util/ustl-1.0/simd.h deleted file mode 100644 index 950efc2116e5532d4ffb1f042204302a192e2593..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/simd.h +++ /dev/null @@ -1,465 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -/// \file simd.h -/// \brief SIMD-type algorithms, with hardware acceleration, if available. -/// -/// All algorithms are container-based because iterator syntax is just too -/// damn verbose and because the specializations need to be able to tell -/// how many elements are in the container in order to choose proper SIMD -/// instruction set (i.e.: 4 floats select SSE, while 2 floats select 3dNow!) -/// Specializations are only for the tuple template because the container -/// must be of a fixed and compile-time-known size for the compiler to be -/// able to choose the specialization. -/// - -#ifndef SIMD_H_39BE2D970DF4BD00508CCFFB482496F9 -#define SIMD_H_39BE2D970DF4BD00508CCFFB482496F9 - -#include "uassert.h" -#include "ulimits.h" -#if HAVE_MATH_H - #include -#endif - -#if PLATFORM_ANDROID -#include -#undef CPU_HAS_MMX -#endif - -namespace ustl { -namespace simd { - -//---------------------------------------------------------------------- -// Generic algorithms -//---------------------------------------------------------------------- - -/// Applies \p op to each element in \p op1. -template -inline void packop (Ctr& op1, UnaryOperation op) -{ - foreach (typename Ctr::iterator, i, op1) - op (*i); -} - -/// Applies \p op to each element in \p op1 and \p op2 and stores in \p op2. -template -inline void packop (const Ctr& op1, Ctr& op2, BinaryOperation op) -{ - assert (op2.size() <= op1.size()); - typename Ctr::const_iterator i1 (op1.begin()); - typename Ctr::iterator i2 (op2.begin()); - for (; i2 != op2.end(); ++i1, ++i2) - *i2 = op (*i2, *i1); -} - -/// Applies \p op to corresponding elements in \p op1 and \p op2 and stores in \p result. -template -inline void packop (const Ctr& op1, const Ctr& op2, Ctr& result, BinaryOperation op) -{ - assert (op1.size() <= op2.size() && op1.size() <= result.size()); - passign (op1, result); - packop (op2, result); -} - -/// Copies \p op1 into \p result. -template -inline void passign (const Ctr& op1, Ctr& result) -{ - assert (op1.size() <= result.size()); - typename Ctr::iterator d (result.begin()); - foreach (typename Ctr::const_iterator, s, op1) - *d++ = *s; -} - -/// Copies \p result.size() elements from \p op1 to \p result. -template -inline void ipassign (typename Ctr::const_iterator op1, Ctr& result) -{ - foreach (typename Ctr::iterator, d, result) - *d = *op1++; -} - -template -inline void pconvert (const Ctr1& op1, Ctr2& op2, ConvertFunction f) -{ - assert (op1.size() <= op2.size()); - typename Ctr1::const_iterator i1 (op1.begin()); - typename Ctr2::iterator i2 (op2.begin()); - for (; i1 != op1.end(); ++i1, ++i2) - *i2 = f (*i1); -} - -// Functionoids for SIMD operations, like saturation arithmetic, shifts, etc. -STD_BINARY_FUNCTOR (fpadds, T, ((b > numeric_limits::max() - a) ? numeric_limits::max() : a + b)) -STD_BINARY_FUNCTOR (fpsubs, T, ((a < numeric_limits::min() + b) ? numeric_limits::min() : a - b)) -STD_BINARY_FUNCTOR (fpshl, T, (a << b)) -STD_BINARY_FUNCTOR (fpshr, T, (a >> b)) -STD_BINARY_FUNCTOR (fpmin, T, (min (a, b))) -STD_BINARY_FUNCTOR (fpmax, T, (max (a, b))) -STD_BINARY_FUNCTOR (fpavg, T, ((a + b + 1) / 2)) -STD_CONVERSION_FUNCTOR (fcast, (D(a))) -#if HAVE_MATH_H -STD_UNARY_FUNCTOR (fpreciprocal,T, (1 / a)) -STD_UNARY_FUNCTOR (fpsqrt, T, (reset_mmx(), T (sqrt (a)))) -STD_UNARY_FUNCTOR (fprecipsqrt, T, (reset_mmx(), 1 / T(sqrt (a)))) -STD_UNARY_FUNCTOR (fsin, T, (reset_mmx(), T (sin (a)))) -STD_UNARY_FUNCTOR (fcos, T, (reset_mmx(), T (cos (a)))) -STD_UNARY_FUNCTOR (ftan, T, (reset_mmx(), T (tan (a)))) -#if HAVE_RINTF -STD_CONVERSION_FUNCTOR (fround, (reset_mmx(), D(rintf(a)))) -#else -STD_CONVERSION_FUNCTOR (fround, (reset_mmx(), D(rint(a)))) -#endif -template <> inline int32_t fround::operator()(const double& a) const { reset_mmx(); return (int32_t(rint(a))); } -#endif -template <> inline float fpavg::operator()(const float& a, const float& b) const { return ((a + b) / 2); } -template <> inline double fpavg::operator()(const double& a, const double& b) const { return ((a + b) / 2); } - -#define SIMD_PACKEDOP1(name, operation) \ -template \ -inline void name (Ctr& op1) \ -{ \ - typedef typename Ctr::value_type value_t; \ - packop (op1, operation()); \ -} -#define SIMD_PACKEDOP2(name, operation) \ -template \ -inline void name (const Ctr& op1, Ctr& op2) \ -{ \ - typedef typename Ctr::value_type value_t; \ - packop (op1, op2, operation()); \ -} -#define SIMD_PACKEDOP3(name, operation) \ -template \ -inline void name (const Ctr& op1, const Ctr& op2, Ctr& result) \ -{ \ - typedef typename Ctr::value_type value_t; \ - packop (op1, op2, result, operation()); \ -} -#define SIMD_SINGLEOP1(name, operation) \ -template \ -inline T name (T op) \ -{ \ - operation obj; \ - return (obj(op)); \ -} -#define SIMD_CONVERTOP(name, operation) \ -template \ -inline void name (const Ctr1& op1, Ctr2& op2) \ -{ \ - typedef typename Ctr1::value_type value1_t; \ - typedef typename Ctr2::value_type value2_t; \ - pconvert (op1, op2, operation());\ -} - -SIMD_PACKEDOP2 (padd, plus) -SIMD_PACKEDOP2 (psub, minus) -SIMD_PACKEDOP2 (pmul, multiplies) -SIMD_PACKEDOP2 (pdiv, divides) -SIMD_PACKEDOP2 (pand, bitwise_and) -SIMD_PACKEDOP2 (por, bitwise_or) -SIMD_PACKEDOP2 (pxor, bitwise_xor) -SIMD_PACKEDOP2 (pshl, fpshl) -SIMD_PACKEDOP2 (pshr, fpshr) -SIMD_PACKEDOP2 (psubs, fpsubs) -SIMD_PACKEDOP2 (pmin, fpmin) -SIMD_PACKEDOP2 (pmax, fpmax) -SIMD_PACKEDOP2 (pavg, fpavg) - -SIMD_PACKEDOP3 (padd, plus) -SIMD_PACKEDOP3 (psub, minus) -SIMD_PACKEDOP3 (pmul, multiplies) -SIMD_PACKEDOP3 (pdiv, divides) -SIMD_PACKEDOP3 (pand, bitwise_and) -SIMD_PACKEDOP3 (por, bitwise_or) -SIMD_PACKEDOP3 (pxor, bitwise_xor) -SIMD_PACKEDOP3 (pshl, fpshl) -SIMD_PACKEDOP3 (pshr, fpshr) -SIMD_PACKEDOP3 (padds, fpadds) -SIMD_PACKEDOP3 (psubs, fpsubs) -SIMD_PACKEDOP3 (pmin, fpmin) -SIMD_PACKEDOP3 (pmax, fpmax) -SIMD_PACKEDOP3 (pavg, fpavg) - -#if HAVE_MATH_H -SIMD_PACKEDOP1 (precip, fpreciprocal) -SIMD_PACKEDOP1 (psqrt, fpsqrt) -SIMD_PACKEDOP1 (precipsqrt, fprecipsqrt) -SIMD_PACKEDOP1 (psin, fsin) -SIMD_PACKEDOP1 (pcos, fcos) -SIMD_PACKEDOP1 (ptan, ftan) - -SIMD_SINGLEOP1 (srecip, fpreciprocal) -SIMD_SINGLEOP1 (ssqrt, fpsqrt) -SIMD_SINGLEOP1 (srecipsqrt, fprecipsqrt) -SIMD_SINGLEOP1 (ssin, fsin) -SIMD_SINGLEOP1 (scos, fcos) -SIMD_SINGLEOP1 (stan, ftan) - -SIMD_CONVERTOP (pround, fround) - -template inline int32_t sround (T op) { fround obj; return (obj (op)); } -#endif - -#undef SIMD_SINGLEOP1 -#undef SIMD_PACKEDOP3 -#undef SIMD_PACKEDOP2 -#undef SIMD_PACKEDOP1 - -//---------------------------------------------------------------------- -// Vector types to cast tuple data to -//---------------------------------------------------------------------- - -#if HAVE_VECTOR_EXTENSIONS && __GNUC__ >= 4 -#define VECTOR_ATTRIBUTE(mode,vs) __attribute__((vector_size(vs))) -#else -#define VECTOR_ATTRIBUTE(mode,vs) -#endif -typedef uint8_t v8qi_t VECTOR_ATTRIBUTE (V8QI,8); -typedef uint16_t v4hi_t VECTOR_ATTRIBUTE (V4HI,8); -typedef uint16_t v8hi_t VECTOR_ATTRIBUTE (V8HI,16); -typedef uint32_t v2si_t VECTOR_ATTRIBUTE (V2SI,8); -typedef uint32_t v4si_t VECTOR_ATTRIBUTE (V4SI,16); -#if HAVE_INT64_T -typedef uint64_t v1di_t VECTOR_ATTRIBUTE (V1DI,8); -#endif -typedef float v2sf_t VECTOR_ATTRIBUTE (V2SF,8); -typedef float v4sf_t VECTOR_ATTRIBUTE (V4SF,16); -typedef double v2df_t VECTOR_ATTRIBUTE (V2DF,16); -#undef VECTOR_ATTRIBUTE - -//---------------------------------------------------------------------- -// Hardware accelerated specializations -//---------------------------------------------------------------------- - -#define SIMD_PKOP2_SPEC(n, type, optype) \ -template <> \ -inline void packop (const tuple& oin, tuple& oout, optype) -#define SIMD_PASSIGN_SPEC(n, type) \ -template <> \ -inline void passign (const tuple& oin, tuple& oout) -#define SIMD_IPASSIGN_SPEC(n, type) \ -template <> \ -inline void ipassign (tuple::const_iterator oin, tuple& oout) -#define SIMD_CONVERT_SPEC(n, type1, type2, optype) \ -template <> \ -inline void pconvert (const tuple& oin, tuple& oout, optype) - -#if CPU_HAS_MMX -#define STD_MMX_ARGS "=m"(oout[0]) : "m"(oin[0]) : "mm0", "st", "memory" -#define DBL_MMX_ARGS "=m"(oout[0]), "=m"(oout[2]) : "m"(oin[0]), "m"(oin[2]) : "mm0", "mm1", "st", "st(1)", "memory" -#define MMX_PKOP2_SPEC(n,type,optype,instruction) \ -SIMD_PKOP2_SPEC(n,type,optype) \ -{ asm ("movq %0, %%mm0\n\t" #instruction " %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); } -#define MMX_DBL_PKOP2_SPEC(n,type,optype,instruction) \ -SIMD_PKOP2_SPEC(n,type,optype) \ -{ asm ("movq %0, %%mm0\n\tmovq %1, %%mm1\n\t" #instruction " %2, %%mm0\n\t" #instruction " %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); } -#define MMX_PASSIGN_SPEC(n,type) \ -SIMD_PASSIGN_SPEC(n,type) \ -{ asm ("movq %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); } -#define MMX_DBL_PASSIGN_SPEC(n,type) \ -SIMD_PASSIGN_SPEC(n,type) \ -{ asm ("movq %2, %%mm0\n\tmovq %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); } -#define MMX_IPASSIGN_SPEC(n,type) \ -SIMD_IPASSIGN_SPEC(n,type) \ -{ asm ("movq %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); } -#define MMX_DBL_IPASSIGN_SPEC(n,type) \ -SIMD_IPASSIGN_SPEC(n,type) \ -{ asm ("movq %2, %%mm0\n\tmovq %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); } - -MMX_PASSIGN_SPEC(8,uint8_t) -MMX_PKOP2_SPEC(8,uint8_t,plus,paddb) -MMX_PKOP2_SPEC(8,uint8_t,minus,psubb) -MMX_PKOP2_SPEC(8,uint8_t,bitwise_and,pand) -MMX_PKOP2_SPEC(8,uint8_t,bitwise_or,por) -MMX_PKOP2_SPEC(8,uint8_t,bitwise_xor,pxor) -MMX_PKOP2_SPEC(8,uint8_t,fpadds,paddusb) -MMX_PKOP2_SPEC(8,uint8_t,fpsubs,psubusb) - -MMX_PASSIGN_SPEC(8,int8_t) -MMX_PKOP2_SPEC(8,int8_t,plus,paddb) -MMX_PKOP2_SPEC(8,int8_t,minus,psubb) -MMX_PKOP2_SPEC(8,int8_t,bitwise_and,pand) -MMX_PKOP2_SPEC(8,int8_t,bitwise_or,por) -MMX_PKOP2_SPEC(8,int8_t,bitwise_xor,pxor) -MMX_PKOP2_SPEC(8,int8_t,fpadds,paddsb) -MMX_PKOP2_SPEC(8,int8_t,fpsubs,psubsb) - -MMX_PASSIGN_SPEC(4,uint16_t) -MMX_PKOP2_SPEC(4,uint16_t,plus,paddw) -MMX_PKOP2_SPEC(4,uint16_t,minus,psubw) -MMX_PKOP2_SPEC(4,uint16_t,bitwise_and,pand) -MMX_PKOP2_SPEC(4,uint16_t,bitwise_or,por) -MMX_PKOP2_SPEC(4,uint16_t,bitwise_xor,pxor) -/// \todo psllw does not work like other operations, it uses the first element for shift count. -//MMX_PKOP2_SPEC(4,uint16_t,fpshl,psllw) -//MMX_PKOP2_SPEC(4,uint16_t,fpshr,psrlw) -MMX_PKOP2_SPEC(4,uint16_t,fpadds,paddusw) -MMX_PKOP2_SPEC(4,uint16_t,fpsubs,psubusw) - -MMX_PASSIGN_SPEC(4,int16_t) -MMX_PKOP2_SPEC(4,int16_t,plus,paddw) -MMX_PKOP2_SPEC(4,int16_t,minus,psubw) -MMX_PKOP2_SPEC(4,int16_t,bitwise_and,pand) -MMX_PKOP2_SPEC(4,int16_t,bitwise_or,por) -MMX_PKOP2_SPEC(4,int16_t,bitwise_xor,pxor) -//MMX_PKOP2_SPEC(4,int16_t,fpshl,psllw) -//MMX_PKOP2_SPEC(4,int16_t,fpshr,psrlw) -MMX_PKOP2_SPEC(4,int16_t,fpadds,paddsw) -MMX_PKOP2_SPEC(4,int16_t,fpsubs,psubsw) - -MMX_PASSIGN_SPEC(2,uint32_t) -MMX_PKOP2_SPEC(2,uint32_t,plus,paddd) -MMX_PKOP2_SPEC(2,uint32_t,minus,psubd) -MMX_PKOP2_SPEC(2,uint32_t,bitwise_and,pand) -MMX_PKOP2_SPEC(2,uint32_t,bitwise_or,por) -MMX_PKOP2_SPEC(2,uint32_t,bitwise_xor,pxor) -//MMX_PKOP2_SPEC(2,uint32_t,fpshl,pslld) -//MMX_PKOP2_SPEC(2,uint32_t,fpshr,psrld) - -MMX_PASSIGN_SPEC(2,int32_t) -MMX_PKOP2_SPEC(2,int32_t,plus,paddd) -MMX_PKOP2_SPEC(2,int32_t,minus,psubd) -MMX_PKOP2_SPEC(2,int32_t,bitwise_and,pand) -MMX_PKOP2_SPEC(2,int32_t,bitwise_or,por) -MMX_PKOP2_SPEC(2,int32_t,bitwise_xor,pxor) -//MMX_PKOP2_SPEC(2,int32_t,fpshl,pslld) -//MMX_PKOP2_SPEC(2,int32_t,fpshr,psrld) - -MMX_DBL_PKOP2_SPEC(4,uint32_t,plus,paddd) -MMX_DBL_PKOP2_SPEC(4,uint32_t,minus,psubd) -MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_and,pand) -MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_or,por) -MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_xor,pxor) -//MMX_DBL_PKOP2_SPEC(2,uint32_t,fpshl,pslld) -//MMX_DBL_PKOP2_SPEC(2,uint32_t,fpshr,psrld) - -MMX_DBL_PKOP2_SPEC(4,int32_t,plus,paddd) -MMX_DBL_PKOP2_SPEC(4,int32_t,minus,psubd) -MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_and,pand) -MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_or,por) -MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_xor,pxor) -//MMX_DBL_PKOP2_SPEC(2,int32_t,fpshl,pslld) -//MMX_DBL_PKOP2_SPEC(2,int32_t,fpshr,psrld) - -#if CPU_HAS_SSE || CPU_HAS_3DNOW -MMX_PKOP2_SPEC(8,uint8_t,fpavg,pavgb) -MMX_PKOP2_SPEC(8,int8_t,fpavg,pavgb) -MMX_PKOP2_SPEC(4,uint16_t,fpavg,pavgw) -MMX_PKOP2_SPEC(4,int16_t,fpavg,pavgw) -MMX_PKOP2_SPEC(8,uint8_t,fpmin,pminub) -MMX_PKOP2_SPEC(8,uint8_t,fpmax,pmaxub) -MMX_PKOP2_SPEC(4,int16_t,fpmax,pmaxsw) -MMX_PKOP2_SPEC(4,int16_t,fpmin,pminsw) -#endif // CPU_HAS_SSE || CPU_HAS_3DNOW - -#if CPU_HAS_3DNOW -MMX_PASSIGN_SPEC(2,float) -MMX_PKOP2_SPEC(2,float,plus,pfadd) -MMX_PKOP2_SPEC(2,float,minus,pfsub) -MMX_PKOP2_SPEC(2,float,multiplies,pfmul) -MMX_PKOP2_SPEC(2,float,fpmin,pfmin) -MMX_PKOP2_SPEC(2,float,fpmax,pfmax) -#ifndef CPU_HAS_SSE -MMX_DBL_PKOP2_SPEC(4,float,plus,pfadd) -MMX_DBL_PKOP2_SPEC(4,float,minus,pfsub) -MMX_DBL_PKOP2_SPEC(4,float,multiplies,pfmul) -MMX_DBL_PKOP2_SPEC(4,float,fpmin,pfmin) -MMX_DBL_PKOP2_SPEC(4,float,fpmax,pfmax) -#endif -#endif // CPU_HAS_3DNOW - -MMX_IPASSIGN_SPEC(8,uint8_t) -MMX_IPASSIGN_SPEC(4,uint16_t) -MMX_IPASSIGN_SPEC(2,uint32_t) -MMX_IPASSIGN_SPEC(2,float) - -#ifndef CPU_HAS_SSE -MMX_DBL_PASSIGN_SPEC(4,float) -MMX_DBL_PASSIGN_SPEC(4,uint32_t) -MMX_DBL_PASSIGN_SPEC(4,int32_t) -MMX_DBL_IPASSIGN_SPEC(4,float) -MMX_DBL_IPASSIGN_SPEC(4,uint32_t) -MMX_DBL_IPASSIGN_SPEC(4,int32_t) -#endif - -#undef MMX_IPASSIGN_SPEC -#undef MMX_PASSIGN_SPEC -#undef MMX_PKOP2_SPEC -#undef STD_MMX_ARGS -#endif // CPU_HAS_MMX - -#if CPU_HAS_SSE -#define STD_SSE_ARGS "=m"(oout[0]) : "m"(oin[0]) : "xmm0", "memory" -#define SSE_PKOP2_SPEC(n,type,optype,instruction) \ -SIMD_PKOP2_SPEC(n,type,optype) \ -{ asm ("movups %0, %%xmm0\n\tmovups %1, %%xmm1\n\t" #instruction " %%xmm1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);} -#define SSE_PASSIGN_SPEC(n,type) \ -SIMD_PASSIGN_SPEC(n,type) \ -{ asm ("movups %1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);} -#define SSE_IPASSIGN_SPEC(n,type) \ -SIMD_IPASSIGN_SPEC(n,type) \ -{ asm ("movups %1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);} -SSE_PASSIGN_SPEC(4,float) -SSE_PASSIGN_SPEC(4,int32_t) -SSE_PASSIGN_SPEC(4,uint32_t) -SSE_PKOP2_SPEC(4,float,plus,addps) -SSE_PKOP2_SPEC(4,float,minus,subps) -SSE_PKOP2_SPEC(4,float,multiplies,mulps) -SSE_PKOP2_SPEC(4,float,divides,divps) -SSE_PKOP2_SPEC(4,float,bitwise_and,andps) -SSE_PKOP2_SPEC(4,float,bitwise_or,orps) -SSE_PKOP2_SPEC(4,float,bitwise_xor,xorps) -SSE_PKOP2_SPEC(4,float,fpmax,maxps) -SSE_PKOP2_SPEC(4,float,fpmin,minps) - -SIMD_CONVERT_SPEC(4,float,int32_t,fround) { - asm ("cvtps2pi %2, %%mm0\n\t" - "cvtps2pi %3, %%mm1\n\t" - "movq %%mm0, %0\n\t" - "movq %%mm1, %1" - : DBL_MMX_ARGS); - reset_mmx(); -} -SIMD_CONVERT_SPEC(4,int32_t,float,fround) { - asm ("cvtpi2ps %2, %%xmm0\n\t" - "shufps $0x4E,%%xmm0,%%xmm0\n\t" - "cvtpi2ps %1, %%xmm0\n\t" - "movups %%xmm0, %0" - : "=m"(oout[0]) : "m"(oin[0]), "m"(oin[2]) : "xmm0", "memory"); -} -template <> inline int32_t fround::operator()(const float& a) const { - register int32_t rv; - asm ("movss %1, %%xmm0\n\t" - "cvtss2si %%xmm0, %0" - : "=r"(rv) : "m"(a) : "xmm0" ); - return (rv); -} -template <> inline uint32_t fround::operator()(const float& a) const { - register uint32_t rv; - asm ("movss %1, %%xmm0\n\t" - "cvtss2si %%xmm0, %0" - : "=r"(rv) : "m"(a) : "xmm0" ); - return (rv); -} - -SSE_IPASSIGN_SPEC(4,float) -SSE_IPASSIGN_SPEC(4,int32_t) -SSE_IPASSIGN_SPEC(4,uint32_t) - -#undef SSE_IPASSIGN_SPEC -#undef SSE_PASSIGN_SPEC -#undef SSE_PKOP2_SPEC -#undef STD_SSE_ARGS -#endif // CPU_HAS_SSE - -#undef SIMD_PACKEDOP_SPEC - -} // namespace simd -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/sistream.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/sistream.cpp deleted file mode 100644 index 8a20ddfdfad13dda1eb360078f615d3073e75af1..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/sistream.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// sistream.cc -// - -#include "sistream.h" -#include "sostream.h" -#include "uassert.h" -#include "ustring.h" - -namespace ustl { - -const char ios_base::c_DefaultDelimiters [istringstream::c_MaxDelimiters] = " \t\n\r;:,.?"; - -/// Default constructor. -istringstream::istringstream (void) -: istream (), - m_Base (0) -{ - set_delimiters (c_DefaultDelimiters); -} - -istringstream::istringstream (const void* p, size_type n) -: istream (), - m_Base (0) -{ - link (p, n); - set_delimiters (c_DefaultDelimiters); -} - -istringstream::istringstream (const cmemlink& source) -: istream (), - m_Base (0) -{ - link (source); - set_delimiters (c_DefaultDelimiters); -} - -/// Sets delimiters to the contents of \p delimiters. -void istringstream::set_delimiters (const char* delimiters) -{ - fill (VectorRange (m_Delimiters), '\0'); - strncpy (m_Delimiters, delimiters, VectorSize(m_Delimiters)-1); -} - -inline bool istringstream::is_delimiter (char c) const -{ - return (memchr (m_Delimiters, c, VectorSize(m_Delimiters)-1)); -} - -char istringstream::skip_delimiters (void) -{ - char c = m_Delimiters[0]; - while (is_delimiter(c) && (remaining() || underflow())) - istream::iread (c); - return (c); -} - -void istringstream::iread (int8_t& v) -{ - v = skip_delimiters(); -} - -typedef istringstream::iterator issiter_t; -template -inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t base, T& v) - { v = strtol (i, const_cast(iend), base); } -template <> inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t, double& v) - { v = strtod (i, const_cast(iend)); } -#ifdef HAVE_LONG_LONG -template <> inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t base, long long& v) - { v = strtoll (i, const_cast(iend), base); } -#endif - -template -inline void istringstream::read_number (T& v) -{ - v = 0; - if (skip_delimiters() == m_Delimiters[0]) - return; - ungetc(); - iterator ilast; - do { - str_to_num (ipos(), &ilast, m_Base, v); - } while (ilast == end() && underflow()); - skip (distance (ipos(), ilast)); -} - -void istringstream::iread (int32_t& v) { read_number (v); } -void istringstream::iread (double& v) { read_number (v); } -#if HAVE_INT64_T -void istringstream::iread (int64_t& v) { read_number (v); } -#endif -#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8) -void istringstream::iread (long long& v) { read_number (v); } -#endif - -void istringstream::iread (wchar_t& v) -{ - if ((v = skip_delimiters()) == wchar_t(m_Delimiters[0])) - return; - size_t cs = Utf8SequenceBytes (v) - 1; - if (remaining() >= cs || underflow(cs) >= cs) { - ungetc(); - v = *utf8in (ipos()); - skip (cs + 1); - } -} - -void istringstream::iread (bool& v) -{ - static const char tf[2][8] = { "false", "true" }; - char c = skip_delimiters(); - v = (c == 't' || c == '1'); - if (c != tf[v][0]) - return; - for (const char* tv = tf[v]; c == *tv && (remaining() || underflow()); ++tv) - istream::iread (c); - ungetc(); -} - -void istringstream::iread (string& v) -{ - v.clear(); - char prevc, quoteChar = 0, c = skip_delimiters(); - if (c == '\"' || c == '\'') - quoteChar = c; - else - v += c; - while (remaining() || underflow()) { - prevc = c; - istream::iread (c); - if (!quoteChar && is_delimiter(c)) - break; - if (prevc == '\\') { - switch (c) { - case 't': c = '\t'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 'b': c = '\b'; break; - case 'E': c = 27; break; // ESC sequence - case '\"': c = '\"'; break; - case '\'': c = '\''; break; - case '\\': c = '\\'; break; - }; - v.end()[-1] = c; - } else { - if (c == quoteChar) - break; - v += c; - } - } -} - -void istringstream::read (void* buffer, size_type sz) -{ - if (remaining() < sz && underflow(sz) < sz) -#ifdef WANT_STREAM_BOUNDS_CHECKING - verify_remaining ("read", "", sz); -#else - assert (remaining() >= size()); -#endif - istream::read (buffer, sz); -} - -void istringstream::read (memlink& buf) -{ - if (remaining() < buf.size() && underflow(buf.size()) < buf.size()) -#ifdef WANT_STREAM_BOUNDS_CHECKING - verify_remaining ("read", "", buf.size()); -#else - assert (remaining() >= buf.size()); -#endif - istream::read (buf); -} - -/// Reads one character from the stream. -int istringstream::get (void) -{ - int8_t v = 0; - if (remaining() || underflow()) - istream::iread (v); - return (v); -} - -/// Reads characters into \p s until \p delim is found (but not stored or extracted) -void istringstream::get (string& s, char delim) -{ - getline (s, delim); - if (!s.empty() && pos() > 0 && ipos()[-1] == delim) - ungetc(); -} - -/// Reads characters into \p p,n until \p delim is found (but not stored or extracted) -void istringstream::get (char* p, size_type n, char delim) -{ - assert (p && !n && "A non-empty buffer is required by this implementation"); - string s; - get (s, delim); - const size_t ntc (min (n - 1, s.size())); - memcpy (p, s.data(), ntc); - p[ntc] = 0; -} - -/// Reads characters into \p s until \p delim is extracted (but not stored) -void istringstream::getline (string& s, char delim) -{ - char oldDelim [VectorSize(m_Delimiters)]; - copy (VectorRange (m_Delimiters), oldDelim); - fill (VectorRange (m_Delimiters), '\0'); - m_Delimiters[0] = delim; - iread (s); - copy (VectorRange (oldDelim), m_Delimiters); -} - -/// Reads characters into \p p,n until \p delim is extracted (but not stored) -void istringstream::getline (char* p, size_type n, char delim) -{ - assert (p && !n && "A non-empty buffer is required by this implementation"); - string s; - getline (s, delim); - const size_t ntc (min (n - 1, s.size())); - memcpy (p, s.data(), ntc); - p[ntc] = 0; -} - -/// Extract until \p delim or \p n chars have been read. -void istringstream::ignore (size_type n, char delim) -{ - while (n-- && (remaining() || underflow()) && get() != delim); -} - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/sistream.h b/media/libdrm/mobile2/src/util/ustl-1.0/sistream.h deleted file mode 100644 index 924f43b49f74d569bb9ae04f2380214d806e0dbe..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/sistream.h +++ /dev/null @@ -1,133 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// sistream.h -// - -#ifndef SISTREAM_H_0CCA102229A49F5D65EE852E62B27CE2 -#define SISTREAM_H_0CCA102229A49F5D65EE852E62B27CE2 - -#include "mistream.h" -#include "uassert.h" -#include "ustring.h" - -namespace ustl { - -/// \class istringstream sistream.h ustl.h -/// \ingroup TextStreams -/// -/// \brief A stream that reads textual data from a memory block. -/// -class istringstream : public istream { -public: - static const size_type c_MaxDelimiters = 16; ///< Maximum number of word delimiters. -public: - istringstream (void); - istringstream (const void* p, size_type n); - explicit istringstream (const cmemlink& source); - void iread (int8_t& v); - void iread (int32_t& v); - void iread (double& v); - void iread (bool& v); - void iread (wchar_t& v); - void iread (string& v); -#ifdef HAVE_INT64_T - void iread (int64_t& v); -#endif -#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8) - void iread (long long& v); -#endif - inline string str (void) const { string s; s.link (*this); return (s); } - inline void str (const string& s) { link (s); } - int get (void); - inline void get (char& c) { c = get(); } - void get (char* p, size_type n, char delim = '\n'); - void get (string& s, char delim = '\n'); - void getline (char* p, size_type n, char delim = '\n'); - void getline (string& s, char delim = '\n'); - void ignore (size_type n, char delim = '\0'); - inline char peek (void) { int8_t v; iread (v); ungetc(); return (v); } - inline void putback (char) { ungetc(); } - inline void unget (void) { ungetc(); } - void set_delimiters (const char* delimiters); - inline void set_base (short base); - inline void set_decimal_separator (char) { } - inline void set_thousand_separator (char) { } - void read (void* buffer, size_type size); - void read (memlink& buf); - inline void read_strz (string& str); - inline void sync (void) { skip (remaining()); } -protected: - char skip_delimiters (void); -private: - inline bool is_delimiter (char c) const; - template void read_number (T& v); -private: - char m_Delimiters [c_MaxDelimiters]; - uint8_t m_Base; -}; - -/// Sets the numeric base used to read numbers. -inline void istringstream::set_base (short base) -{ - m_Base = base; -} - -/// Reads a null-terminated character stream. This is not allowed in this class. -inline void istringstream::read_strz (string&) -{ - assert (!"Reading nul characters is not allowed from text streams"); -} - -/// Reads one type as another. -template -inline void _cast_read (istringstream& is, RealT& v) -{ - CastT cv; - is.iread (cv); - v = RealT (cv); -} - -inline istringstream& operator>> (istringstream& is, int8_t& v) { is.iread (v); return (is); } -inline istringstream& operator>> (istringstream& is, int32_t& v){ is.iread (v); return (is); } -inline istringstream& operator>> (istringstream& is, double& v) { is.iread (v); return (is); } -inline istringstream& operator>> (istringstream& is, bool& v) { is.iread (v); return (is); } -inline istringstream& operator>> (istringstream& is, wchar_t& v){ is.iread (v); return (is); } -inline istringstream& operator>> (istringstream& is, string& v) { is.iread (v); return (is); } -#if HAVE_INT64_T -inline istringstream& operator>> (istringstream& is, int64_t& v){ is.iread (v); return (is); } -#endif -#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8) -inline istringstream& operator>> (istringstream& is, long long& v) { is.iread (v); return (is); } -#endif - -#define ISTRSTREAM_CAST_OPERATOR(RealT, CastT) \ -inline istringstream& operator>> (istringstream& is, RealT& v) \ -{ _cast_read(is, v); return (is); } - -ISTRSTREAM_CAST_OPERATOR (uint8_t, int8_t) -ISTRSTREAM_CAST_OPERATOR (int16_t, int32_t) -ISTRSTREAM_CAST_OPERATOR (uint16_t, int32_t) -ISTRSTREAM_CAST_OPERATOR (uint32_t, int32_t) -ISTRSTREAM_CAST_OPERATOR (float, double) -#if HAVE_THREE_CHAR_TYPES -ISTRSTREAM_CAST_OPERATOR (char, int8_t) -#endif -#if HAVE_INT64_T -ISTRSTREAM_CAST_OPERATOR (uint64_t, int64_t) -#endif -#if SIZE_OF_LONG == SIZE_OF_INT -ISTRSTREAM_CAST_OPERATOR (long, int) -ISTRSTREAM_CAST_OPERATOR (unsigned long,int) -#endif -#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8) -ISTRSTREAM_CAST_OPERATOR (unsigned long long, long long) -#endif -#undef ISTRSTREAM_CAST_OPERATOR - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/sostream.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/sostream.cpp deleted file mode 100644 index 96f09764a8edb109fda6ccff95349efc19847a3e..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/sostream.cpp +++ /dev/null @@ -1,193 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// sostream.h -// - -#include "mistream.h" // for istream_iterator, referenced in utf8.h -#include "sostream.h" -#include "uassert.h" -#include "ulimits.h" -#include "ustring.h" -#include - -namespace ustl { - -/// Creates an output string stream linked to the given memory area. -ostringstream::ostringstream (void* p, size_t n) -: ostream (), - m_Buffer (), - m_Flags (0), - m_Width (0), - m_Base (10), - m_Precision (2) -{ - link (p, n); -} - -/// Creates an output string stream, initializing the buffer with v. -ostringstream::ostringstream (const string& v) -: ostream (), - m_Buffer (v), - m_Flags (0), - m_Width (0), - m_Base (10), - m_Precision (2) -{ - ostream::link (m_Buffer); -} - -/// Copies \p s to the internal buffer. -void ostringstream::str (const string& s) -{ - m_Buffer = s; - ostream::link (m_Buffer); - SetPos (m_Buffer.size()); -} - -/// Writes a single character into the stream. -void ostringstream::iwrite (uint8_t v) -{ - if (remaining() >= 1 || overflow() >= 1) - ostream::iwrite (v); -} - -/// Writes \p buf of size \p bufSize through the internal buffer. -void ostringstream::write_buffer (const char* buf, size_type bufSize) -{ - size_type btw = 0, written = 0; - while ((written += btw) < bufSize && (remaining() || overflow(bufSize - written))) - write (buf + written, btw = min (remaining(), bufSize - written)); -} - -/// Simple decimal encoding of \p n into \p fmt. -inline char* ostringstream::encode_dec (char* fmt, uint32_t n) const -{ - do { - *fmt++ = '0' + n % 10; - } while (n /= 10); - return (fmt); -} - -/// Generates a sprintf format string for the given type. -void ostringstream::fmtstring (char* fmt, const char* typestr, bool bInteger) const -{ - *fmt++ = '%'; - if (m_Width) - fmt = encode_dec (fmt, m_Width); - if (m_Flags & left) - *fmt++ = '-'; - if (!bInteger) { - *fmt++ = '.'; - fmt = encode_dec (fmt, m_Precision); - } - while (*typestr) - *fmt++ = *typestr++; - if (bInteger) { - if (m_Base == 16) - fmt[-1] = 'X'; - else if (m_Base == 8) - fmt[-1] = 'o'; - } else { - if (m_Flags & scientific) - fmt[-1] = 'E'; - } - *fmt = 0; -} - -/// Writes \p v into the stream as utf8 -void ostringstream::iwrite (wchar_t v) -{ - char buffer [8]; - *utf8out(buffer) = v; - write_buffer (buffer, Utf8Bytes(v)); -} - -/// Writes value \p v into the stream as text. -void ostringstream::iwrite (bool v) -{ - static const char tf[2][8] = { "false", "true" }; - write_buffer (tf[v], 5 - v); -} - -/// Equivalent to a vsprintf on the string. -int ostringstream::vformat (const char* fmt, va_list args) -{ -#if HAVE_VA_COPY - va_list args2; -#else - #define args2 args - #undef __va_copy - #define __va_copy(x,y) -#endif - size_t rv, space; - do { - space = remaining(); - __va_copy (args2, args); - rv = vsnprintf (ipos(), space, fmt, args2); - if (ssize_t(rv) < 0) - rv = space; - } while (rv >= space && rv < overflow(rv + 1)); - SetPos (pos() + min (rv, space)); - return (rv); -} - -/// Equivalent to a sprintf on the string. -int ostringstream::format (const char* fmt, ...) -{ - va_list args; - va_start (args, fmt); - const int rv = vformat (fmt, args); - va_end (args); - return (rv); -} - -/// Links to string \p l as resizable. -void ostringstream::link (void* p, size_t n) -{ - assert ((p || !n) && "The output string buffer must not be read-only"); - ostream::link (p, n); - m_Buffer.link (p, n); -} - -/// Writes the contents of \p buffer of \p size into the stream. -void ostringstream::write (const void* buffer, size_type sz) -{ - if (remaining() < sz && overflow(sz) < sz) - return; - ostream::write (buffer, sz); -} - -/// Writes the contents of \p buf into the stream. -void ostringstream::write (const cmemlink& buf) -{ - if (remaining() < buf.size() && overflow(buf.size()) < buf.size()) - return; - ostream::write (buf); -} - -/// Flushes the internal buffer by truncating it at the current position. -void ostringstream::flush (void) -{ - m_Buffer.resize (pos()); -} - -/// Attempts to create more output space. Returns remaining(). -ostringstream::size_type ostringstream::overflow (size_type n) -{ - if (n > remaining()) { - const uoff_t oldPos (pos()); - m_Buffer.reserve (oldPos + n, false); - m_Buffer.resize (oldPos + n); - ostream::link (m_Buffer); - SetPos (oldPos); - } - verify_remaining ("write", "text", n); - return (remaining()); -} - -} // namespace ustl - - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/sostream.h b/media/libdrm/mobile2/src/util/ustl-1.0/sostream.h deleted file mode 100644 index 11dc328d7bf6ab9231e28ce43955d482107ac2cf..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/sostream.h +++ /dev/null @@ -1,158 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// sostream.h -// - -#ifndef SOSTREAM_H_5323DC8C26E181D43278F2F53FDCF19F -#define SOSTREAM_H_5323DC8C26E181D43278F2F53FDCF19F - -#include "uassert.h" -#include "ustring.h" -#include "mostream.h" - -namespace ustl { - -class string; - -/// \class ostringstream sostream.h ustl.h -/// \ingroup TextStreams -/// -/// \brief This stream writes textual data into a memory block. -/// -class ostringstream : public ostream { -public: - ostringstream (const string& v = string::empty_string); - ostringstream (void* p, size_t n); - void iwrite (uint8_t v); - void iwrite (wchar_t v); - inline void iwrite (int v) { iformat (v); } - inline void iwrite (unsigned int v) { iformat (v); } - inline void iwrite (long int v) { iformat (v); } - inline void iwrite (unsigned long int v) { iformat (v); } - inline void iwrite (float v) { iformat (v); } - inline void iwrite (double v) { iformat (v); } - void iwrite (bool v); - inline void iwrite (const char* s) { write_buffer (s, strlen(s)); } - inline void iwrite (const string& v) { write_buffer (v.begin(), v.size()); } - inline void iwrite (fmtflags f); -#if HAVE_LONG_LONG - inline void iwrite (long long v) { iformat (v); } - inline void iwrite (unsigned long long v) { iformat (v); } -#endif - inline size_type max_size (void) const { return (m_Buffer.max_size()); } - inline void put (char c) { iwrite (uint8_t(c)); } - int vformat (const char* fmt, va_list args); - int format (const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))); - inline void set_base (uint16_t b) { m_Base = b; } - inline void set_width (uint16_t w) { m_Width = w; } - inline void set_decimal_separator (char) { } - inline void set_thousand_separator (char) { } - inline void set_precision (uint16_t v) { m_Precision = v; } - void link (void* p, size_type n); - inline void link (memlink& l) { link (l.data(), l.writable_size()); } - inline const string& str (void) { flush(); return (m_Buffer); } - void str (const string& s); - void write (const void* buffer, size_type size); - void write (const cmemlink& buf); - inline void write_strz (const char*) { assert (!"Writing nul characters into a text stream is not allowed"); } - void flush (void); - virtual size_type overflow (size_type n = 1); -protected: - void write_buffer (const char* buf, size_type bufSize); - inline void reserve (size_type n) { m_Buffer.reserve (n, false); } - inline size_type capacity (void) const { return (m_Buffer.capacity()); } -private: - inline char* encode_dec (char* fmt, uint32_t n) const; - void fmtstring (char* fmt, const char* typestr, bool bInteger) const; - template - void iformat (T v); -private: - string m_Buffer; ///< The output buffer. - uint32_t m_Flags; ///< See ios_base::fmtflags. - uint16_t m_Width; ///< Field width. - uint8_t m_Base; ///< Numeric base for writing numbers. - uint8_t m_Precision; ///< Number of digits after the decimal separator. -}; - -//---------------------------------------------------------------------- - -template -inline const char* printf_typestring (const T&) { return (""); } -#define PRINTF_TYPESTRING_SPEC(type,str) \ -template <> inline const char* printf_typestring (const type&) { return (str); } -PRINTF_TYPESTRING_SPEC (int, "d") -PRINTF_TYPESTRING_SPEC (unsigned int, "u") -PRINTF_TYPESTRING_SPEC (long, "ld") -PRINTF_TYPESTRING_SPEC (unsigned long, "lu") -PRINTF_TYPESTRING_SPEC (float, "f") -PRINTF_TYPESTRING_SPEC (double, "lf") -#if HAVE_LONG_LONG -PRINTF_TYPESTRING_SPEC (long long, "lld") -PRINTF_TYPESTRING_SPEC (unsigned long long, "llu") -#endif -#undef PRINTF_TYPESTRING_SPEC - -template -void ostringstream::iformat (T v) -{ - char fmt [16]; - fmtstring (fmt, printf_typestring(v), numeric_limits::is_integer); - format (fmt, v); -} - -/// Sets the flag \p f in the stream. -inline void ostringstream::iwrite (fmtflags f) -{ - switch (f) { - case oct: set_base (8); break; - case dec: set_base (10); break; - case hex: set_base (16); break; - case left: m_Flags |= left; m_Flags &= ~right; break; - case right: m_Flags |= right; m_Flags &= ~left; break; - default: m_Flags |= f; break; - } -} - -//---------------------------------------------------------------------- - -#define OSTRSTREAM_OPERATOR(RealT, CastT) \ -inline ostringstream& operator<< (ostringstream& os, RealT v) \ -{ os.iwrite ((CastT) v); return (os); } - -template -OSTRSTREAM_OPERATOR (T*, unsigned long int) -OSTRSTREAM_OPERATOR (const void*, unsigned long int) -OSTRSTREAM_OPERATOR (void*, unsigned long int) -OSTRSTREAM_OPERATOR (const char*, const char*) -OSTRSTREAM_OPERATOR (char*, const char*) -OSTRSTREAM_OPERATOR (uint8_t*, const char*) -OSTRSTREAM_OPERATOR (const uint8_t*, const char*) -OSTRSTREAM_OPERATOR (const string&, const string&) -OSTRSTREAM_OPERATOR (ios_base::fmtflags,ios_base::fmtflags) -OSTRSTREAM_OPERATOR (int8_t, uint8_t) -OSTRSTREAM_OPERATOR (uint8_t, uint8_t) -OSTRSTREAM_OPERATOR (short int, int) -OSTRSTREAM_OPERATOR (unsigned short, unsigned int) -OSTRSTREAM_OPERATOR (int, int) -OSTRSTREAM_OPERATOR (unsigned int, unsigned int) -OSTRSTREAM_OPERATOR (long, long) -OSTRSTREAM_OPERATOR (unsigned long, unsigned long) -OSTRSTREAM_OPERATOR (float, float) -OSTRSTREAM_OPERATOR (double, double) -OSTRSTREAM_OPERATOR (bool, bool) -OSTRSTREAM_OPERATOR (wchar_t, wchar_t) -#if HAVE_THREE_CHAR_TYPES -OSTRSTREAM_OPERATOR (char, uint8_t) -#endif -#if HAVE_LONG_LONG -OSTRSTREAM_OPERATOR (long long, long long) -OSTRSTREAM_OPERATOR (unsigned long long, unsigned long long) -#endif - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/strmsize.h b/media/libdrm/mobile2/src/util/ustl-1.0/strmsize.h deleted file mode 100644 index 5888e15fe7086087a66321ff373dfbb0213e3c75..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/strmsize.h +++ /dev/null @@ -1,135 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -/// \file strmsize.h -/// \brief This file contains stream_size_of functions for basic types and *STREAMABLE macros. -/// stream_size_of functions return the size of the object's data that is written or -/// read from a stream. -// - -#ifndef STRMSIZE_H_052FF16B2D8A608761BF10333D065073 -#define STRMSIZE_H_052FF16B2D8A608761BF10333D065073 - -#include "uassert.h" - -namespace ustl { - -/// Returns the size of the given object. Overloads for standard types are available. -template -inline size_t stream_size_of (T*) { return (sizeof(T*)); } -#ifndef DOXYGEN_SHOULD_IGNORE_THIS -inline size_t stream_size_of (int8_t) { return (sizeof(int8_t)); } -inline size_t stream_size_of (uint8_t) { return (sizeof(uint8_t)); } -inline size_t stream_size_of (int16_t) { return (sizeof(int16_t)); } -inline size_t stream_size_of (uint16_t) { return (sizeof(uint16_t)); } -inline size_t stream_size_of (int32_t) { return (sizeof(int32_t)); } -inline size_t stream_size_of (uint32_t) { return (sizeof(uint32_t)); } -inline size_t stream_size_of (float) { return (sizeof(float)); } -inline size_t stream_size_of (double) { return (sizeof(double)); } -inline size_t stream_size_of (bool) { return (sizeof(uint8_t)); } -inline size_t stream_size_of (wchar_t) { return (sizeof(wchar_t)); } -#if HAVE_THREE_CHAR_TYPES -inline size_t stream_size_of (char) { return (sizeof(char)); } -#endif -#if HAVE_INT64_T -inline size_t stream_size_of (int64_t) { return (sizeof(int64_t)); } -inline size_t stream_size_of (uint64_t) { return (sizeof(uint64_t)); } -#endif -#if SIZE_OF_LONG == SIZE_OF_INT -inline size_t stream_size_of (long v) { return (sizeof (v)); } -inline size_t stream_size_of (unsigned long v) { return (sizeof (v)); } -#endif -#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8) -inline size_t stream_size_of (long long v) { return (sizeof (v)); } -inline size_t stream_size_of (unsigned long long v) { return (sizeof (v)); } -#endif -#endif // DOXYGEN_SHOULD_IGNORE_THIS - -} // namespace ustl - -/// Declares that T is not written to istream/ostream. -#define NOT_STREAMABLE(T) \ - namespace ustl { \ - inline istream& operator>> (istream& is, T&) { return (is); } \ - inline ostream& operator<< (ostream& os, const T&) { return (os); } \ - inline size_t stream_size_of (const T&) { return (0); } \ - } - -// -// Extra overloads in this macro are needed because it is the one used for -// marshalling pointers. Passing a pointer to stream_size_of creates a -// conversion ambiguity between converting to const pointer& and converting -// to bool; the compiler always chooses the bool conversion (because it -// requires 1 conversion instead of 2 for the other choice). There is little -// point in adding the overloads to other macros, since they are never used -// for pointers. -// -/// Declares that T is to be written as is into binary streams. -#define INTEGRAL_STREAMABLE(T) \ - namespace ustl { \ - inline istream& operator>> (istream& is, T& v) { is.iread(v); return (is); } \ - inline ostream& operator<< (ostream& os, const T& v) { os.iwrite(v); return (os); } \ - inline ostream& operator<< (ostream& os, T& v) { os.iwrite(v); return (os); } \ - inline size_t stream_size_of (const T& v) { return (sizeof(v)); } \ - inline size_t stream_size_of (T& v) { return (sizeof(v)); } \ - } - -#ifdef NDEBUG - #define STD_STREAMABLE_SZCHK_BEGIN - #define STD_STREAMABLE_SZCHK_END -#else - #define STD_STREAMABLE_SZCHK_BEGIN \ - assert (os.aligned (alignof (v))); \ - const uoff_t vStart (os.pos()) - #define STD_STREAMABLE_SZCHK_END \ - if (os.pos() - vStart != v.stream_size()) \ - throw stream_bounds_exception ("write", typeid(v).name(), vStart, os.pos() - vStart, v.stream_size()) -#endif - -/// Declares that T contains read, write, and stream_size methods. -#define STD_STREAMABLE(T) \ - namespace ustl { \ - inline istream& operator>> (istream& is, T& v) { assert (is.aligned (alignof (v))); v.read (is); return (is); } \ - inline ostream& operator<< (ostream& os, const T& v) { STD_STREAMABLE_SZCHK_BEGIN; v.write (os); STD_STREAMABLE_SZCHK_END; return (os); } \ - inline size_t stream_size_of (const T& v) { return (v.stream_size()); } \ - } - -/// Declares that T is to be cast into TSUB for streaming. -#define CAST_STREAMABLE(T,TSUB) \ - namespace ustl { \ - inline istream& operator>> (istream& is, T& v) { TSUB sv; is >> sv; v = (T)(sv); return (is); } \ - inline ostream& operator<< (ostream& os, const T& v) { os << TSUB(v); return (os); } \ - inline size_t stream_size_of (const T& v) { return (sizeof(TSUB(v))); } \ - } - -/// Placed into a class it declares the methods required by STD_STREAMABLE. Syntactic sugar. -#define DECLARE_STD_STREAMABLE \ - public: \ - void read (istream& is); \ - void write (ostream& os) const; \ - size_t stream_size (void) const - -/// Declares \p T to be writable to text streams. Reading is not implemented because you should not do it. -#define TEXT_STREAMABLE(T) \ - namespace ustl { \ - inline ostringstream& operator<< (ostringstream& os, const T& v) \ - { v.text_write (os); return (os); } \ - } - -/// Specifies that \p T is printed by using it as an index into \p Names string array. -#define LOOKUP_TEXT_STREAMABLE(T,Names,nNames) \ - namespace ustl { \ - inline ostringstream& operator<< (ostringstream& os, const T& v) \ - { \ - if (uoff_t(v) < (nNames)) \ - os << Names[v]; \ - else \ - os << uoff_t(v); \ - return (os); \ - } \ - } - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ualgo.h b/media/libdrm/mobile2/src/util/ustl-1.0/ualgo.h deleted file mode 100644 index 47b66d0e431000c44487a688a23613766d59c206..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ualgo.h +++ /dev/null @@ -1,677 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ualgo.h -// -// Implementation of STL algorithms. -// -// The function prototypes are copied -// exactly from the SGI version of STL documentation along with comments about -// their use. The code is NOT the same, though the functionality usually is. -// - -#ifndef UALGO_H_711AB4214D417A51166694D47A662D6E -#define UALGO_H_711AB4214D417A51166694D47A662D6E - -#include "upair.h" -#include "ualgobase.h" -#include "ufunction.h" -#include "upredalgo.h" -#include "umemory.h" -#include // for rand() - -namespace ustl { - -/// Swaps corresponding elements of [first, last) and [result,) -/// \ingroup SwapAlgorithms -/// -template -inline ForwardIterator2 swap_ranges (ForwardIterator1 first, ForwardIterator2 last, ForwardIterator2 result) -{ - for (; first != last; ++first, ++result) - iter_swap (first, result); - return (result); -} - -/// Returns the first iterator i in the range [first, last) such that -/// *i == value. Returns last if no such iterator exists. -/// \ingroup SearchingAlgorithms -/// -template -inline InputIterator find (InputIterator first, InputIterator last, const EqualityComparable& value) -{ - while (first != last && !(*first == value)) - ++ first; - return (first); -} - -/// Returns the first iterator such that *i == *(i + 1) -/// \ingroup SearchingAlgorithms -/// -template -ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last) -{ - if (first != last) - for (ForwardIterator prev = first; ++first != last; ++ prev) - if (*prev == *first) - return (prev); - return (last); -} - -/// Returns the pointer to the first pair of unequal elements. -/// \ingroup SearchingAlgorithms -/// -template -pair -mismatch (InputIterator first1, InputIterator last1, InputIterator first2) -{ - while (first1 != last1 && *first1 == *first2) - ++ first1, ++ first2; - return (make_pair (first1, first2)); -} - -/// \brief Returns true if two ranges are equal. -/// This is an extension, present in uSTL and SGI STL. -/// \ingroup SearchingAlgorithms -/// -template -inline bool equal (InputIterator first1, InputIterator last1, InputIterator first2) -{ - return (mismatch (first1, last1, first2).first == last1); -} - -/// Count finds the number of elements in [first, last) that are equal -/// to value. More precisely, the first version of count returns the -/// number of iterators i in [first, last) such that *i == value. -/// \ingroup SearchingAlgorithms -/// -template -inline size_t count (InputIterator first, InputIterator last, const EqualityComparable& value) -{ - size_t total = 0; - for (; first != last; ++first) - if (*first == value) - ++ total; - return (total); -} - -/// -/// The first version of transform performs the operation op(*i) for each -/// iterator i in the range [first, last), and assigns the result of that -/// operation to *o, where o is the corresponding output iterator. That is, -/// for each n such that 0 <= n < last - first, it performs the assignment -/// *(result + n) = op(*(first + n)). -/// The return value is result + (last - first). -/// \ingroup MutatingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline OutputIterator transform (InputIterator first, InputIterator last, OutputIterator result, UnaryFunction op) -{ - for (; first != last; ++result, ++first) - *result = op (*first); - return (result); -} - -/// -/// The second version of transform is very similar, except that it uses a -/// Binary Function instead of a Unary Function: it performs the operation -/// op(*i1, *i2) for each iterator i1 in the range [first1, last1) and assigns -/// the result to *o, where i2 is the corresponding iterator in the second -/// input range and where o is the corresponding output iterator. That is, -/// for each n such that 0 <= n < last1 - first1, it performs the assignment -/// *(result + n) = op(*(first1 + n), *(first2 + n). -/// The return value is result + (last1 - first1). -/// \ingroup MutatingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline OutputIterator transform (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryFunction op) -{ - for (; first1 != last1; ++result, ++first1, ++first2) - *result = op (*first1, *first2); - return (result); -} - -/// Replace replaces every element in the range [first, last) equal to -/// old_value with new_value. That is: for every iterator i, -/// if *i == old_value then it performs the assignment *i = new_value. -/// \ingroup MutatingAlgorithms -/// -template -inline void replace (ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value) -{ - for (; first != last; ++first) - if (*first == old_value) - *first = new_value; -} - -/// Replace_copy copies elements from the range [first, last) to the range -/// [result, result + (last-first)), except that any element equal to old_value -/// is not copied; new_value is copied instead. More precisely, for every -/// integer n such that 0 <= n < last-first, replace_copy performs the -/// assignment *(result+n) = new_value if *(first+n) == old_value, and -/// *(result+n) = *(first+n) otherwise. -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator replace_copy (InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value) -{ - for (; first != last; ++result, ++first) - *result = (*first == old_value) ? new_value : *first; -} - -/// Generate assigns the result of invoking gen, a function object that -/// takes no arguments, to each element in the range [first, last). -/// \ingroup GeneratorAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline void generate (ForwardIterator first, ForwardIterator last, Generator gen) -{ - for (; first != last; ++first) - *first = gen(); -} - -/// Generate_n assigns the result of invoking gen, a function object that -/// takes no arguments, to each element in the range [first, first+n). -/// The return value is first + n. -/// \ingroup GeneratorAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline OutputIterator generate_n (OutputIterator first, size_t n, Generator gen) -{ - for (uoff_t i = 0; i != n; ++i, ++first) - *first = gen(); - return (first); -} - -/// \brief Reverse reverses a range. -/// That is: for every i such that 0 <= i <= (last - first) / 2), -/// it exchanges *(first + i) and *(last - (i + 1)). -/// \ingroup MutatingAlgorithms -/// -template -inline void reverse (BidirectionalIterator first, BidirectionalIterator last) -{ - for (; distance (first, --last) > 0; ++first) - iter_swap (first, last); -} - -/// \brief Reverses [first,last) and writes it to \p output. -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator reverse_copy (BidirectionalIterator first, BidirectionalIterator last, OutputIterator result) -{ - for (; first != last; ++result) - *result = *--last; - return (result); -} - -/// \brief Exchanges ranges [first, middle) and [middle, last) -/// \ingroup MutatingAlgorithms -/// -template -ForwardIterator rotate (ForwardIterator first, ForwardIterator middle, ForwardIterator last) -{ - if (first == middle || middle == last) - return (first); - reverse (first, middle); - reverse (middle, last); - for (;first != middle && middle != last; ++first) - iter_swap (first, --last); - reverse (first, (first == middle ? last : middle)); - return (first); -} - -/// Specialization for pointers, which can be treated identically. -template -inline T* rotate (T* first, T* middle, T* last) -{ - rotate_fast (first, middle, last); - return (first); -} - - -/// \brief Exchanges ranges [first, middle) and [middle, last) into \p result. -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator rotate_copy (ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result) -{ - return (copy (first, middle, copy (middle, last, result))); -} - -/// \brief Combines two sorted ranges. -/// \ingroup SortingAlgorithms -/// -template -OutputIterator merge (InputIterator1 first1, InputIterator1 last1, - InputIterator2 first2, InputIterator2 last2, OutputIterator result) -{ - for (; first1 != last1 && first2 != last2; ++result) { - if (*first1 < *first2) - *result = *first1++; - else - *result = *first2++; - } - if (first1 < last1) - return (copy (first1, last1, result)); - else - return (copy (first2, last2, result)); -} - -/// Combines two sorted ranges from the same container. -/// \ingroup SortingAlgorithms -/// -template -void inplace_merge (InputIterator first, InputIterator middle, InputIterator last) -{ - for (; middle != last; ++first) { - while (*first < *middle) - ++ first; - reverse (first, middle); - reverse (first, ++middle); - } -} - -/// Remove_copy copies elements that are not equal to value from the range -/// [first, last) to a range beginning at result. The return value is the -/// end of the resulting range. This operation is stable, meaning that the -/// relative order of the elements that are copied is the same as in the -/// range [first, last). -/// \ingroup MutatingAlgorithms -/// -template -OutputIterator remove_copy (InputIterator first, InputIterator last, OutputIterator result, const T& value) -{ - for (; first != last; ++first) { - if (!(*first == value)) { - *result = *first; - ++ result; - } - } - return (result); -} - -/// Remove_copy copies elements pointed to by iterators in [rfirst, rlast) -/// from the range [first, last) to a range beginning at result. The return -/// value is the end of the resulting range. This operation is stable, meaning -/// that the relative order of the elements that are copied is the same as in the -/// range [first, last). Range [rfirst, rlast) is assumed to be sorted. -/// This algorithm is a uSTL extension. -/// \ingroup MutatingAlgorithms -/// -template -OutputIterator remove_copy (InputIterator first, InputIterator last, OutputIterator result, RInputIterator rfirst, RInputIterator rlast) -{ - for (; first != last; ++first) { - while (rfirst != rlast && *rfirst < first) - ++ rfirst; - if (rfirst == rlast || first != *rfirst) { - *result = *first; - ++ result; - } - } - return (result); -} - -/// Remove removes from the range [first, last) all elements that are equal to -/// value. That is, remove returns an iterator new_last such that the range -/// [first, new_last) contains no elements equal to value. [1] The iterators -/// in the range [new_last, last) are all still dereferenceable, but the -/// elements that they point to are unspecified. Remove is stable, meaning -/// that the relative order of elements that are not equal to value is -/// unchanged. -/// \ingroup MutatingAlgorithms -/// -template -inline ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& value) -{ - return (remove_copy (first, last, first, value)); -} - -/// Unique_copy copies elements from the range [first, last) to a range -/// beginning with result, except that in a consecutive group of duplicate -/// elements only the first one is copied. The return value is the end of -/// the range to which the elements are copied. This behavior is similar -/// to the Unix filter uniq. -/// \ingroup MutatingAlgorithms -/// -template -OutputIterator unique_copy (InputIterator first, InputIterator last, OutputIterator result) -{ - if (first != last) { - *result = *first; - while (++first != last) - if (!(*first == *result)) - *++result = *first; - ++ result; - } - return (result); -} - -/// Every time a consecutive group of duplicate elements appears in the range -/// [first, last), the algorithm unique removes all but the first element. -/// That is, unique returns an iterator new_last such that the range [first, -/// new_last) contains no two consecutive elements that are duplicates. -/// The iterators in the range [new_last, last) are all still dereferenceable, -/// but the elements that they point to are unspecified. Unique is stable, -/// meaning that the relative order of elements that are not removed is -/// unchanged. -/// \ingroup MutatingAlgorithms -/// -template -inline ForwardIterator unique (ForwardIterator first, ForwardIterator last) -{ - return (unique_copy (first, last, first)); -} - -/// Returns the furthermost iterator i in [first, last) such that, -/// for every iterator j in [first, i), *j < value -/// Assumes the range is sorted. -/// \ingroup SearchingAlgorithms -/// -template -ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const LessThanComparable& value) -{ - ForwardIterator mid; - while (first != last) { - mid = advance (first, distance (first,last) / 2); - if (*mid < value) - first = mid + 1; - else - last = mid; - } - return (first); -} - -/// Performs a binary search inside the sorted range. -/// \ingroup SearchingAlgorithms -/// -template -inline ForwardIterator binary_search (ForwardIterator first, ForwardIterator last, const LessThanComparable& value) -{ - ForwardIterator found = lower_bound (first, last, value); - return ((found == last || value < *found) ? last : found); -} - -/// Returns the furthermost iterator i in [first,last) such that for -/// every iterator j in [first,i), value < *j is false. -/// \ingroup SearchingAlgorithms -/// -template -ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const LessThanComparable& value) -{ - ForwardIterator mid; - while (first != last) { - mid = advance (first, distance (first,last) / 2); - if (value < *mid) - last = mid; - else - first = mid + 1; - } - return (last); -} - -/// Returns pair -/// \ingroup SearchingAlgorithms -/// -template -inline pair equal_range (ForwardIterator first, ForwardIterator last, const LessThanComparable& value) -{ - pair rv; - rv.second = rv.first = lower_bound (first, last, value); - while (rv.second != last && !(value < *(rv.second))) - ++ rv.second; - return (rv); -} - -/// Randomly permute the elements of the container. -/// \ingroup GeneratorAlgorithms -/// -template -void random_shuffle (RandomAccessIterator first, RandomAccessIterator last) -{ - for (; first != last; ++ first) - iter_swap (first, first + (rand() % distance (first, last))); -} - -/// \brief Generic compare function adaptor to pass to qsort -/// \ingroup FunctorObjects -template -int qsort_adapter (const void* p1, const void* p2) -{ - ConstPointer i1 = reinterpret_cast(p1); - ConstPointer i2 = reinterpret_cast(p2); - Compare comp; - return (comp (*i1, *i2) ? -1 : (comp (*i2, *i1) ? 1 : 0)); -} - -/// Sorts the container -/// \ingroup SortingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -void sort (RandomAccessIterator first, RandomAccessIterator last, Compare) -{ - typedef typename iterator_traits::value_type value_type; - typedef typename iterator_traits::const_pointer const_pointer; - qsort (first, distance (first, last), sizeof(value_type), - &qsort_adapter); -} - -/// Sorts the container -/// \ingroup SortingAlgorithms -/// -template -inline void sort (RandomAccessIterator first, RandomAccessIterator last) -{ - typedef typename iterator_traits::value_type value_type; - sort (first, last, less()); -} - -/// Sorts the container preserving order of equal elements. -/// \ingroup SortingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -void stable_sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp) -{ - for (RandomAccessIterator j, i = first; ++i < last;) { // Insertion sort - for (j = i; j-- > first && !comp(*j, *i);); - rotate (++j, i, i + 1); - } -} - -/// Sorts the container -/// \ingroup SortingAlgorithms -/// -template -inline void stable_sort (RandomAccessIterator first, RandomAccessIterator last) -{ - typedef typename iterator_traits::value_type value_type; - stable_sort (first, last, less()); -} - -/// \brief Searches for the first subsequence [first2,last2) in [first1,last1) -/// \ingroup SearchingAlgorithms -template -inline ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) -{ - typedef typename iterator_traits::value_type value_type; - return (search (first1, last1, first2, last2, equal_to())); -} - -/// \brief Searches for the last subsequence [first2,last2) in [first1,last1) -/// \ingroup SearchingAlgorithms -template -inline ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2) -{ - typedef typename iterator_traits::value_type value_type; - return (find_end (first1, last1, first2, last2, equal_to())); -} - -/// \brief Searches for the first occurence of \p count \p values in [first, last) -/// \ingroup SearchingAlgorithms -template -inline Iterator search_n (Iterator first, Iterator last, size_t count, const T& value) -{ - typedef typename iterator_traits::value_type value_type; - return (search_n (first, last, count, value, equal_to())); -} - -/// \brief Searches [first1,last1) for the first occurrence of an element from [first2,last2) -/// \ingroup SearchingAlgorithms -template -inline InputIterator find_first_of (InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2) -{ - typedef typename iterator_traits::value_type value_type; - return (find_first_of (first1, last1, first2, last2, equal_to())); -} - -/// \brief Returns true if [first2,last2) is a subset of [first1,last1) -/// \ingroup ConditionAlgorithms -/// \ingroup SetAlgorithms -template -inline bool includes (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) -{ - typedef typename iterator_traits::value_type value_type; - return (includes (first1, last1, first2, last2, less())); -} - -/// \brief Merges [first1,last1) with [first2,last2) -/// -/// Result will contain every element that is in either set. If duplicate -/// elements are present, max(n,m) is placed in the result. -/// -/// \ingroup SetAlgorithms -template -inline OutputIterator set_union (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) -{ - typedef typename iterator_traits::value_type value_type; - return (set_union (first1, last1, first2, last2, result, less())); -} - -/// \brief Creates a set containing elements shared by the given ranges. -/// \ingroup SetAlgorithms -template -inline OutputIterator set_intersection (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) -{ - typedef typename iterator_traits::value_type value_type; - return (set_intersection (first1, last1, first2, last2, result, less())); -} - -/// \brief Removes from [first1,last1) elements present in [first2,last2) -/// \ingroup SetAlgorithms -template -inline OutputIterator set_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) -{ - typedef typename iterator_traits::value_type value_type; - return (set_difference (first1, last1, first2, last2, result, less())); -} - -/// \brief Performs union of sets A-B and B-A. -/// \ingroup SetAlgorithms -template -inline OutputIterator set_symmetric_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result) -{ - typedef typename iterator_traits::value_type value_type; - return (set_symmetric_difference (first1, last1, first2, last2, result, less())); -} - -/// \brief Returns true if the given range is sorted. -/// \ingroup ConditionAlgorithms -template -inline bool is_sorted (ForwardIterator first, ForwardIterator last) -{ - typedef typename iterator_traits::value_type value_type; - return (is_sorted (first, last, less())); -} - -/// \brief Compares two given containers like strcmp compares strings. -/// \ingroup ConditionAlgorithms -template -inline bool lexicographical_compare (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) -{ - typedef typename iterator_traits::value_type value_type; - return (lexicographical_compare (first1, last1, first2, last2, less())); -} - -/// \brief Creates the next lexicographical permutation of [first,last). -/// Returns false if no further permutations can be created. -/// \ingroup GeneratorAlgorithms -template -inline bool next_permutation (BidirectionalIterator first, BidirectionalIterator last) -{ - typedef typename iterator_traits::value_type value_type; - return (next_permutation (first, last, less())); -} - -/// \brief Creates the previous lexicographical permutation of [first,last). -/// Returns false if no further permutations can be created. -/// \ingroup GeneratorAlgorithms -template -inline bool prev_permutation (BidirectionalIterator first, BidirectionalIterator last) -{ - typedef typename iterator_traits::value_type value_type; - return (prev_permutation (first, last, less())); -} - -/// \brief Returns iterator to the max element in [first,last) -/// \ingroup SearchingAlgorithms -template -inline ForwardIterator max_element (ForwardIterator first, ForwardIterator last) -{ - typedef typename iterator_traits::value_type value_type; - return (max_element (first, last, less())); -} - -/// \brief Returns iterator to the min element in [first,last) -/// \ingroup SearchingAlgorithms -template -inline ForwardIterator min_element (ForwardIterator first, ForwardIterator last) -{ - typedef typename iterator_traits::value_type value_type; - return (min_element (first, last, less())); -} - -/// \brief Makes [first,middle) a part of the sorted array. -/// Contents of [middle,last) is undefined. This implementation just calls stable_sort. -/// \ingroup SortingAlgorithms -template -inline void partial_sort (RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last) -{ - typedef typename iterator_traits::value_type value_type; - partial_sort (first, middle, last, less()); -} - -/// \brief Puts \p nth element into its sorted position. -/// In this implementation, the entire array is sorted. I can't think of any -/// use for it where the time gained would be useful. -/// \ingroup SortingAlgorithms -/// \ingroup SearchingAlgorithms -/// -template -inline void nth_element (RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last) -{ - partial_sort (first, nth, last); -} - -/// \brief Like partial_sort, but outputs to [result_first,result_last) -/// \ingroup SortingAlgorithms -template -inline RandomAccessIterator partial_sort_copy (InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last) -{ - typedef typename iterator_traits::value_type value_type; - return (partial_sort_copy (first, last, result_first, result_last, less())); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.cpp deleted file mode 100644 index 9764cd1021dc071c0f86a45e7f95a77e07229690..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.cpp +++ /dev/null @@ -1,293 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ualgobase.cc -// -// Copy and fill optimizations are here. -// - -#ifndef NDEBUG // Optimized code here. asserts slow it down, and are checked elsewhere. -#define NDEBUG -#endif - -#include "ualgo.h" - -#undef CPU_HAS_MMX - -namespace ustl { - -// Generic version for implementing fill_nX_fast on non-i386 architectures. -template inline void stosv (T*& p, size_t n, T v) - { while (n--) *p++ = v; } - -#if defined(__i386__) || defined(__x86_64__) - -//---------------------------------------------------------------------- -// Copy functions -//---------------------------------------------------------------------- - -#if __GNUC__ >= 3 -static inline void movsb_dir_up (void) __attribute__((always_inline)); -static inline void movsb_dir_down (void) __attribute__((always_inline)); -static inline void movsb (const void*& src, size_t nBytes, void*& dest) __attribute__((always_inline)); -static inline void movsd (const void*& src, size_t nWords, void*& dest) __attribute__((always_inline)); -#endif - -static inline void movsb_dir_up (void) { asm volatile ("cld"); } -static inline void movsb_dir_down (void) { asm volatile ("std"); } - -static inline void movsb (const void*& src, size_t nBytes, void*& dest) -{ - asm volatile ("rep;\n\tmovsb" - : "=&S"(src), "=&D"(dest), "=&c"(nBytes) - : "0"(src), "1"(dest), "2"(nBytes) - : "memory"); -} - -static inline void movsd (const void*& src, size_t nWords, void*& dest) -{ - asm volatile ("rep;\n\tmovsl" - : "=&S"(src), "=&D"(dest), "=&c"(nWords) - : "0"(src), "1"(dest), "2"(nWords) - : "memory"); -} - -template <> inline void stosv (uint8_t*& p, size_t n, uint8_t v) -{ asm volatile ("rep;\n\tstosb" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); } -template <> inline void stosv (uint16_t*& p, size_t n, uint16_t v) -{ asm volatile ("rep;\n\tstosw" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); } -template <> inline void stosv (uint32_t*& p, size_t n, uint32_t v) -{ asm volatile ("rep;\n\tstosl" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); } - -#if CPU_HAS_MMX -#define MMX_ALIGN 16U // Data must be aligned on this grain -#define MMX_BS 32U // Assembly routines copy data this many bytes at a time. - -static inline void simd_block_copy (const void* src, void* dest) __attribute__((always_inline)); -static inline void simd_block_store (uint8_t* dest) __attribute__((always_inline)); -static inline void simd_block_cleanup (void) __attribute__((always_inline)); - -static inline void simd_block_copy (const void* src, void* dest) -{ - const char* csrc ((const char*) src); - char* cdest ((char*) dest); - #if CPU_HAS_SSE - asm ( - "movaps\t%2, %%xmm0 \n\t" - "movaps\t%3, %%xmm1 \n\t" - "movntps\t%%xmm0, %0 \n\t" - "movntps\t%%xmm1, %1" - : "=m"(cdest[0]), "=m"(cdest[16]) - : "m"(csrc[0]), "m"(csrc[16]) - : "xmm0", "xmm1"); - #else - asm ( - "movq %4, %%mm0 \n\t" - "movq %5, %%mm1 \n\t" - "movq %6, %%mm2 \n\t" - "movq %7, %%mm3 \n\t" - "movq %%mm0, %0 \n\t" - "movq %%mm1, %1 \n\t" - "movq %%mm2, %2 \n\t" - "movq %%mm3, %3" - : "=m"(cdest[0]), "=m"(cdest[8]), "=m"(cdest[16]), "=m"(cdest[24]) - : "m"(csrc[0]), "m"(csrc[8]), "m"(csrc[16]), "m"(csrc[24]) - : "mm0", "mm1", "mm2", "mm3", "st", "st(1)", "st(2)", "st(3)"); - #endif -} - -static inline void simd_block_store (uint8_t* dest) -{ - #if CPU_HAS_SSE - asm volatile ( - "movntq %%mm0, %0\n\t" - "movntq %%mm0, %1\n\t" - "movntq %%mm0, %2\n\t" - "movntq %%mm0, %3" - : "=m"(dest[0]), "=m"(dest[8]), "=m"(dest[16]), "=m"(dest[24])); - #else - asm volatile ( - "movq %%mm0, %0 \n\t" - "movq %%mm0, %1 \n\t" - "movq %%mm0, %2 \n\t" - "movq %%mm0, %3" - : "=m"(dest[0]), "=m"(dest[8]), "=m"(dest[16]), "=m"(dest[24])); - #endif -} - -static inline void simd_block_cleanup (void) -{ - #if !CPU_HAS_SSE - simd::reset_mmx(); - #endif - asm volatile ("sfence"); -} - -/// The fastest optimized raw memory copy. -void copy_n_fast (const void* src, size_t nBytes, void* dest) -{ - movsb_dir_up(); - size_t nHeadBytes = Align(uintptr_t(src), MMX_ALIGN) - uintptr_t(src); - nHeadBytes = min (nHeadBytes, nBytes); - movsb (src, nHeadBytes, dest); - nBytes -= nHeadBytes; - if (!(uintptr_t(dest) % MMX_ALIGN)) { - const size_t nMiddleBlocks = nBytes / MMX_BS; - for (uoff_t i = 0; i < nMiddleBlocks; ++ i) { - prefetch (advance (src, 512), 0, 0); - simd_block_copy (src, dest); - src = advance (src, MMX_BS); - dest = advance (dest, MMX_BS); - } - simd_block_cleanup(); - nBytes %= MMX_BS; - } - movsb (src, nBytes, dest); -} -#endif // CPU_HAS_MMX - -/// The fastest optimized backwards raw memory copy. -void copy_backward_fast (const void* first, const void* last, void* result) -{ - prefetch (first, 0, 0); - prefetch (result, 1, 0); - size_t nBytes (distance (first, last)); - movsb_dir_down(); - size_t nHeadBytes = uintptr_t(last) % 4; - last = advance (last, -1); - result = advance (result, -1); - movsb (last, nHeadBytes, result); - nBytes -= nHeadBytes; - if (uintptr_t(result) % 4 == 3) { - const size_t nMiddleBlocks = nBytes / 4; - last = advance (last, -3); - result = advance (result, -3); - movsd (last, nMiddleBlocks, result); - nBytes %= 4; - } - movsb (last, nBytes, result); - movsb_dir_up(); -} -#endif // __i386__ - -//---------------------------------------------------------------------- -// Fill functions -//---------------------------------------------------------------------- - -#if CPU_HAS_MMX -template inline void build_block (T) {} -template <> inline void build_block (uint8_t v) -{ - asm volatile ( - "movd %0, %%mm0\n\tpunpcklbw %%mm0, %%mm0\n\tpshufw $0, %%mm0, %%mm0" - : : "g"(uint32_t(v)) : "mm0"); -} -template <> inline void build_block (uint16_t v) -{ - asm volatile ( - "movd %0, %%mm0\n\tpshufw $0, %%mm0, %%mm0" - : : "g"(uint32_t(v)) : "mm0"); -} -template <> inline void build_block (uint32_t v) -{ - asm volatile ( - "movd %0, %%mm0\n\tpunpckldq %%mm0, %%mm0" - : : "g"(uint32_t(v)) : "mm0"); -} - -static inline void simd_block_fill_loop (uint8_t*& dest, size_t count) -{ - prefetch (advance (dest, 512), 1, 0); - for (uoff_t i = 0; i < count; ++ i, dest += MMX_BS) - simd_block_store (dest); - simd_block_cleanup(); - simd::reset_mmx(); -} - -template -inline void fill_n_fast (T* dest, size_t count, T v) -{ - size_t nHead = Align(uintptr_t(dest), MMX_ALIGN) - uintptr_t(dest) / sizeof(T); - nHead = min (nHead, count); - stosv (dest, nHead, v); - count -= nHead; - build_block (v); - simd_block_fill_loop ((uint8_t*&) dest, count * sizeof(T) / MMX_BS); - count %= MMX_BS; - stosv (dest, count, v); -} - -void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v) - { fill_n_fast (dest, count, v); } -void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v) - { fill_n_fast (dest, count, v); } -void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v) - { fill_n_fast (dest, count, v); } -#else -void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v) { memset (dest, v, count); } -void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v) { stosv (dest, count, v); } -void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v) { stosv (dest, count, v); } -#endif // CPU_HAS_MMX - -/// Exchanges ranges [first, middle) and [middle, last) -void rotate_fast (void* first, void* middle, void* last) -{ -#ifdef HAVE_ALLOCA_H - const size_t half1 (distance (first, middle)), half2 (distance (middle, last)); - const size_t hmin (min (half1, half2)); - if (!hmin) { - return; - } - void* buf = alloca (hmin); - if (buf) { - if (half2 < half1) { - copy_n_fast (middle, half2, buf); - copy_backward_fast (first, middle, last); - copy_n_fast (buf, half2, first); - } else { - copy_n_fast (first, half1, buf); - copy_n_fast (middle, half2, first); - copy_n_fast (buf, half1, advance (first, half2)); - } - } else -#else - if (first == middle || middle == last) { - return; - } -#endif - { - char* f = (char*) first; - char* m = (char*) middle; - char* l = (char*) last; - reverse (f, m); - reverse (m, l); - while (f != m && m != l) - iter_swap (f++, --l); - reverse (f, (f == m ? l : m)); - } -} - -#if __GNUC__ < 4 -size_t popcount (uint32_t v) -{ - const uint32_t w = v - ((v >> 1) & 0x55555555); // Algorithm from AMD optimization guide - const uint32_t x = (w & 0x33333333) + ((w >> 2) & 0x33333333); - return (((x + (x >> 4) & 0x0F0F0F0F) * 0x01010101) >> 24); -} - -#if HAVE_INT64_T -/// \brief Returns the number of 1s in \p v in binary. -size_t popcount (uint64_t v) -{ - v -= (v >> 1) & UINT64_C(0x5555555555555555); // Algorithm from Wikipedia - v = (v & UINT64_C(0x3333333333333333)) + ((v >> 2) & UINT64_C(0x3333333333333333)); - v = (v + (v >> 4)) & UINT64_C(0x0F0F0F0F0F0F0F0F); - return ((v * UINT64_C(0x0101010101010101)) >> 56); -} -#endif // HAVE_INT64_T -#endif // !__GNUC__ - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.h b/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.h deleted file mode 100644 index 38c1a7272bafd81c980a0b73d23051f5ec21e651..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.h +++ /dev/null @@ -1,334 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ualgobase.h -// -// Implementation of STL algorithms. -// -// The function prototypes are copied -// exactly from the SGI version of STL documentation along with comments about -// their use. The code is NOT the same, though the functionality usually is. -// - -#ifndef UALGOBASE_H_683A0BE77546133C4CE0E3622CFAA2EB -#define UALGOBASE_H_683A0BE77546133C4CE0E3622CFAA2EB - -#include "uutility.h" -#include - -#if PLATFORM_ANDROID -#include -#undef CPU_HAS_MMX -#endif - -namespace ustl { - -/// Assigns the contents of a to b and the contents of b to a. -/// This is used as a primitive operation by many other algorithms. -/// \ingroup SwapAlgorithms -/// -template -inline void swap (Assignable& a, Assignable& b) -{ - Assignable tmp = a; - a = b; - b = tmp; -} - -/// Equivalent to swap (*a, *b) -/// \ingroup SwapAlgorithms -/// -template -inline void iter_swap (Iterator a, Iterator b) -{ - swap (*a, *b); -} - -/// Copy copies elements from the range [first, last) to the range -/// [result, result + (last - first)). That is, it performs the assignments -/// *result = *first, *(result + 1) = *(first + 1), and so on. [1] Generally, -/// for every integer n from 0 to last - first, copy performs the assignment -/// *(result + n) = *(first + n). Assignments are performed in forward order, -/// i.e. in order of increasing n. -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result) -{ - for (; first != last; ++result, ++first) - *result = *first; - return (result); -} - -/// Copy_n copies elements from the range [first, first + n) to the range -/// [result, result + n). That is, it performs the assignments -/// *result = *first, *(result + 1) = *(first + 1), and so on. Generally, -/// for every integer i from 0 up to (but not including) n, copy_n performs -/// the assignment *(result + i) = *(first + i). Assignments are performed -/// in forward order, i.e. in order of increasing n. -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator copy_n (InputIterator first, size_t count, OutputIterator result) -{ - for (; count; --count, ++result, ++first) - *result = *first; - return (result); -} - -/// \brief Copy copies elements from the range (last, first] to result. -/// \ingroup MutatingAlgorithms -/// Copies elements starting at last, decrementing both last and result. -/// -template -inline OutputIterator copy_backward (InputIterator first, InputIterator last, OutputIterator result) -{ - while (first != last) - *--result = *--last; - return (result); -} - -/// For_each applies the function object f to each element in the range -/// [first, last); f's return value, if any, is ignored. Applications are -/// performed in forward order, i.e. from first to last. For_each returns -/// the function object after it has been applied to each element. -/// \ingroup MutatingAlgorithms -/// -template -inline UnaryFunction for_each (InputIterator first, InputIterator last, UnaryFunction f) -{ - for (; first != last; ++first) - f (*first); - return (f); -} - -/// Fill assigns the value value to every element in the range [first, last). -/// That is, for every iterator i in [first, last), -/// it performs the assignment *i = value. -/// \ingroup GeneratorAlgorithms -/// -template -inline void fill (ForwardIterator first, ForwardIterator last, const T& value) -{ - for (; first != last; ++first) - *first = value; -} - -/// Fill_n assigns the value value to every element in the range -/// [first, first+count). That is, for every iterator i in [first, first+count), -/// it performs the assignment *i = value. The return value is first + count. -/// \ingroup GeneratorAlgorithms -/// -template -inline OutputIterator fill_n (OutputIterator first, size_t count, const T& value) -{ - for (; count; --count, ++first) - *first = value; - return (first); -} - -#if CPU_HAS_MMX -extern "C" void copy_n_fast (const void* src, size_t count, void* dest); -#else -inline void copy_n_fast (const void* src, size_t count, void* dest) -{ memcpy (dest, src, count); } -#endif -#if __i386__ || __x86_64__ -extern "C" void copy_backward_fast (const void* first, const void* last, void* result); -#else -inline void copy_backward_fast (const void* first, const void* last, void* result) -{ - const size_t nBytes (distance (first, last)); - memmove (advance (result, -nBytes), first, nBytes); -} -#endif -extern "C" void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v); -extern "C" void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v); -extern "C" void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v); -extern "C" void rotate_fast (void* first, void* middle, void* last); - -#if __GNUC__ >= 4 -/// \brief Computes the number of 1 bits in a number. -/// \ingroup ConditionAlgorithms -inline size_t popcount (uint32_t v) { return (__builtin_popcount (v)); } -#if HAVE_INT64_T -inline size_t popcount (uint64_t v) { return (__builtin_popcountll (v)); } -#endif -#else -size_t popcount (uint32_t v); -#if HAVE_INT64_T -size_t popcount (uint64_t v); -#endif // HAVE_INT64_T -#endif // __GNUC__ - -//---------------------------------------------------------------------- -// Optimized versions for standard types -//---------------------------------------------------------------------- - -#if WANT_UNROLLED_COPY - -template -inline T* unrolled_copy (const T* first, size_t count, T* result) -{ - copy_n_fast (first, count * sizeof(T), result); - return (advance (result, count)); -} - -template <> -inline uint8_t* copy_backward (const uint8_t* first, const uint8_t* last, uint8_t* result) -{ - copy_backward_fast (first, last, result); - return (result); -} - -template -inline T* unrolled_fill (T* result, size_t count, T value) -{ - for (; count; --count, ++result) - *result = value; - return (result); -} -template <> inline uint8_t* unrolled_fill (uint8_t* result, size_t count, uint8_t value) - { fill_n8_fast (result, count, value); return (advance (result, count)); } -template <> inline uint16_t* unrolled_fill (uint16_t* result, size_t count, uint16_t value) - { fill_n16_fast (result, count, value); return (advance (result, count)); } -template <> inline uint32_t* unrolled_fill (uint32_t* result, size_t count, uint32_t value) - { fill_n32_fast (result, count, value); return (advance (result, count)); } -template <> inline float* unrolled_fill (float* result, size_t count, float value) - { fill_n32_fast ((uint32_t*) result, count, noalias(uint32_t(),&value)); return (advance (result, count)); } - -#if CPU_HAS_MMX -#define UNROLLED_COPY_SPECIALIZATION(type) \ -template <> inline type* copy (const type* first, const type* last, type* result) \ -{ return (unrolled_copy (first, distance (first, last), result)); } \ -template <> inline type* copy_n (const type* first, size_t count, type* result) \ -{ return (unrolled_copy (first, count, result)); } -#define UNROLLED_FILL_SPECIALIZATION(type) \ -template <> inline void fill (type* first, type* last, const type& value) \ -{ unrolled_fill (first, distance (first, last), value); } \ -template <> inline type* fill_n (type* first, size_t count, const type& value) \ -{ return (unrolled_fill (first, count, value)); } -UNROLLED_COPY_SPECIALIZATION(uint8_t) -UNROLLED_FILL_SPECIALIZATION(uint8_t) -UNROLLED_COPY_SPECIALIZATION(uint16_t) -UNROLLED_FILL_SPECIALIZATION(uint16_t) -UNROLLED_COPY_SPECIALIZATION(uint32_t) -UNROLLED_FILL_SPECIALIZATION(uint32_t) -UNROLLED_COPY_SPECIALIZATION(float) -UNROLLED_FILL_SPECIALIZATION(float) -#undef UNROLLED_FILL_SPECIALIZATION -#undef UNROLLED_COPY_SPECIALIZATION -#endif // WANT_UNROLLED_COPY -#endif // CPU_HAS_MMX - -// Specializations for void* and char*, aliasing the above optimized versions. -// -// All these need duplication with const and non-const arguments, since -// otherwise the compiler will default to the unoptimized version for -// pointers not const in the caller's context, such as local variables. -// These are all inline, but they sure slow down compilation... :( -// -#define COPY_ALIAS_FUNC(ctype, type, alias_type) \ -template <> inline type* copy (ctype* first, ctype* last, type* result) \ -{ return ((type*) copy ((const alias_type*) first, (const alias_type*) last, (alias_type*) result)); } -#if WANT_UNROLLED_COPY -#if HAVE_THREE_CHAR_TYPES -COPY_ALIAS_FUNC(const char, char, uint8_t) -COPY_ALIAS_FUNC(char, char, uint8_t) -#endif -COPY_ALIAS_FUNC(const int8_t, int8_t, uint8_t) -COPY_ALIAS_FUNC(int8_t, int8_t, uint8_t) -COPY_ALIAS_FUNC(uint8_t, uint8_t, uint8_t) -COPY_ALIAS_FUNC(const int16_t, int16_t, uint16_t) -COPY_ALIAS_FUNC(int16_t, int16_t, uint16_t) -COPY_ALIAS_FUNC(uint16_t, uint16_t, uint16_t) -#if CPU_HAS_MMX || (SIZE_OF_LONG > 4) -COPY_ALIAS_FUNC(const int32_t, int32_t, uint32_t) -COPY_ALIAS_FUNC(int32_t, int32_t, uint32_t) -COPY_ALIAS_FUNC(uint32_t, uint32_t, uint32_t) -#endif -#endif -COPY_ALIAS_FUNC(const void, void, uint8_t) -COPY_ALIAS_FUNC(void, void, uint8_t) -#undef COPY_ALIAS_FUNC -#define COPY_BACKWARD_ALIAS_FUNC(ctype, type, alias_type) \ -template <> inline type* copy_backward (ctype* first, ctype* last, type* result) \ -{ return ((type*) copy_backward ((const alias_type*) first, (const alias_type*) last, (alias_type*) result)); } -#if WANT_UNROLLED_COPY -#if HAVE_THREE_CHAR_TYPES -COPY_BACKWARD_ALIAS_FUNC(char, char, uint8_t) -#endif -COPY_BACKWARD_ALIAS_FUNC(uint8_t, uint8_t, uint8_t) -COPY_BACKWARD_ALIAS_FUNC(int8_t, int8_t, uint8_t) -COPY_BACKWARD_ALIAS_FUNC(uint16_t, uint16_t, uint8_t) -COPY_BACKWARD_ALIAS_FUNC(const uint16_t, uint16_t, uint8_t) -COPY_BACKWARD_ALIAS_FUNC(int16_t, int16_t, uint8_t) -COPY_BACKWARD_ALIAS_FUNC(const int16_t, int16_t, uint8_t) -#endif -COPY_BACKWARD_ALIAS_FUNC(void, void, uint8_t) -COPY_BACKWARD_ALIAS_FUNC(const void, void, uint8_t) -#undef COPY_BACKWARD_ALIAS_FUNC -#define FILL_ALIAS_FUNC(type, alias_type, v_type) \ -template <> inline void fill (type* first, type* last, const v_type& value) \ -{ fill ((alias_type*) first, (alias_type*) last, (const alias_type&) value); } -FILL_ALIAS_FUNC(void, uint8_t, char) -FILL_ALIAS_FUNC(void, uint8_t, uint8_t) -#if WANT_UNROLLED_COPY -#if HAVE_THREE_CHAR_TYPES -FILL_ALIAS_FUNC(char, uint8_t, char) -FILL_ALIAS_FUNC(char, uint8_t, uint8_t) -#endif -FILL_ALIAS_FUNC(int8_t, uint8_t, int8_t) -FILL_ALIAS_FUNC(int16_t, uint16_t, int16_t) -#if CPU_HAS_MMX || (SIZE_OF_LONG > 4) -FILL_ALIAS_FUNC(int32_t, uint32_t, int32_t) -#endif -#endif -#undef FILL_ALIAS_FUNC -#define COPY_N_ALIAS_FUNC(ctype, type, alias_type) \ -template <> inline type* copy_n (ctype* first, size_t count, type* result) \ -{ return ((type*) copy_n ((const alias_type*) first, count, (alias_type*) result)); } -COPY_N_ALIAS_FUNC(const void, void, uint8_t) -COPY_N_ALIAS_FUNC(void, void, uint8_t) -#if WANT_UNROLLED_COPY -#if HAVE_THREE_CHAR_TYPES -COPY_N_ALIAS_FUNC(const char, char, uint8_t) -COPY_N_ALIAS_FUNC(char, char, uint8_t) -#endif -COPY_N_ALIAS_FUNC(int8_t, int8_t, uint8_t) -COPY_N_ALIAS_FUNC(uint8_t, uint8_t, uint8_t) -COPY_N_ALIAS_FUNC(const int8_t, int8_t, uint8_t) -COPY_N_ALIAS_FUNC(int16_t, int16_t, uint16_t) -COPY_N_ALIAS_FUNC(uint16_t, uint16_t, uint16_t) -COPY_N_ALIAS_FUNC(const int16_t, int16_t, uint16_t) -#if CPU_HAS_MMX || (SIZE_OF_LONG > 4) -COPY_N_ALIAS_FUNC(int32_t, int32_t, uint32_t) -COPY_N_ALIAS_FUNC(uint32_t, uint32_t, uint32_t) -COPY_N_ALIAS_FUNC(const int32_t, int32_t, uint32_t) -#endif -#endif -#undef COPY_N_ALIAS_FUNC -#define FILL_N_ALIAS_FUNC(type, alias_type, v_type) \ -template <> inline type* fill_n (type* first, size_t n, const v_type& value) \ -{ return ((type*) fill_n ((alias_type*) first, n, (const alias_type&) value)); } -FILL_N_ALIAS_FUNC(void, uint8_t, char) -FILL_N_ALIAS_FUNC(void, uint8_t, uint8_t) -#if WANT_UNROLLED_COPY -#if HAVE_THREE_CHAR_TYPES -FILL_N_ALIAS_FUNC(char, uint8_t, char) -FILL_N_ALIAS_FUNC(char, uint8_t, uint8_t) -#endif -FILL_N_ALIAS_FUNC(int8_t, uint8_t, int8_t) -FILL_N_ALIAS_FUNC(int16_t, uint16_t, int16_t) -#if CPU_HAS_MMX || (SIZE_OF_LONG > 4) -FILL_N_ALIAS_FUNC(int32_t, uint32_t, int32_t) -#endif -#endif -#undef FILL_N_ALIAS_FUNC - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uassert.h b/media/libdrm/mobile2/src/util/ustl-1.0/uassert.h deleted file mode 100644 index a9fde4663dfd7bdf0b1891886ddbbc5d281c2685..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uassert.h +++ /dev/null @@ -1,21 +0,0 @@ -// uassert.h - -#ifndef UASSERT_H -#define UASSERT_H - -#if PLATFORM_ANDROID -#include - -#undef assert -#define assert(x) _uassert((x), #x, __FILE__, __LINE__) - -static void _uassert(int x, const char *xstr, const char *file, int line) { - if (!x) { - printf("assert %s failed at %s:%d\n", xstr, file, line); - } -} -#else -#include -#endif - -#endif diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.cpp deleted file mode 100644 index 21b5a7a8c636539d65b07c64412aa3af6f1cb926..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ubitset.cc -// - -#include "ubitset.h" - -namespace ustl { - -/// Copies bits from \p v of size \p n into \p buf as MSB "1011001..." LSB -/// If \p buf is too small, MSB bits will be truncated. -void convert_to_bitstring (const bitset_value_type* v, size_t n, string& buf) -{ - string::iterator stri = buf.end(); - for (size_t i = 0; i < n && stri > buf.begin(); ++ i) - for (bitset_value_type b = 1; b && stri > buf.begin(); b <<= 1) - *--stri = (v[i] & b) ? '1' : '0'; -} - -/// Copies bits from \p buf as MSB "1011001..." LSB into \p v of size \p n. -void convert_from_bitstring (const string& buf, bitset_value_type* v, size_t n) -{ - string::const_iterator stri = buf.end(); - for (size_t i = 0; i < n; ++ i) { - for (bitset_value_type b = 1; b; b <<= 1) { - if (stri == buf.begin() || *--stri == '0') - v[i] &= ~b; - else - v[i] |= b; - } - } -} - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.h b/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.h deleted file mode 100644 index 4f53a9525e39bde31566ba48a4a6bff0cb48cffa..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.h +++ /dev/null @@ -1,131 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ubitset.h -// -#ifndef UBITSET_H_7B6450EC1400CBA45DCE0127739F82EE -#define UBITSET_H_7B6450EC1400CBA45DCE0127739F82EE - -#include "uassert.h" -#include "ustring.h" -#include "ufunction.h" - -namespace ustl { - -typedef uint32_t bitset_value_type; - -void convert_to_bitstring (const bitset_value_type* v, size_t n, string& buf); -void convert_from_bitstring (const string& buf, bitset_value_type* v, size_t n); - -/// \class bitset ubitset.h ustl.h -/// \ingroup Sequences -/// -/// \brief bitset is a fixed-size block of memory with addressable bits. -/// -/// Normally used for state flags; allows setting and unsetting of individual -/// bits as well as bitwise operations on the entire set. The interface is -/// most like that of unsigned integers, and is intended to be used as such. -/// If you were using begin() and end() functions in STL's bitset, you would -/// not be able to do the same thing here, because those functions return -/// host type iterators, not bits. -/// -template -class bitset { -public: - typedef bitset_value_type value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef pointer iterator; - typedef const_pointer const_iterator; - typedef size_t difference_type; - typedef size_t size_type; -private: - static const size_t s_WordBits = BitsInType (value_type); - static const size_t s_nWords = Size / s_WordBits + ((Size % s_WordBits) != 0); - static const size_t s_nBits = s_nWords * s_WordBits; -private: - inline value_type& BitRef (uoff_t n) { assert (n < Size); return (m_Bits [n / s_WordBits]); } - inline const value_type BitRef (uoff_t n) const { assert (n < Size); return (m_Bits [n / s_WordBits]); } - inline const value_type Mask (uoff_t n) const { assert (n < Size); return (1 << (n % s_WordBits)); } -public: - inline bitset (value_type v = 0) { fill_n (m_Bits, s_nWords, 0); m_Bits[0] = v; } - inline bitset (const string& buf) { convert_from_bitstring (buf, m_Bits, s_nWords); } - inline void flip (uoff_t n) { BitRef(n) ^= Mask(n); } - inline void reset (void) { fill_n (m_Bits, s_nWords, 0); } - inline void clear (void) { fill_n (m_Bits, s_nWords, 0); } - inline void set (void) { fill_n (m_Bits, s_nWords, -1); } - inline bitset operator~ (void) const { bitset rv (*this); rv.flip(); return (rv); } - inline size_type size (void) const { return (Size); } - inline size_type capacity (void) const { return (s_nBits); } - inline const bool test (uoff_t n) const { return (BitRef(n) & Mask(n)); } - inline const bool operator[] (uoff_t n) const { return (test(n)); } - inline const_iterator begin (void) const { return (m_Bits); } - inline iterator begin (void) { return (m_Bits); } - inline const_iterator end (void) const { return (m_Bits + s_nWords); } - inline iterator end (void) { return (m_Bits + s_nWords); } - /// Returns the value_type with the equivalent bits. If size() > 1, you'll get only the first BitsInType(value_type) bits. - inline const value_type to_value (void) const { return (m_Bits[0]); } - /// Flips all the bits in the set. - inline void flip (void) { transform (begin(), end(), begin(), bitwise_not()); } - /// Sets or clears bit \p n. - inline void set (uoff_t n, bool val = true) - { - value_type& br (BitRef (n)); - const value_type mask (Mask (n)); - const value_type bOn (br | mask), bOff (br & ~mask); - br = val ? bOn : bOff; - } - // Sets the value of the bitrange \p first through \p last to the equivalent number of bits from \p v. - inline void set (uoff_t first, uoff_t DebugArg(last), value_type v) - { -#if !PLATFORM_ANDROID - assert (size_t (distance (first, last)) <= s_WordBits && "Bit ranges must be 32 bits or smaller"); - assert (first / s_WordBits == last / s_WordBits && "Bit ranges can not cross dword (4 byte) boundary"); - assert ((v & BitMask(value_type,distance(first,last))) == v && "The value is too large to fit in the given bit range"); -#endif - BitRef(first) |= v << (first % s_WordBits); - } - /// Clears the bit \p n. - inline void reset (uoff_t n) { set (n, false); } - /// Returns a string with bits MSB "001101001..." LSB. - inline string to_string (void) const - { - string rv (Size, '0'); - convert_to_bitstring (m_Bits, s_nWords, rv); - return (rv); - } - inline value_type at (uoff_t n) const { return (test(n)); } - /// Returns the value in bits \p first through \p last. - inline value_type at (uoff_t first, uoff_t last) const - { - assert (size_t (distance (first, last)) <= s_WordBits && "Bit ranges must be 32 bits or smaller"); - assert (first / s_WordBits == last / s_WordBits && "Bit ranges can not cross dword (4 byte) boundary"); - return ((BitRef(first) >> (first % s_WordBits)) & BitMask(value_type,distance(first, last))); - } - inline bool any (void) const { value_type sum = 0; foreach (const_iterator, i, *this) sum |= *i; return (sum); } - inline bool none (void) const { return (!any()); } - inline size_t count (void) const { size_t sum = 0; foreach (const_iterator, i, *this) sum += popcount(*i); return (sum); } - inline bool operator== (const bitset& v) const - { return (s_nWords == 1 ? (m_Bits[0] == v.m_Bits[0]) : equal (begin(), end(), v.begin())); } - inline const bitset operator& (const bitset& v) - { bitset result; transform (begin(), end(), v.begin(), result.begin(), bitwise_and()); return (result); } - inline const bitset operator| (const bitset& v) - { bitset result; transform (begin(), end(), v.begin(), result.begin(), bitwise_or()); return (result); } - inline const bitset operator^ (const bitset& v) - { bitset result; transform (begin(), end(), v.begin(), result.begin(), bitwise_xor()); return (result); } - inline const bitset& operator&= (const bitset& v) - { transform (begin(), end(), v.begin(), begin(), bitwise_and()); return (*this); } - inline const bitset& operator|= (const bitset& v) - { transform (begin(), end(), v.begin(), begin(), bitwise_or()); return (*this); } - inline const bitset& operator^= (const bitset& v) - { transform (begin(), end(), v.begin(), begin(), bitwise_xor()); return (*this); } -private: - value_type m_Bits [s_nWords]; -}; - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uctralgo.h b/media/libdrm/mobile2/src/util/ustl-1.0/uctralgo.h deleted file mode 100644 index 57f637d6bab595ff3ab9ff9fc6f3ab69982887d3..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uctralgo.h +++ /dev/null @@ -1,482 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// \file uctralgo.h -// -// \brief Implementation of STL algorithms with container shortcuts. -// -// The function prototypes are copied -// exactly from the SGI version of STL documentation along with comments about -// their use. The code is NOT the same, though the functionality usually is. -// - -#ifndef UCTRALGO_H_0D1AEDFA74B09791489FE25B1EC644B0 -#define UCTRALGO_H_0D1AEDFA74B09791489FE25B1EC644B0 - -#include "uassert.h" - -namespace ustl { - -/// Copy copies elements from the range [first, last) to the range -/// [result, result + (last - first)). That is, it performs the assignments -/// *result = *first, *(result + 1) = *(first + 1), and so on. [1] Generally, -/// for every integer n from 0 to last - first, copy performs the assignment -/// *(result + n) = *(first + n). Assignments are performed in forward order, -/// i.e. in order of increasing n. -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator copy (const Container& ctr, OutputIterator result) -{ - return (copy (ctr.begin(), ctr.end(), result)); -} - -/// Copy_if copies elements from the range [first, last) to the range -/// [result, result + (last - first)) if pred(*i) returns true. -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator copy_if (Container& ctr, OutputIterator result, Predicate pred) -{ - return (copy_if (ctr.begin(), ctr.end(), result, pred)); -} - -/// For_each applies the function object f to each element in the range -/// [first, last); f's return value, if any, is ignored. Applications are -/// performed in forward order, i.e. from first to last. For_each returns -/// the function object after it has been applied to each element. -/// \ingroup MutatingAlgorithms -/// -template -inline UnaryFunction for_each (Container& ctr, UnaryFunction f) -{ - return (for_each (ctr.begin(), ctr.end(), f)); -} - -/// For_each applies the function object f to each element in the range -/// [first, last); f's return value, if any, is ignored. Applications are -/// performed in forward order, i.e. from first to last. For_each returns -/// the function object after it has been applied to each element. -/// \ingroup MutatingAlgorithms -/// -template -inline UnaryFunction for_each (const Container& ctr, UnaryFunction f) -{ - return (for_each (ctr.begin(), ctr.end(), f)); -} - -/// Returns the first iterator i in the range [first, last) such that -/// *i == value. Returns last if no such iterator exists. -/// \ingroup SearchingAlgorithms -/// -template -inline typename Container::const_iterator find (const Container& ctr, const EqualityComparable& value) -{ - return (find (ctr.begin(), ctr.end(), value)); -} -template -inline typename Container::iterator find (Container& ctr, const EqualityComparable& value) -{ - return (find (ctr.begin(), ctr.end(), value)); -} - -/// Returns the first iterator i in the range [first, last) such that -/// pred(*i) is true. Returns last if no such iterator exists. -/// \ingroup SearchingAlgorithms -/// -template -inline typename Container::const_iterator find_if (const Container& ctr, Predicate pred) -{ - return (find_if (ctr.begin(), ctr.end(), pred)); -} -template -inline typename Container::iterator find_if (Container& ctr, Predicate pred) -{ - return (find_if (ctr.begin(), ctr.end(), pred)); -} - -/// Count finds the number of elements in [first, last) that are equal -/// to value. More precisely, the first version of count returns the -/// number of iterators i in [first, last) such that *i == value. -/// \ingroup ConditionAlgorithms -/// -template -inline size_t count (const Container& ctr, const EqualityComparable& value) -{ - return (count (ctr.begin(), ctr.end(), value)); -} - -/// Count_if finds the number of elements in [first, last) that satisfy the -/// predicate pred. More precisely, the first version of count_if returns the -/// number of iterators i in [first, last) such that pred(*i) is true. -/// \ingroup ConditionAlgorithms -/// -template -inline size_t count_if (const Container& ctr, Predicate pred) -{ - return (count_if (ctr.begin(), ctr.end(), pred)); -} - -/// The first version of transform performs the operation op(*i) for each -/// iterator i in the range [first, last), and assigns the result of that -/// operation to *o, where o is the corresponding output iterator. That is, -/// for each n such that 0 <= n < last - first, it performs the assignment -/// *(result + n) = op(*(first + n)). -/// The return value is result + (last - first). -/// \ingroup MutatingAlgorithms -/// -template -inline void transform (Container& ctr, UnaryFunction op) -{ - transform (ctr.begin(), ctr.end(), ctr.begin(), op); -} - -/// The first version of transform performs the operation op(*i) for each -/// iterator i in the range [first, last), and assigns the result of that -/// operation to *o, where o is the corresponding output iterator. That is, -/// for each n such that 0 <= n < last - first, it performs the assignment -/// *(result + n) = op(*(first + n)). -/// The return value is result + (last - first). -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator transform (Container& ctr, OutputIterator result, UnaryFunction op) -{ - return (transform (ctr.begin(), ctr.end(), result, op)); -} - -/// The second version of transform is very similar, except that it uses a -/// Binary Function instead of a Unary Function: it performs the operation -/// op(*i1, *i2) for each iterator i1 in the range [first1, last1) and assigns -/// the result to *o, where i2 is the corresponding iterator in the second -/// input range and where o is the corresponding output iterator. That is, -/// for each n such that 0 <= n < last1 - first1, it performs the assignment -/// *(result + n) = op(*(first1 + n), *(first2 + n). -/// The return value is result + (last1 - first1). -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator transform (Container& ctr, InputIterator first, OutputIterator result, BinaryFunction op) -{ - return (transform (ctr.begin(), ctr.end(), first, result, op)); -} - -/// Replace replaces every element in the range [first, last) equal to -/// old_value with new_value. That is: for every iterator i, -/// if *i == old_value then it performs the assignment *i = new_value. -/// \ingroup MutatingAlgorithms -/// -template -inline void replace (Container& ctr, const T& old_value, const T& new_value) -{ - replace (ctr.begin(), ctr.end(), old_value, new_value); -} - -/// Replace_if replaces every element in the range [first, last) for which -/// pred returns true with new_value. That is: for every iterator i, if -/// pred(*i) is true then it performs the assignment *i = new_value. -/// \ingroup MutatingAlgorithms -/// -template -inline void replace_if (Container& ctr, Predicate pred, const T& new_value) -{ - replace_if (ctr.begin(), ctr.end(), pred, new_value); -} - -/// Replace_copy copies elements from the range [first, last) to the range -/// [result, result + (last-first)), except that any element equal to old_value -/// is not copied; new_value is copied instead. More precisely, for every -/// integer n such that 0 <= n < last-first, replace_copy performs the -/// assignment *(result+n) = new_value if *(first+n) == old_value, and -/// *(result+n) = *(first+n) otherwise. -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator replace_copy (const Container& ctr, OutputIterator result, const T& old_value, const T& new_value) -{ - return (replace_copy (ctr.begin(), ctr.end(), result, old_value, new_value)); -} - -/// Replace_copy_if copies elements from the range [first, last) to the range -/// [result, result + (last-first)), except that any element for which pred is -/// true is not copied; new_value is copied instead. More precisely, for every -/// integer n such that 0 <= n < last-first, replace_copy_if performs the -/// assignment *(result+n) = new_value if pred(*(first+n)), -/// and *(result+n) = *(first+n) otherwise. -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator replace_copy_if (const Container& ctr, OutputIterator result, Predicate pred, const T& new_value) -{ - return (replace_copy_if (ctr.begin(), ctr.end(), result, pred, new_value)); -} - -/// Fill assigns the value value to every element in the range [first, last). -/// That is, for every iterator i in [first, last), -/// it performs the assignment *i = value. -/// \ingroup GeneratorAlgorithms -/// -template -inline void fill (Container& ctr, const T& value) -{ - fill (ctr.begin(), ctr.end(), value); -} - -/// Generate assigns the result of invoking gen, a function object that -/// takes no arguments, to each element in the range [first, last). -/// \ingroup GeneratorAlgorithms -/// -template -inline void generate (Container& ctr, Generator gen) -{ - generate (ctr.begin(), ctr.end(), gen); -} - -/// Randomly permute the elements of the container. -/// \ingroup GeneratorAlgorithms -/// -template -inline void random_shuffle (Container& ctr) -{ - random_shuffle (ctr.begin(), ctr.end()); -} - -/// Remove_copy copies elements that are not equal to value from the range -/// [first, last) to a range beginning at result. The return value is the -/// end of the resulting range. This operation is stable, meaning that the -/// relative order of the elements that are copied is the same as in the -/// range [first, last). -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator remove_copy (const Container& ctr, OutputIterator result, const T& value) -{ - return (remove_copy (ctr.begin(), ctr.end(), result, value)); -} - -/// Remove_copy_if copies elements from the range [first, last) to a range -/// beginning at result, except that elements for which pred is true are not -/// copied. The return value is the end of the resulting range. This operation -/// is stable, meaning that the relative order of the elements that are copied -/// is the same as in the range [first, last). -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator remove_copy_if (const Container& ctr, OutputIterator result, Predicate pred) -{ - return (remove_copy_if (ctr.begin(), ctr.end(), result, pred)); -} - -/// Remove removes from the range [first, last) all elements that are equal to -/// value. That is, remove returns an iterator new_last such that the range -/// [first, new_last) contains no elements equal to value. Remove is stable, -/// meaning that the relative order of elements that are not equal to value is -/// unchanged. -/// \ingroup MutatingAlgorithms -/// -template -inline void remove (Container& ctr, const T& value) -{ - ctr.erase (remove_copy (ctr.begin(), ctr.end(), ctr.begin(), value), ctr.end()); -} - -/// Remove removes from the range [first, last) all elements that have an iterator -/// in range [rfirst, rlast). The range is assumed to be sorted. That is, remove -/// returns an iterator new_last such that the range [first, new_last) contains -/// no elements whose iterators are in [rfirst, rlast). Remove is stable, -/// meaning that the relative order of elements that are not equal to value is -/// unchanged. This version of the algorithm is a uSTL extension. -/// \ingroup MutatingAlgorithms -/// -template -inline void remove (Container& ctr, ForwardIterator rfirst, ForwardIterator rlast) -{ - ctr.erase (remove_copy (ctr.begin(), ctr.end(), ctr.begin(), rfirst, rlast), ctr.end()); -} - -/// Remove_if removes from the range [first, last) every element x such that -/// pred(x) is true. That is, remove_if returns an iterator new_last such that -/// the range [first, new_last) contains no elements for which pred is true. -/// The iterators in the range [new_last, last) are all still dereferenceable, -/// but the elements that they point to are unspecified. Remove_if is stable, -/// meaning that the relative order of elements that are not removed is -/// unchanged. -/// \ingroup MutatingAlgorithms -/// -template -inline void remove_if (Container& ctr, Predicate pred) -{ - ctr.erase (remove_copy_if (ctr.begin(), ctr.end(), ctr.begin(), pred), ctr.end()); -} - -/// Unique_copy copies elements from the range [first, last) to a range -/// beginning with result, except that in a consecutive group of duplicate -/// elements only the first one is copied. The return value is the end of -/// the range to which the elements are copied. This behavior is similar -/// to the Unix filter uniq. -/// \ingroup MutatingAlgorithms -/// -template -inline OutputIterator unique_copy (const Container& ctr, OutputIterator result) -{ - return (unique_copy (ctr.begin(), ctr.end(), result)); -} - -/// Every time a consecutive group of duplicate elements appears in the range -/// [first, last), the algorithm unique removes all but the first element. -/// That is, unique returns an iterator new_last such that the range [first, -/// new_last) contains no two consecutive elements that are duplicates. -/// The iterators in the range [new_last, last) are all still dereferenceable, -/// but the elements that they point to are unspecified. Unique is stable, -/// meaning that the relative order of elements that are not removed is -/// unchanged. -/// \ingroup MutatingAlgorithms -/// -template -inline void unique (Container& ctr) -{ - ctr.erase (unique_copy (ctr.begin(), ctr.end(), ctr.begin()), ctr.end()); -} - -/// Every time a consecutive group of duplicate elements appears in the range -/// [first, last), the algorithm unique removes all but the first element. -/// That is, unique returns an iterator new_last such that the range [first, -/// new_last) contains no two consecutive elements that are duplicates. -/// The iterators in the range [new_last, last) are all still dereferenceable, -/// but the elements that they point to are unspecified. Unique is stable, -/// meaning that the relative order of elements that are not removed is -/// unchanged. -/// \ingroup MutatingAlgorithms -/// -template -inline void unique (Container& ctr, BinaryPredicate binary_pred) -{ - ctr.erase (unique_copy (ctr.begin(), ctr.end(), ctr.begin(), binary_pred), ctr.end()); -} - -/// Reverse reverses a range. -/// That is: for every i such that 0 <= i <= (last - first) / 2), -/// it exchanges *(first + i) and *(last - (i + 1)). -/// \ingroup MutatingAlgorithms -/// -template -inline void reverse (Container& ctr) -{ - reverse (ctr.begin(), ctr.end()); -} - -/// Exchanges ranges [first, middle) and [middle, last) -/// \ingroup MutatingAlgorithms -/// -template -inline void rotate (Container& ctr, off_t offset) -{ - assert (size_t(offset > 0 ? offset : -offset) < ctr.size()); - if (offset > 0) - rotate (ctr.begin(), ctr.end() - offset, ctr.end()); - else - rotate (ctr.begin(), ctr.begin() - offset, ctr.end()); -} - -/// Returns the furthermost iterator i in [first, last) such that, -/// for every iterator j in [first, i), *j < value -/// Assumes the range is sorted. -/// \ingroup SearchingAlgorithms -/// -template -inline typename Container::const_iterator lower_bound (const Container& ctr, const LessThanComparable& value) -{ - return (lower_bound (ctr.begin(), ctr.end(), value)); -} -template -inline typename Container::iterator lower_bound (Container& ctr, const LessThanComparable& value) -{ - return (lower_bound (ctr.begin(), ctr.end(), value)); -} - -/// Returns the furthermost iterator i in [first,last) such that for -/// every iterator j in [first,i), value < *j is false. -/// \ingroup SearchingAlgorithms -/// -template -inline typename Container::const_iterator upper_bound (const Container& ctr, const LessThanComparable& value) -{ - return (upper_bound (ctr.begin(), ctr.end(), value)); -} -template -inline typename Container::iterator upper_bound (Container& ctr, const LessThanComparable& value) -{ - return (upper_bound (ctr.begin(), ctr.end(), value)); -} - -/// Performs a binary search for \p value. -/// Assumes the range is sorted. -/// \ingroup SearchingAlgorithms -/// -template -inline typename Container::const_iterator binary_search (const Container& ctr, const typename Container::value_type& value) -{ - return (binary_search (ctr.begin(), ctr.end(), value)); -} -template -inline typename Container::iterator binary_search (Container& ctr, const typename Container::value_type& value) -{ - return (binary_search (ctr.begin(), ctr.end(), value)); -} - -/// Returns pair -/// \ingroup SearchingAlgorithms -/// -template -inline pair equal_range (const Container& ctr, const LessThanComparable& value) -{ - return (equal_range (ctr.begin(), ctr.end(), value)); -} -template -inline pair equal_range (Container& ctr, const LessThanComparable& value) -{ - return (equal_range (ctr.begin(), ctr.end(), value)); -} - -/// Sorts the container -/// \ingroup SortingAlgorithms -/// -template -inline void sort (Container& ctr) -{ - sort (ctr.begin(), ctr.end()); -} - -/// Sorts the container -/// \ingroup SortingAlgorithms -/// -template -inline void sort (Container& ctr, Compare comp) -{ - sort (ctr.begin(), ctr.end(), comp); -} - -/// Sorts the container -/// \ingroup SortingAlgorithms -/// -template -inline void stable_sort (Container& ctr) -{ - stable_sort (ctr.begin(), ctr.end()); -} - -/// Sorts the container -/// \ingroup SortingAlgorithms -/// -template -inline void stable_sort (Container& ctr, Compare comp) -{ - stable_sort (ctr.begin(), ctr.end(), comp); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uctrstrm.h b/media/libdrm/mobile2/src/util/ustl-1.0/uctrstrm.h deleted file mode 100644 index 39ddcdd7670f85ce11185657f653afaa2b5abc2e..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uctrstrm.h +++ /dev/null @@ -1,177 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -/// \file uctrstrm.h -/// -/// \brief Serialization templates for standard containers. -/// Because containers are templates, a single operator>> is impossible. -/// Making virtual read/write is also impossible because not all containers -/// contain serializable elements. Therefore, use the macros in this file. -/// - -#ifndef UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC -#define UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC - -#include "mistream.h" -#include "sostream.h" -#include "uiosfunc.h" - -namespace ustl { - -//---------------------------------------------------------------------- -// Macros for easily declaring a container streamable. -//---------------------------------------------------------------------- - -/// \brief Declares container template \p type streamable. -/// -/// Use TEMPLATE_TYPE and TEMPLATE_DECL macros to pass in templated -/// type with commas and the template declaration. -/// -#define STD_TEMPLATE_CTR_STREAMABLE(type, template_decl) \ - template_decl \ - inline istream& operator>> (istream& is, type& v) \ - { return (container_read (is, v)); } \ - template_decl \ - inline ostream& operator<< (ostream& os, const type& v) \ - { return (container_write (os, v)); } \ - template_decl \ - inline ostringstream& operator<< (ostringstream& os, const type& v) \ - { return (container_text_write (os, v)); } \ - template_decl \ - inline size_t stream_size_of (const type& v) \ - { return (container_stream_size (v)); } - -/// \brief Declares non-resizable container template \p type streamable. -#define STD_TEMPLATE_NR_CTR_STREAMABLE(type, template_decl) \ - template_decl \ - inline istream& operator>> (istream& is, type& v) \ - { return (nr_container_read (is, v)); } \ - template_decl \ - inline ostream& operator<< (ostream& os, const type& v) \ - { return (nr_container_write (os, v)); } \ - template_decl \ - inline ostringstream& operator<< (ostringstream& os, const type& v) \ - { return (container_text_write (os, v)); } \ - template_decl \ - inline size_t stream_size_of (const type& v) \ - { return (nr_container_stream_size (v)); } - -//---------------------------------------------------------------------- -// Fixed size container serialization. -//---------------------------------------------------------------------- - -/// Reads fixed size container \p v from stream \p is. -template -inline istream& nr_container_read (istream& is, Container& v) -{ - foreach (typename Container::iterator, i, v) - is >> *i; - return (is); -} - -/// Writes fixed size container \p v into stream \p os. -template -inline ostream& nr_container_write (ostream& os, const Container& v) -{ - foreach (typename Container::const_iterator, i, v) - os << *i; - return (os); -} - -/// Computes the stream size of a fixed size standard container. -template -size_t nr_container_stream_size (const Container& v) -{ - typedef typename Container::const_iterator vciter_t; - typedef typename iterator_traits::value_type value_type; - size_t s = 0; - if (numeric_limits::is_integral) - s += v.size() * stream_size_of(value_type()); - else - foreach (vciter_t, i, v) - s += stream_size_of(*i); - return (s); -} - -//---------------------------------------------------------------------- -// Resizable container serialization. -//---------------------------------------------------------------------- - -/// Reads container \p v from stream \p is. -template -istream& container_read (istream& is, Container& v) -{ - typedef typename Container::value_type value_type; - typedef typename Container::iterator iterator; - typedef typename Container::written_size_type written_size_type; - written_size_type n; - is >> n; - const size_t expectedSize = n * stream_size_of(value_type()); -#if !PLATFORM_ANDROID - is.verify_remaining ("read", typeid(v).name(), expectedSize); -#endif - if (alignof(value_type()) > alignof(n)) - is >> ios::talign(); - v.resize (n); - nr_container_read (is, v); - is >> ios::talign(); - return (is); -} - -/// Writes the vector to stream \p os. -template -ostream& container_write (ostream& os, const Container& v) -{ - typedef typename Container::value_type value_type; - typedef typename Container::written_size_type written_size_type; - const written_size_type sz (v.size()); - os << sz; - if (alignof(value_type()) > alignof(sz)) - os << ios::talign(); - nr_container_write (os, v); - os << ios::talign(); - return (os); -} - -/// Computes the stream size of a standard container. -template -size_t container_stream_size (const Container& v) -{ - typedef typename Container::value_type value_type; - typedef typename Container::written_size_type written_size_type; - const written_size_type sz (v.size()); - size_t sizeSize = stream_size_of (sz); - if (alignof(value_type()) > alignof(sz)) - sizeSize = Align (sizeSize, alignof(value_type())); - return (Align (sizeSize + nr_container_stream_size (v), alignof(sz))); -} - -/// \brief Writes element \p v into stream \p os as text. -/// Specialize to custom print elements. -template -inline ostringstream& container_element_text_write (ostringstream& os, const T& v) -{ return (os << v); } - -/// Writes container \p v into stream \p os as text. -template -ostringstream& container_text_write (ostringstream& os, const Container& v) -{ - typename Container::const_iterator i = v.begin(); - os << '('; - while (i < v.end()) { - container_element_text_write (os, *i); - if (++i >= v.end()) break; - os << ','; - } - os << ')'; - return (os); -} - -//---------------------------------------------------------------------- - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uexception.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/uexception.cpp deleted file mode 100644 index d00f2194f2dd7ff029841a79a559ac9a44e8b254..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uexception.cpp +++ /dev/null @@ -1,305 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// uexception.cc -// - -#include "uassert.h" -#include "uexception.h" -#include "ustring.h" -#include "mistream.h" -#include "sostream.h" -#include "strmsize.h" -#include "uspecial.h" -#include -#if __GNUC__ >= 3 && !PLATFORM_ANDROID - #include -#endif - -namespace ustl { - -//---------------------------------------------------------------------- - -/// \brief Returns a descriptive error message. fmt="%s" -/// Overloads of this functions must set NULL as the default fmt -/// argument and handle that case to provide a default format string -/// in case the user does not have a localized one. The format -/// string should be shown in the documentation to not require -/// translators to look through code. Also, this function must -/// not throw anything, so you must wrap memory allocation routines -/// (like string::format, for instance) in a try{}catch(...){} block. -/// -void exception::info (string& msgbuf, const char*) const throw() -{ -#if PLATFORM_ANDROID - msgbuf.format ("%s", what()); -#else /* !PLATFORM_ANDROID */ - try { msgbuf.format ("%s", what()); } catch (...) { /* Ignore all exceptions */ } -#endif -} - -/// Reads the exception from stream \p is. -void exception::read (istream& is) -{ - uint32_t stmSize; - xfmt_t fmt; - is >> fmt >> stmSize >> m_Backtrace; - assert (fmt == m_Format && "The saved exception is of a different type."); - assert (stmSize - exception::stream_size() <= is.remaining() && "The saved exception data is corrupt."); - m_Format = fmt; -} - -/// Writes the exception into stream \p os as an IFF chunk. -void exception::write (ostream& os) const -{ - os << m_Format << uint32_t(stream_size()) << m_Backtrace; -} - -/// Writes the exception as text into stream \p os. -void exception::text_write (ostringstream& os) const -{ -#if !PLATFORM_ANDROID - try { -#endif - string buf; - info (buf); - os << buf; -#if !PLATFORM_ANDROID - } catch (...) {} -#endif -} - -//---------------------------------------------------------------------- - -/// Initializes the empty object. \p nBytes is the size of the attempted allocation. -bad_alloc::bad_alloc (size_t nBytes) throw() -: ustl::exception(), - m_nBytesRequested (nBytes) -{ - set_format (xfmt_BadAlloc); -} - -/// Returns a descriptive error message. fmt="failed to allocate %d bytes" -void bad_alloc::info (string& msgbuf, const char* fmt) const throw() -{ - if (!fmt) fmt = "failed to allocate %d bytes"; -#if PLATFORM_ANDROID - msgbuf.format (fmt, m_nBytesRequested); -#else /* !PLATFORM_ANDROID */ - try { msgbuf.format (fmt, m_nBytesRequested); } catch (...) {} -#endif -} - -/// Reads the exception from stream \p is. -void bad_alloc::read (istream& is) -{ - ustl::exception::read (is); - is >> m_nBytesRequested; -} - -/// Writes the exception into stream \p os. -void bad_alloc::write (ostream& os) const -{ - ustl::exception::write (os); - os << m_nBytesRequested; -} - -/// Returns the size of the written exception. -size_t bad_alloc::stream_size (void) const -{ - return (ustl::exception::stream_size() + stream_size_of(m_nBytesRequested)); -} - -//---------------------------------------------------------------------- - -/// Initializes the empty object. \p operation is the function that returned the error code. -libc_exception::libc_exception (const char* operation) throw() -: exception(), - m_Errno (errno), - m_Operation (operation) -{ - set_format (xfmt_LibcException); -} - -/// Copies object \p v. -libc_exception::libc_exception (const libc_exception& v) throw() -: exception (v), - m_Errno (v.m_Errno), - m_Operation (v.m_Operation) -{ -} - -/// Copies object \p v. -const libc_exception& libc_exception::operator= (const libc_exception& v) -{ - m_Errno = v.m_Errno; - m_Operation = v.m_Operation; - return (*this); -} - -/// Returns a descriptive error message. fmt="%s: %m" -void libc_exception::info (string& msgbuf, const char* fmt) const throw() -{ - if (!fmt) fmt = "%s: %m"; -#if PLATFORM_ANDROID - msgbuf.format (fmt, m_Operation, m_Errno, m_Errno); -#else /* !PLATFORM_ANDROID */ - try { msgbuf.format (fmt, m_Operation, m_Errno, m_Errno); } catch (...) {} -#endif -} - -/// Reads the exception from stream \p is. -void libc_exception::read (istream& is) -{ - exception::read (is); - is >> m_Errno >> m_Operation; -} - -/// Writes the exception into stream \p os. -void libc_exception::write (ostream& os) const -{ - exception::write (os); - os << m_Errno << m_Operation; -} - -/// Returns the size of the written exception. -size_t libc_exception::stream_size (void) const -{ - return (exception::stream_size() + - stream_size_of(m_Errno) + - stream_size_of(m_Operation)); -} - -//---------------------------------------------------------------------- - -/// Initializes the empty object. \p operation is the function that returned the error code. -file_exception::file_exception (const char* operation, const char* filename) throw() -: libc_exception (operation) -{ - memset (m_Filename, 0, VectorSize(m_Filename)); - set_format (xfmt_FileException); - if (filename) { - strncpy (m_Filename, filename, VectorSize(m_Filename)); - m_Filename [VectorSize(m_Filename) - 1] = 0; - } -} - -/// Returns a descriptive error message. fmt="%s %s: %m" -void file_exception::info (string& msgbuf, const char* fmt) const throw() -{ - if (!fmt) fmt = "%s %s: %m"; -#if PLATFORM_ANDROID - msgbuf.format (fmt, m_Operation, m_Filename, m_Errno, m_Errno); -#else /* !PLATFORM_ANDROID */ - try { msgbuf.format (fmt, m_Operation, m_Filename, m_Errno, m_Errno); } catch (...) {} -#endif -} - -/// Reads the exception from stream \p is. -void file_exception::read (istream& is) -{ - libc_exception::read (is); - string filename; - is >> filename; - is.align (8); - filename.copyto (filename, VectorSize(m_Filename)); -} - -/// Writes the exception into stream \p os. -void file_exception::write (ostream& os) const -{ - libc_exception::write (os); - os << string (m_Filename); - os.align (8); -} - -/// Returns the size of the written exception. -size_t file_exception::stream_size (void) const -{ - return (libc_exception::stream_size() + - Align (stream_size_of (string (m_Filename)), 8)); -} - -//---------------------------------------------------------------------- - -/// \brief Uses C++ ABI call, if available to demangle the contents of \p buf. -/// -/// The result is written to \p buf, with the maximum size of \p bufSize, and -/// is zero-terminated. The return value is \p buf. -/// -const char* demangle_type_name (char* buf, size_t bufSize, size_t* pdmSize) -{ - size_t bl = strlen (buf); -#if __GNUC__ >= 3 && !PLATFORM_ANDROID - char dmname [256]; - size_t sz = VectorSize(dmname); - int bFailed; - abi::__cxa_demangle (buf, dmname, &sz, &bFailed); - if (!bFailed) { - bl = min (strlen (dmname), bufSize - 1); - memcpy (buf, dmname, bl); - buf[bl] = 0; - } -#else - bl = min (bl, bufSize); -#endif - if (pdmSize) - *pdmSize = bl; - return (buf); -} - -//---------------------------------------------------------------------- - -/// Initializes the empty object. \p operation is the function that returned the error code. -stream_bounds_exception::stream_bounds_exception (const char* operation, const char* type, uoff_t offset, size_t expected, size_t remaining) throw() -: libc_exception (operation), - m_TypeName (type), - m_Offset (offset), - m_Expected (expected), - m_Remaining (remaining) -{ - set_format (xfmt_StreamBoundsException); -} - -/// Returns a descriptive error message. fmt="%s stream %s: @%u: expected %u, available %u"; -void stream_bounds_exception::info (string& msgbuf, const char* fmt) const throw() -{ - char typeName [256]; - strncpy (typeName, m_TypeName, VectorSize(typeName)); - typeName[VectorSize(typeName)-1] = 0; - if (!fmt) fmt = "%s stream %s: @0x%X: need %u bytes, have %u"; -#if PLATFORM_ANDROID - msgbuf.format (fmt, demangle_type_name (VectorBlock(typeName)), m_Operation, m_Offset, m_Expected, m_Remaining); -#else /* !PLATFORM_ANDROID */ - try { msgbuf.format (fmt, demangle_type_name (VectorBlock(typeName)), m_Operation, m_Offset, m_Expected, m_Remaining); } catch (...) {} -#endif -} - -/// Reads the exception from stream \p is. -void stream_bounds_exception::read (istream& is) -{ - libc_exception::read (is); - is >> m_TypeName >> m_Offset >> m_Expected >> m_Remaining; -} - -/// Writes the exception into stream \p os. -void stream_bounds_exception::write (ostream& os) const -{ - libc_exception::write (os); - os << m_TypeName << m_Offset << m_Expected << m_Remaining; -} - -/// Returns the size of the written exception. -size_t stream_bounds_exception::stream_size (void) const -{ - return (libc_exception::stream_size() + - stream_size_of(m_TypeName) + - stream_size_of(m_Offset) + - stream_size_of(m_Expected) + - stream_size_of(m_Remaining)); -} - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uexception.h b/media/libdrm/mobile2/src/util/ustl-1.0/uexception.h deleted file mode 100644 index 3e9a179d04319997e823b68ff908b42eb73d6482..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uexception.h +++ /dev/null @@ -1,194 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// uexception.h -// -// This file contains stuff from \. -// The standard C++ headers are duplicated because uSTL is intended -// to completely replace all C++ standard library functions. -// - -#ifndef UEXCEPTION_H_18DE3EF55C4F00673268F0D66546AF5D -#define UEXCEPTION_H_18DE3EF55C4F00673268F0D66546AF5D - -#include "utypes.h" -#ifndef WITHOUT_LIBSTDCPP - #include - #include -#endif -#include "bktrace.h" - -#ifdef WITHOUT_LIBSTDCPP // This code is copied from -namespace std { -/// If you write a replacement terminate handler, it must be of this type. -typedef void (*terminate_handler) (void); -/// If you write a replacement unexpected handler, it must be of this type. -typedef void (*unexpected_handler) (void); -/// Takes a new handler function as an argument, returns the old function. -terminate_handler set_terminate (terminate_handler pHandler) throw(); -/// The runtime will call this function if exception handling must be -/// abandoned for any reason. It can also be called by the user. -void terminate (void) __attribute__ ((__noreturn__)); -/// Takes a new handler function as an argument, returns the old function. -unexpected_handler set_unexpected (unexpected_handler pHandler) throw(); -/// The runtime will call this function if an exception is thrown which -/// violates the function's exception specification. -void unexpected (void) __attribute__ ((__noreturn__)); -/// Returns true when the caught exception violates the throw specification. -bool uncaught_exception() throw(); -} // namespace std -#endif - -namespace ustl { - -class string; - -typedef uint32_t xfmt_t; - -enum { - xfmt_Exception, - xfmt_BadAlloc, - xfmt_LibcException = 12, - xfmt_FileException = 13, - xfmt_StreamBoundsException = 14 -}; - -/// \class exception uexception.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Base class for exceptions, equivalent to std::exception. -/// -#ifdef WITHOUT_LIBSTDCPP -class exception { -#else -class exception : public std::exception { -#endif -public: - typedef const CBacktrace& rcbktrace_t; -public: - inline exception (void) throw() : m_Format (xfmt_Exception) {} - inline virtual ~exception (void) throw() {} - inline virtual const char* what (void) const throw() { return ("error"); } - virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); - virtual void read (istream& is); - virtual void write (ostream& os) const; - void text_write (ostringstream& os) const; - inline virtual size_t stream_size (void) const { return (sizeof(m_Format) + sizeof(uint32_t) + m_Backtrace.stream_size()); } - /// Format of the exception is used to lookup exception::info format string. - /// Another common use is the instantiation of serialized exceptions, used - /// by the error handler node chain to troubleshoot specific errors. - inline xfmt_t format (void) const { return (m_Format); } - inline rcbktrace_t backtrace (void) const { return (m_Backtrace); } -protected: - inline void set_format (xfmt_t fmt) { m_Format = fmt; } -private: - CBacktrace m_Backtrace; ///< Backtrace of the throw point. - xfmt_t m_Format; ///< Format of the exception's data. -}; - -/// \class bad_cast uexception.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Thrown to indicate a bad dynamic_cast usage. -/// -class bad_cast : public exception { -public: - inline explicit bad_cast (void) throw() : exception() {} - inline virtual const char* what (void) const throw() { return ("bad cast"); } -}; - -//---------------------------------------------------------------------- - -/// \class bad_alloc uexception.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Exception thrown on memory allocation failure by memblock::reserve. -/// -#ifdef WITHOUT_LIBSTDCPP -class bad_alloc : public exception { -#else -class bad_alloc : public std::bad_alloc, public exception { -#endif -public: - explicit bad_alloc (size_t nBytes = 0) throw(); - inline virtual const char* what (void) const throw() { return ("memory allocation failed"); } - virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); - virtual void read (istream& is); - virtual void write (ostream& os) const; - virtual size_t stream_size (void) const; -protected: - size_t m_nBytesRequested; ///< Number of bytes requested by the failed allocation. -}; - -/// \class libc_exception uexception.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Thrown when a libc function returns an error. -/// -/// Contains an errno and description. This is a uSTL extension. -/// -class libc_exception : public exception { -public: - explicit libc_exception (const char* operation) throw(); - libc_exception (const libc_exception& v) throw(); - const libc_exception& operator= (const libc_exception& v); - inline virtual const char* what (void) const throw() { return ("libc function failed"); } - virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); - virtual void read (istream& is); - virtual void write (ostream& os) const; - virtual size_t stream_size (void) const; -protected: - intptr_t m_Errno; ///< Error code returned by the failed operation. - const char* m_Operation; ///< Name of the failed operation. -}; - -/// \class file_exception uexception.h ustl.h -/// \ingroup Exceptions -/// -/// \brief File-related exceptions. -/// -/// Contains the file name. This is a uSTL extension. -/// -class file_exception : public libc_exception { -public: - file_exception (const char* operation, const char* filename) throw(); - inline virtual const char* what (void) const throw() { return ("file error"); } - virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); - virtual void read (istream& is); - virtual void write (ostream& os) const; - virtual size_t stream_size (void) const; -protected: - char m_Filename [PATH_MAX]; ///< Name of the file causing the error. -}; - -/// \class stream_bounds_exception uexception.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Stream bounds checking. -/// -/// Only thrown in debug builds unless you say otherwise in config.h -/// This is a uSTL extension. -/// -class stream_bounds_exception : public libc_exception { -public: - stream_bounds_exception (const char* operation, const char* type, uoff_t offset, size_t expected, size_t remaining) throw(); - inline virtual const char* what (void) const throw() { return ("stream bounds exception"); } - virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); - virtual void read (istream& is); - virtual void write (ostream& os) const; - virtual size_t stream_size (void) const; -protected: - const char* m_TypeName; - uoff_t m_Offset; - size_t m_Expected; - size_t m_Remaining; -}; - -const char* demangle_type_name (char* buf, size_t bufSize, size_t* pdmSize = NULL); - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ufunction.h b/media/libdrm/mobile2/src/util/ustl-1.0/ufunction.h deleted file mode 100644 index 53dc5e2b2278ed499e835472430efd83f4fcf0b6..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ufunction.h +++ /dev/null @@ -1,480 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// \file ufunction.h -// -// \brief Implements STL standard functors. -// -// See STL specification and bvts for usage of these. The only -// extension is the mem_var functors for member variable access: -// \code -// f = find_if (ctr, mem_var_equal_to(&MyClass::m_Var, matchVar)); -// f = find_if (ctr, mem_var_less(&MyClass::m_Var, matchVar)); -// \endcode -// There are a couple of others but the syntax is much harder to grasp. -// See bvt10.cc for more examples. -// - -#ifndef UFUNCTION_H_221ABA8551801799263C927234C085F3 -#define UFUNCTION_H_221ABA8551801799263C927234C085F3 - -namespace ustl { - -//---------------------------------------------------------------------- -// Standard functors -//---------------------------------------------------------------------- - -/// \brief void-returning function abstract interface. -/// \ingroup FunctorObjects -template -struct void_function { - typedef Result result_type; -}; - -/// \brief \p Result f (\p Arg) function abstract interface. -/// \ingroup FunctorObjects -template -struct unary_function { - typedef Arg argument_type; - typedef Result result_type; -}; - -/// \brief \p Result f (\p Arg1, \p Arg2) function abstract interface. -/// \ingroup FunctorObjects -template -struct binary_function { - typedef Arg1 first_argument_type; - typedef Arg2 second_argument_type; - typedef Result result_type; -}; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -#define STD_BINARY_FUNCTOR(name, rv, func) \ -template struct name : public binary_function \ -{ inline rv operator()(const T& a, const T& b) const { return func; } }; -#define STD_UNARY_FUNCTOR(name, rv, func) \ -template struct name : public unary_function \ -{ inline rv operator()(const T& a) const { return func; } }; -#define STD_CONVERSION_FUNCTOR(name, func) \ -template struct name : public unary_function \ -{ inline D operator()(const S& a) const { return func; } }; - -STD_BINARY_FUNCTOR (plus, T, (a + b)) -STD_BINARY_FUNCTOR (minus, T, (a - b)) -STD_BINARY_FUNCTOR (divides, T, (a / b)) -STD_BINARY_FUNCTOR (modulus, T, (a % b)) -STD_BINARY_FUNCTOR (multiplies, T, (a * b)) -STD_BINARY_FUNCTOR (logical_and, T, (a && b)) -STD_BINARY_FUNCTOR (logical_or, T, (a || b)) -STD_UNARY_FUNCTOR (logical_not, T, (!a)) -STD_BINARY_FUNCTOR (bitwise_or, T, (a | b)) -STD_BINARY_FUNCTOR (bitwise_and, T, (a & b)) -STD_BINARY_FUNCTOR (bitwise_xor, T, (a ^ b)) -STD_UNARY_FUNCTOR (bitwise_not, T, (~a)) -STD_UNARY_FUNCTOR (negate, T, (-a)) -STD_BINARY_FUNCTOR (equal_to, bool, (a == b)) -STD_BINARY_FUNCTOR (not_equal_to, bool, (!(a == b))) -STD_BINARY_FUNCTOR (greater, bool, (b < a)) -STD_BINARY_FUNCTOR (less, bool, (a < b)) -STD_BINARY_FUNCTOR (greater_equal, bool, (!(a < b))) -STD_BINARY_FUNCTOR (less_equal, bool, (!(b < a))) -STD_BINARY_FUNCTOR (compare, int, (a < b ? -1 : (b < a))) -STD_UNARY_FUNCTOR (identity, T, (a)) - -#endif // DOXYGEN_SHOULD_SKIP_THIS - -/// \brief Selects and returns the first argument. -/// \ingroup FunctorObjects -template struct project1st : public binary_function { inline const T1& operator()(const T1& a, const T2&) const { return (a); } }; -/// \brief Selects and returns the second argument. -/// \ingroup FunctorObjects -template struct project2nd : public binary_function { inline const T2& operator()(const T1&, const T2& a) const { return (a); } }; - -//---------------------------------------------------------------------- -// Generic function to functor converters. -//---------------------------------------------------------------------- - -/// \brief Wrapper object for unary function pointers. -/// Use the \ref ptr_fun accessor to create this object. -/// \ingroup FunctorObjects -template -class pointer_to_unary_function : public unary_function { -public: - typedef Arg argument_type; - typedef Result result_type; - typedef Result (*pfunc_t)(Arg); -public: - explicit inline pointer_to_unary_function (pfunc_t pfn) : m_pfn (pfn) {} - inline result_type operator() (argument_type v) const { return (m_pfn(v)); } -private: - pfunc_t m_pfn; ///< Pointer to the wrapped function. -}; - -/// \brief Wrapper object for binary function pointers. -/// Use the \ref ptr_fun accessor to create this object. -/// \ingroup FunctorObjects -template -class pointer_to_binary_function : public binary_function { -public: - typedef Arg1 first_argument_type; - typedef Arg2 second_argument_type; - typedef Result result_type; - typedef Result (*pfunc_t)(Arg1, Arg2); -public: - explicit inline pointer_to_binary_function (pfunc_t pfn) : m_pfn (pfn) {} - inline result_type operator() (first_argument_type v1, second_argument_type v2) const { return (m_pfn(v1, v2)); } -private: - pfunc_t m_pfn; ///< Pointer to the wrapped function. -}; - -/// ptr_fun(pfn) wraps function pointer pfn into a functor class that calls it. -/// \ingroup FunctorAccessors -template -inline pointer_to_unary_function ptr_fun (Result (*pfn)(Arg)) -{ - return (pointer_to_unary_function (pfn)); -} - -/// ptr_fun(pfn) wraps function pointer pfn into a functor class that calls it. -/// \ingroup FunctorAccessors -template -inline pointer_to_binary_function ptr_fun (Result (*pfn)(Arg1,Arg2)) -{ - return (pointer_to_binary_function (pfn)); -} - -//---------------------------------------------------------------------- -// Negators. -//---------------------------------------------------------------------- - -/// \brief Wraps a unary function to return its logical negative. -/// Use the \ref unary_negator accessor to create this object. -/// \ingroup FunctorObjects -template -class unary_negate : public unary_function { -public: - typedef typename UnaryFunction::argument_type argument_type; - typedef typename UnaryFunction::result_type result_type; -public: - explicit inline unary_negate (UnaryFunction pfn) : m_pfn (pfn) {} - inline result_type operator() (argument_type v) const { return (!m_pfn(v)); } -private: - UnaryFunction m_pfn; -}; - -/// Returns the functor that negates the result of *pfn(). -/// \ingroup FunctorAccessors -template -inline unary_negate unary_negator (UnaryFunction pfn) -{ - return (unary_negate(pfn)); -} - -//---------------------------------------------------------------------- -// Argument binders -//---------------------------------------------------------------------- - -/// \brief Converts a binary function to a unary function -/// by binding a constant value to the first argument. -/// Use the \ref bind1st accessor to create this object. -/// \ingroup FunctorObjects -template -class binder1st : public unary_function { -public: - typedef typename BinaryFunction::first_argument_type arg1_t; - typedef typename BinaryFunction::second_argument_type arg2_t; - typedef typename BinaryFunction::result_type result_t; -public: - inline binder1st (const BinaryFunction& pfn, const arg1_t& v) : m_pfn (pfn), m_Value(v) {} - inline result_t operator()(arg2_t v2) const { return (m_pfn (m_Value, v2)); } -protected: - BinaryFunction m_pfn; - arg1_t m_Value; -}; - -/// \brief Converts a binary function to a unary function -/// by binding a constant value to the second argument. -/// Use the \ref bind2nd accessor to create this object. -/// \ingroup FunctorObjects -template -class binder2nd : public unary_function { -public: - typedef typename BinaryFunction::first_argument_type arg1_t; - typedef typename BinaryFunction::second_argument_type arg2_t; - typedef typename BinaryFunction::result_type result_t; -public: - inline binder2nd (const BinaryFunction& pfn, const arg2_t& v) : m_pfn (pfn), m_Value(v) {} - inline result_t operator()(arg1_t v1) const { return (m_pfn (v1, m_Value)); } -protected: - BinaryFunction m_pfn; - arg2_t m_Value; -}; - -/// Converts \p pfn into a unary function by binding the first argument to \p v. -/// \ingroup FunctorAccessors -template -inline binder1st -bind1st (BinaryFunction pfn, typename BinaryFunction::first_argument_type v) -{ - return (binder1st (pfn, v)); -} - -/// Converts \p pfn into a unary function by binding the second argument to \p v. -/// \ingroup FunctorAccessors -template -inline binder2nd -bind2nd (BinaryFunction pfn, typename BinaryFunction::second_argument_type v) -{ - return (binder2nd (pfn, v)); -} - -//---------------------------------------------------------------------- -// Composition adapters -//---------------------------------------------------------------------- - -/// \brief Chains two unary functions together. -/// -/// When f(x) and g(x) are composed, the result is function c(x)=f(g(x)). -/// Use the \ref compose1 accessor to create this object. -/// This template is an extension, implemented by SGI STL and uSTL. -/// \ingroup FunctorObjects -/// -template -class unary_compose : public unary_function { -public: - typedef typename Operation2::argument_type arg_t; - typedef const arg_t& rcarg_t; - typedef typename Operation1::result_type result_t; -public: - inline unary_compose (const Operation1& f, const Operation2& g) : m_f(f), m_g(g) {} - inline result_t operator() (rcarg_t x) const { return m_f(m_g(x)); } -protected: - Operation1 m_f; ///< f(x), if c(x) = f(g(x)) - Operation2 m_g; ///< g(x), if c(x) = f(g(x)) -}; - -/// Creates a \ref unary_compose object whose function c(x)=f(g(x)) -/// \ingroup FunctorAccessors -template -inline unary_compose -compose1 (const Operation1& f, const Operation2& g) -{ return unary_compose(f, g); } - -/// \brief Chains two unary functions through a binary function. -/// -/// When f(x,y), g(x), and h(x) are composed, the result is function -/// c(x)=f(g(x),h(x)). Use the \ref compose2 accessor to create this -/// object. This template is an extension, implemented by SGI STL and uSTL. -/// \ingroup FunctorObjects -/// -template -class binary_compose : public unary_function { -public: - typedef typename Operation2::argument_type arg_t; - typedef const arg_t& rcarg_t; - typedef typename Operation1::result_type result_t; -public: - inline binary_compose (const Operation1& f, const Operation2& g, const Operation3& h) : m_f(f), m_g(g), m_h(h) {} - inline result_t operator() (rcarg_t x) const { return m_f(m_g(x), m_h(x)); } -protected: - Operation1 m_f; ///< f(x,y), if c(x) = f(g(x),h(x)) - Operation2 m_g; ///< g(x), if c(x) = f(g(x),h(x)) - Operation3 m_h; ///< h(x), if c(x) = f(g(x),h(x)) -}; - -/// Creates a \ref binary_compose object whose function c(x)=f(g(x),h(x)) -/// \ingroup FunctorAccessors -template -inline binary_compose -compose2 (const Operation1& f, const Operation2& g, const Operation3& h) -{ return binary_compose (f, g, h); } - -//---------------------------------------------------------------------- -// Member function adaptors -//---------------------------------------------------------------------- - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -#define MEM_FUN_T(WrapperName, ClassName, ArgType, FuncType, CallType) \ - template \ - class ClassName : public unary_function { \ - public: \ - typedef Ret (T::*func_t) FuncType; \ - public: \ - explicit inline ClassName (func_t pf) : m_pf (pf) {} \ - inline Ret operator() (ArgType p) const { return ((p CallType m_pf)()); } \ - private: \ - func_t m_pf; \ - }; \ - \ - template \ - inline ClassName WrapperName (Ret (T::*pf) FuncType) \ - { \ - return (ClassName (pf)); \ - } - -MEM_FUN_T(mem_fun, mem_fun_t, T*, (void), ->*) -MEM_FUN_T(mem_fun, const_mem_fun_t, const T*, (void) const, ->*) -MEM_FUN_T(mem_fun_ref, mem_fun_ref_t, T&, (void), .*) -MEM_FUN_T(mem_fun_ref, const_mem_fun_ref_t, const T&, (void) const, .*) - -#define EXT_MEM_FUN_T(ClassName, HostType, FuncType) \ - template \ - class ClassName : public unary_function { \ - public: \ - typedef Ret (T::*func_t)(V) FuncType; \ - public: \ - inline ClassName (HostType t, func_t pf) : m_t (t), m_pf (pf) {} \ - inline Ret operator() (V v) const { return ((m_t->*m_pf)(v)); } \ - private: \ - HostType m_t; \ - func_t m_pf; \ - }; \ - \ - template \ - inline ClassName mem_fun (HostType p, Ret (T::*pf)(V) FuncType) \ - { \ - return (ClassName (p, pf)); \ - } - -EXT_MEM_FUN_T(ext_mem_fun_t, T*, ) -EXT_MEM_FUN_T(const_ext_mem_fun_t, const T*, const) - -#endif // DOXYGEN_SHOULD_SKIP_THIS - -//---------------------------------------------------------------------- -// Member variable adaptors (uSTL extension) -//---------------------------------------------------------------------- - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -#define MEM_VAR_T(FunctorName, ArgType, VarType, BaseClass, CallImpl) \ - template \ - class FunctorName##_t : public BaseClass { \ - public: \ - typedef ArgType argument_type; \ - typedef typename Function::result_type result_type; \ - typedef VarType mem_var_ptr_t; \ - public: \ - inline FunctorName##_t (mem_var_ptr_t pv, Function pfn) : m_pv(pv), m_pfn(pfn) {} \ - inline result_type operator() CallImpl \ - private: \ - mem_var_ptr_t m_pv; \ - Function m_pfn; \ - }; \ - \ - template \ - inline FunctorName##_t \ - FunctorName (VT T::*mvp, Function pfn) \ - { \ - return (FunctorName##_t (mvp, pfn)); \ - } - -#define FUNCTOR_UNARY_BASE(ArgType) unary_function -#define FUNCTOR_BINARY_BASE(ArgType) binary_function - -#define MEM_VAR_UNARY_ARGS (argument_type p) const \ - { return (m_pfn(p.*m_pv)); } -#define MEM_VAR_BINARY_ARGS (argument_type p1, argument_type p2) const \ - { return (m_pfn(p1.*m_pv, p2.*m_pv)); } - -MEM_VAR_T(mem_var1, T&, VT T::*, FUNCTOR_UNARY_BASE(T&), MEM_VAR_UNARY_ARGS) -MEM_VAR_T(const_mem_var1, const T&, const VT T::*, FUNCTOR_UNARY_BASE(T&), MEM_VAR_UNARY_ARGS) -MEM_VAR_T(mem_var2, T&, VT T::*, FUNCTOR_BINARY_BASE(T&), MEM_VAR_BINARY_ARGS) -MEM_VAR_T(const_mem_var2, const T&, const VT T::*, FUNCTOR_BINARY_BASE(T&), MEM_VAR_BINARY_ARGS) - -#undef MEM_VAR_UNARY_ARGS -#undef MEM_VAR_BINARY_ARGS - -#endif // DOXYGEN_SHOULD_SKIP_THIS - -/// Returned functor passes member variable \p mvp reference of given object to equal\. -/// \ingroup FunctorAccessors -template -inline const_mem_var1_t >, T, VT> -mem_var_equal_to (const VT T::*mvp, const VT& v) -{ - return (const_mem_var1_t >,T,VT> (mvp, bind2nd(equal_to(), v))); -} - -/// Returned functor passes member variable \p mvp reference of given object to less\. -/// \ingroup FunctorAccessors -template -inline const_mem_var1_t >, T, VT> -mem_var_less (const VT T::*mvp, const VT& v) -{ - return (const_mem_var1_t >,T,VT> (mvp, bind2nd(less(), v))); -} - -/// Returned functor passes member variable \p mvp reference of given object to equal\. -/// \ingroup FunctorAccessors -template -inline const_mem_var2_t, T, VT> -mem_var_equal_to (const VT T::*mvp) -{ - return (const_mem_var2_t,T,VT> (mvp, equal_to())); -} - -/// Returned functor passes member variable \p mvp reference of given object to less\. -/// \ingroup FunctorAccessors -template -inline const_mem_var2_t, T, VT> -mem_var_less (const VT T::*mvp) -{ - return (const_mem_var2_t,T,VT> (mvp, less())); -} - -//---------------------------------------------------------------------- -// Dereference adaptors (uSTL extension) -//---------------------------------------------------------------------- - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -#define DEREFERENCER_T(ClassName, ArgType, BaseClass, CallImpl, FunctorKey) \ - template \ - class ClassName : public BaseClass { \ - public: \ - typedef ArgType* argument_type; \ - typedef typename Function::result_type result_type; \ - public: \ - inline ClassName (Function pfn) : m_pfn (pfn) {} \ - inline result_type operator() CallImpl \ - private: \ - Function m_pfn; \ - }; \ - \ - template \ - inline ClassName _dereference (Function pfn, FunctorKey) \ - { \ - return (ClassName (pfn)); \ - } - -#define DEREF_UNARY_ARGS (argument_type p) const \ - { return (m_pfn(*p)); } -#define DEREF_BINARY_ARGS (argument_type p1, argument_type p2) const \ - { return (m_pfn(*p1, *p2)); } - -DEREFERENCER_T(deref1_t, T, FUNCTOR_UNARY_BASE(T*), DEREF_UNARY_ARGS, FUNCTOR_UNARY_BASE(T)) -DEREFERENCER_T(const_deref1_t, const T, FUNCTOR_UNARY_BASE(const T*), DEREF_UNARY_ARGS, FUNCTOR_UNARY_BASE(const T)) -DEREFERENCER_T(deref2_t, T, FUNCTOR_BINARY_BASE(T*), DEREF_BINARY_ARGS, FUNCTOR_BINARY_BASE(T)) -DEREFERENCER_T(const_deref2_t, const T, FUNCTOR_BINARY_BASE(const T*), DEREF_BINARY_ARGS, FUNCTOR_BINARY_BASE(const T)) - -#define dereference(f) _dereference(f,f) - -#undef DEREF_UNARY_ARGS -#undef DEREF_BINARY_ARGS - -#endif - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uheap.h b/media/libdrm/mobile2/src/util/ustl-1.0/uheap.h deleted file mode 100644 index 9dfddaf63a5fdbd82d8d68e70a3dcb7c7e602070..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uheap.h +++ /dev/null @@ -1,153 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// uheap.h -// -// Implementation of STL heap algorithms. -// -// The function prototypes are copied -// exactly from the SGI version of STL documentation along with comments about -// their use. The code is NOT the same, though the functionality is. -// - -#ifndef UHEAP_H_574B9EAF271A1C107190B4D575A356C5 -#define UHEAP_H_574B9EAF271A1C107190B4D575A356C5 - -#include "uvector.h" -#include "ualgobase.h" - -namespace ustl { - -/// \brief Returns true if the given range is a heap under \p comp. -/// A heap is a sequentially encoded binary tree where for every node -/// comp(node,child1) is false and comp(node,child2) is false. -/// \ingroup HeapAlgorithms -/// \ingroup ConditionAlgorithms -/// -template -bool is_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp) -{ - RandomAccessIterator iChild (first); - for (; ++iChild < last; ++first) - if (comp (*first, *iChild) || (++iChild < last && comp (*first, *iChild))) - return (false); - return (true); -} - -/// \brief make_heap turns the range [first, last) into a heap -/// At completion, is_heap (first, last, comp) is true. -/// The algorithm is adapted from "Classic Data Structures in C++" by Timothy Budd. -/// \ingroup HeapAlgorithms -/// \ingroup SortingAlgorithms -/// -template -void make_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp) -{ - typedef typename iterator_traits::value_type value_type; - const value_type v (*first); - uoff_t iChild, iHole = 0, iEnd (distance (first, last)); - while ((iChild = 2 * iHole + 1) < iEnd) { - if (iChild + 1 < iEnd) // Pick the greater child - iChild += comp (first[iChild], first[iChild + 1]); - if (comp (first[iChild], v)) - break; // Done when parent is greater than both children. - first[iHole] = first[iChild]; - iHole = iChild; - } - if (iHole < iEnd) - first[iHole] = v; -} - -/// \brief Inserts the *--last into the preceeding range assumed to be a heap. -/// \ingroup HeapAlgorithms -/// \ingroup MutatingAlgorithms -template -void push_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp) -{ - if (last <= first) - return; - typedef typename iterator_traits::value_type value_type; - const value_type v (*--last); - while (first < last) { - RandomAccessIterator iParent = first + (distance(first, last) - 1) / 2; - if (comp (v, *iParent)) - break; - *last = *iParent; - last = iParent; - } - *last = v; -} - -/// Removes the largest element from the heap (*first) and places it at *(last-1) -/// [first, last-1) is a heap after this operation. -/// \ingroup HeapAlgorithms -/// \ingroup MutatingAlgorithms -template -void pop_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp) -{ - if (--last <= first) - return; - iter_swap (first, last); - make_heap (first, last, comp); -} - -/// Sorts heap [first, last) in descending order according to comp. -/// \ingroup HeapAlgorithms -/// \ingroup SortingAlgorithms -template -void sort_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp) -{ - for (; first < last; --last) - pop_heap (first, last, comp); -} - -#define HEAP_FN_WITH_LESS(rtype, name) \ -template \ -inline rtype name (RandomAccessIterator first, RandomAccessIterator last) \ -{ \ - typedef typename iterator_traits::value_type value_type; \ - return (name (first, last, less())); \ -} -HEAP_FN_WITH_LESS (bool, is_heap) -HEAP_FN_WITH_LESS (void, make_heap) -HEAP_FN_WITH_LESS (void, push_heap) -HEAP_FN_WITH_LESS (void, pop_heap) -HEAP_FN_WITH_LESS (void, sort_heap) -#undef HEAP_FN_WITH_LESS - -/// \class priority_queue uheap.h ustl.h -/// \ingroup Sequences -/// -/// \brief Sorted queue adapter to uSTL containers. -/// -/// Acts just like the queue adapter, but keeps the elements sorted by priority -/// specified by the given comparison operator. -/// -template , typename Comp = less > -class priority_queue { -public: - typedef Ctr base_ctr; - typedef typename base_ctr::value_type value_type; - typedef typename base_ctr::size_type size_type; - typedef typename base_ctr::const_pointer const_pointer; - typedef typename base_ctr::const_reference reference; -public: - priority_queue (const Comp& c = Comp()) : m_v(), m_c (c) {} - priority_queue (const_pointer f, const_pointer l, const Comp& c = Comp()) - : m_v (f, l), m_c (c) { make_heap (m_v.begin(), m_v.end(), m_c); } - inline size_type size (void) const { return (m_v.size()); } - inline bool empty (void) const { return (m_v.empty()); } - inline reference top (void) const { return (m_v.at(0)); } - inline void push (reference v) { m_v.push_back (v); make_heap (m_v.begin(), m_v.end(), m_c); } - inline void pop (void) { pop_heap (m_v.begin(), m_v.end()); m_v.pop_back(); } -private: - base_ctr m_v; ///< Element container. - Comp m_c; ///< Comparison functor by value. -}; - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uios.h b/media/libdrm/mobile2/src/util/ustl-1.0/uios.h deleted file mode 100644 index 6153be5126bb362b95b42785c4a92105eb958433..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uios.h +++ /dev/null @@ -1,107 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// uios.h -// -// Types used by the streams for option setting. -// - -#ifndef UIOS_H_630C16E316F7650E3A02E1C6611B789A -#define UIOS_H_630C16E316F7650E3A02E1C6611B789A - -#include "utypes.h" - -namespace ustl { - -class file_exception; - -const char endl = '\n'; ///< End of line character. -const char ends = '\0'; ///< End of string character. - -/// Defines types and constants used by all stream classes. -class ios_base { -public: - /// Used to set parameters for stringstreams - enum fmtflags { - boolalpha = (1 << 0), ///< Boolean values printed as text. - dec = (1 << 1), ///< Decimal number output. - fixed = (1 << 2), ///< Fixed-point float output. - hex = (1 << 3), ///< Hexadecimal number output. - internal = (1 << 4), - left = (1 << 5), ///< Left alignment. - oct = (1 << 6), ///< Octal number output. - right = (1 << 7), ///< Right alignment. - scientific = (1 << 8), ///< Scientific float format. - showbase = (1 << 9), ///< Add 0x or 0 prefixes on hex and octal numbers. - showpoint = (1 << 10), ///< Print decimal point. - showpos = (1 << 11), - skipws = (1 << 12), ///< Skip whitespace when reading. - unitbuf = (1 << 13), - uppercase = (1 << 14), - adjustfield = (1 << 15), - basefield = (1 << 16), - floatfield = (1 << 17) - }; - /// For file-based streams, specifies fd mode. - enum openmode_bits { - in = (1 << 0), - out = (1 << 1), - app = (1 << 2), - ate = (1 << 3), - binary = (1 << 4), - trunc = (1 << 5), - #ifndef DOXYGEN_SHOULD_SKIP_THIS - nonblock= (1 << 6), - nocreate= (1 << 7), - noctty = (1 << 8), - nombits = 9 - #endif - }; - /// Seek directions, equivalent to SEEK_SET, SEEK_CUR, and SEEK_END. - enum seekdir { - beg, - cur, - end - }; - /// I/O state bitmasks. - enum iostate_bits { - goodbit = 0, - badbit = (1 << 0), - eofbit = (1 << 1), - failbit = (1 << 2), - #ifndef DOXYGEN_SHOULD_SKIP_THIS - nbadbits = 3, - allbadbits = 0x7 - #endif - }; - - typedef uint32_t openmode; ///< Holds openmode_bits. - typedef uint32_t iostate; ///< Holds iostate_bits for a file stream. - typedef file_exception failure; ///< Thrown by fstream on errors. - - static const char c_DefaultDelimiters [16]; ///< Default word delimiters for stringstreams. -public: - inline ios_base (void) : m_State (goodbit), m_Exceptions (goodbit) {} - inline iostate rdstate (void) const { return (m_State); } - inline bool bad (void) const { return (rdstate() & badbit); } - inline bool good (void) const { return (rdstate() == goodbit); } - inline bool fail (void) const { return (rdstate() & (badbit | failbit)); } - inline bool eof (void) const { return (rdstate() & eofbit); } - inline bool operator! (void) const { return (fail()); } - inline void clear (iostate v = goodbit) { m_State = v; } - inline void setstate (iostate v) { m_State |= v; } - inline iostate exceptions (void) const { return (m_Exceptions); } - inline iostate exceptions (iostate v) { return (m_Exceptions = v); } -protected: - inline bool set_and_throw (iostate v) { setstate(v); return (exceptions() & v); } -private: - uint16_t m_State; ///< Open state, using ios::iostate_bits. - uint16_t m_Exceptions; ///< Exception flags, using ios::iostate_bits. -}; - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uiosfunc.h b/media/libdrm/mobile2/src/util/ustl-1.0/uiosfunc.h deleted file mode 100644 index fe26ed1543ba8cefe7d30865cbd59829682955cc..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uiosfunc.h +++ /dev/null @@ -1,103 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// uiosfunc.h -// - -#ifndef UIOSFUNC_H_730C16E316F7650E3A02E1C6611B789A -#define UIOSFUNC_H_730C16E316F7650E3A02E1C6611B789A - -#include "sostream.h" - -namespace ustl { - -class ios : public ios_base { -public: - /// \class align uiosfunc.h ustl.h - /// \ingroup StreamFunctors - /// \brief Stream functor to allow inline align() calls. - /// - /// Example: os << ios::align(sizeof(uint16_t)); - /// - class align { - public: - inline explicit align (size_t grain = c_DefaultAlignment) : m_Grain(grain) {} - inline istream& apply (istream& is) const { is.align (m_Grain); return (is); } - inline ostream& apply (ostream& os) const { os.align (m_Grain); return (os); } - inline size_t stream_size (void) const { return (m_Grain - 1); } - private: - const size_t m_Grain; - }; - - /// \class talign uiosfunc.h ustl.h - /// \ingroup StreamFunctors - /// \brief Stream functor to allow type-based alignment. - template - class talign : public align { - public: - inline explicit talign (void) : align (alignof (T())) {} - }; - - /// \class skip uiosfunc.h ustl.h - /// \ingroup StreamFunctors - /// \brief Stream functor to allow inline skip() calls. - /// - /// Example: os << ios::skip(sizeof(uint16_t)); - /// - class skip { - public: - inline explicit skip (size_t nBytes) : m_nBytes(nBytes) {} - inline istream& apply (istream& is) const { is.skip (m_nBytes); return (is); } - inline ostream& apply (ostream& os) const { os.skip (m_nBytes); return (os); } - inline size_t stream_size (void) const { return (m_nBytes); } - private: - const size_t m_nBytes; - }; - - /// \class width uiosfunc.h ustl.h - /// \ingroup StreamFunctors - /// \brief Stream functor to allow inline set_width() calls. - /// - /// Example: os << ios::width(15); - /// - class width { - public: - inline explicit width (size_t nBytes) : m_nBytes(nBytes) {} - inline ostringstream& apply (ostringstream& os) const { os.set_width (m_nBytes); return (os); } - private: - const size_t m_nBytes; - }; - - /// \class base uiosfunc.h ustl.h - /// \ingroup StreamFunctors - /// \brief Stream functor to allow inline set_base() calls. - /// - /// Example: os << ios::base(15); - /// - class base { - public: - inline explicit base (size_t n) : m_Base(n) {} - inline ostringstream& apply (ostringstream& os) const { os.set_base (m_Base); return (os); } - private: - const size_t m_Base; - }; -}; - -inline istream& operator>> (istream& is, const ios::skip& op) { return (op.apply (is)); } -inline ostream& operator<< (ostream& os, const ios::skip& op) { return (op.apply (os)); } -inline size_t stream_size_of (const ios::skip& op) { return (op.stream_size()); } -inline istream& operator>> (istream& is, const ios::align& op) { return (op.apply (is)); } -inline ostream& operator<< (ostream& os, const ios::align& op) { return (op.apply (os)); } -inline size_t stream_size_of (const ios::align& op) { return (op.stream_size()); } -inline ostringstream& operator<< (ostringstream& os, const ios::width& op) { return (op.apply (os)); } -inline ostringstream& operator<< (ostringstream& os, const ios::base& op) { return (op.apply (os)); } - -} // namespace ustl - -CAST_STREAMABLE(ustl::ios::fmtflags, uint32_t) -CAST_STREAMABLE(ustl::ios::seekdir, uint32_t) - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uiterator.h b/media/libdrm/mobile2/src/util/ustl-1.0/uiterator.h deleted file mode 100644 index 48c0d2d879867d5df684234a8771c3252a6d0629..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uiterator.h +++ /dev/null @@ -1,268 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -/// \file uiterator.h -/// \brief Contains various iterator adapters. -// - -#ifndef UITERATOR_H_5BCA176C7214A30F2069E2614D2DC226 -#define UITERATOR_H_5BCA176C7214A30F2069E2614D2DC226 - -#include "uassert.h" -#include "utypes.h" - -namespace ustl { - -//---------------------------------------------------------------------- - -/// \struct iterator_traits uiterator.h ustl.h -/// \brief Contains the type traits of \p Iterator -/// -template -struct iterator_traits { - typedef typename Iterator::value_type value_type; - typedef typename Iterator::difference_type difference_type; - typedef typename Iterator::pointer pointer; - typedef typename Iterator::reference reference; -}; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -template -struct iterator_traits { - typedef T value_type; - typedef ptrdiff_t difference_type; - typedef const T* const_pointer; - typedef T* pointer; - typedef T& reference; -}; - -template -struct iterator_traits { - typedef T value_type; - typedef ptrdiff_t difference_type; - typedef const T* const_pointer; - typedef const T* pointer; - typedef const T& reference; -}; - -template <> -struct iterator_traits { - typedef uint8_t value_type; - typedef ptrdiff_t difference_type; - typedef const void* const_pointer; - typedef void* pointer; - typedef value_type& reference; -}; - -template <> -struct iterator_traits { - typedef uint8_t value_type; - typedef ptrdiff_t difference_type; - typedef const void* const_pointer; - typedef const void* pointer; - typedef const value_type& reference; -}; - -#endif - -//---------------------------------------------------------------------- - -/// \class reverse_iterator uiterator.h ustl.h -/// \ingroup IteratorAdaptors -/// \brief Wraps \p Iterator to behave in an exactly opposite manner. -/// -template -class reverse_iterator { -public: - typedef typename iterator_traits::value_type value_type; - typedef typename iterator_traits::difference_type difference_type; - typedef typename iterator_traits::pointer pointer; - typedef typename iterator_traits::reference reference; -public: - reverse_iterator (void) : m_i() {} - explicit reverse_iterator (Iterator iter) : m_i (iter) {} - inline bool operator== (const reverse_iterator& iter) const { return (m_i == iter.m_i); } - inline bool operator< (const reverse_iterator& iter) const { return (iter.m_i < m_i); } - inline Iterator base (void) const { return (m_i); } - inline reference operator* (void) const { Iterator prev (m_i); --prev; return (*prev); } - inline pointer operator-> (void) const { return (&(operator*())); } - inline reverse_iterator& operator++ (void) { -- m_i; return (*this); } - inline reverse_iterator& operator-- (void) { ++ m_i; return (*this); } - inline reverse_iterator operator++ (int) { reverse_iterator prev (*this); -- m_i; return (prev); } - inline reverse_iterator operator-- (int) { reverse_iterator prev (*this); ++ m_i; return (prev); } - inline reverse_iterator& operator+= (size_t n) { m_i -= n; return (*this); } - inline reverse_iterator& operator-= (size_t n) { m_i += n; return (*this); } - inline reverse_iterator operator+ (size_t n) const { return (reverse_iterator (m_i - n)); } - inline reverse_iterator operator- (size_t n) const { return (reverse_iterator (m_i + n)); } - inline reference operator[] (uoff_t n) const { return (*(*this + n)); } - inline difference_type operator- (const reverse_iterator& i) const { return (distance (m_i, i.m_i)); } -protected: - Iterator m_i; -}; - -//---------------------------------------------------------------------- - -/// \class insert_iterator uiterator.h ustl.h -/// \ingroup IteratorAdaptors -/// \brief Calls insert on bound container for each assignment. -/// -template -class insert_iterator { -public: - typedef typename Container::value_type value_type; - typedef typename Container::difference_type difference_type; - typedef typename Container::pointer pointer; - typedef typename Container::reference reference; - typedef typename Container::iterator iterator; -public: - explicit insert_iterator (Container& ctr, iterator ip) : m_rCtr (ctr), m_ip (ip) {} - inline insert_iterator& operator= (typename Container::const_reference v) - { m_ip = m_rCtr.insert (m_ip, v); return (*this); } - inline insert_iterator& operator* (void) { return (*this); } - inline insert_iterator& operator++ (void) { ++ m_ip; return (*this); } - inline insert_iterator operator++ (int) { insert_iterator prev (*this); ++ m_ip; return (*this); } -protected: - Container& m_rCtr; - iterator m_ip; -}; - -/// Returns the insert_iterator for \p ctr. -template -inline insert_iterator inserter (Container& ctr, typename Container::iterator ip) -{ - return (insert_iterator (ctr, ip)); -} - -//---------------------------------------------------------------------- - -/// \class back_insert_iterator uiterator.h ustl.h -/// \ingroup IteratorAdaptors -/// \brief Calls push_back on bound container for each assignment. -/// -template -class back_insert_iterator { -public: - typedef typename Container::value_type value_type; - typedef typename Container::difference_type difference_type; - typedef typename Container::pointer pointer; - typedef typename Container::reference reference; -public: - explicit back_insert_iterator (Container& ctr) : m_rCtr (ctr) {} - inline back_insert_iterator& operator= (typename Container::const_reference v) - { m_rCtr.push_back (v); return (*this); } - inline back_insert_iterator& operator* (void) { return (*this); } - inline back_insert_iterator& operator++ (void) { return (*this); } - inline back_insert_iterator operator++ (int) { return (*this); } -protected: - Container& m_rCtr; -}; - -/// Returns the back_insert_iterator for \p ctr. -template -inline back_insert_iterator back_inserter (Container& ctr) -{ - return (back_insert_iterator (ctr)); -} - -//---------------------------------------------------------------------- - -/// \class index_iterate uiterator.h ustl.h -/// \ingroup IteratorAdaptors -/// -/// \brief Allows iteration through an index container. -/// -/// Converts an iterator into a container of uoff_t indexes to an -/// iterator of iterators into another container. -/// -template -class index_iterate { -public: - typedef RandomAccessIterator value_type; - typedef ptrdiff_t difference_type; - typedef RandomAccessIterator* pointer; - typedef RandomAccessIterator reference; -public: - index_iterate (void) : m_Base(), m_i() {} - index_iterate (RandomAccessIterator ibase, IndexIterator iindex) : m_Base (ibase), m_i (iindex) {} - inline bool operator== (const index_iterate& i) const { return (m_i == i.m_i); } - inline bool operator< (const index_iterate& i) const { return (m_i < i.m_i); } - inline bool operator== (const RandomAccessIterator& i) const { return (m_Base == i); } - inline bool operator< (const RandomAccessIterator& i) const { return (m_Base < i); } - inline IndexIterator base (void) const { return (m_i); } - inline reference operator* (void) const { return (advance(m_Base, *m_i)); } - inline pointer operator-> (void) const { return (&(operator*())); } - inline index_iterate& operator++ (void) { ++ m_i; return (*this); } - inline index_iterate& operator-- (void) { -- m_i; return (*this); } - inline index_iterate operator++ (int) { index_iterate prev (*this); ++ m_i; return (prev); } - inline index_iterate operator-- (int) { index_iterate prev (*this); -- m_i; return (prev); } - inline index_iterate& operator+= (size_t n) { m_i += n; return (*this); } - inline index_iterate& operator-= (size_t n) { m_i -= n; return (*this); } - inline index_iterate operator+ (size_t n) const { return (index_iterate (m_Base, m_i + n)); } - inline index_iterate operator- (size_t n) const { return (index_iterate (m_Base, m_i - n)); } - inline reference operator[] (uoff_t n) const { return (*(*this + n)); } - inline difference_type operator- (const index_iterate& i) const { return (distance (m_i, i.m_i)); } -private: - RandomAccessIterator m_Base; - IndexIterator m_i; -}; - -/// Returns an index_iterate for \p ibase over \p iindex. -template -inline index_iterate index_iterator (RandomAccessIterator ibase, IndexIterator iindex) -{ - return (index_iterate (ibase, iindex)); -} - -/// Converts the indexes in \p xc to iterators in \p ic of base \p ibase. -template -inline void indexv_to_iteratorv (typename IteratorContainer::value_type ibase, const IndexContainer& xc, IteratorContainer& ic) -{ - ic.resize (xc.size()); - copy_n (index_iterator (ibase, xc.begin()), xc.size(), ic.begin()); -} - -//---------------------------------------------------------------------- - -/// Converts the given const_iterator into an iterator. -/// -template -inline typename Container::iterator unconst (typename Container::const_iterator i, Container& ctr) -{ - const Container& cctr = ctr; - return (ctr.begin() + (i - cctr.begin())); -} - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -#define IBYI(Iter1, Iter2, Ctr1, Ctr2) \ -template \ -inline typename Container2::Iter2 ibyi (typename Container1::Iter1 idx, Ctr1& ctr1, Ctr2& ctr2) \ -{ \ - assert (ctr1.size() == ctr2.size()); \ - return (ctr2.begin() + (idx - ctr1.begin())); \ -} - -IBYI(const_iterator, const_iterator, const Container1, const Container2) -IBYI(iterator, iterator, Container1, Container2) -IBYI(const_iterator, iterator, const Container1, Container2) -IBYI(iterator, const_iterator, Container1, const Container2) - -#else // DOXYGEN - -#error This declaration is for doxygen only; it is not compiled. - -/// Converts a const_iterator in one container into a const_iterator in another container. -template -inline typename Container2::iterator ibyi (typename Container1::iterator idx, Container1& ctr1, Container2& ctr2) {} - -#endif // DOXYGEN - -//---------------------------------------------------------------------- - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ulaalgo.h b/media/libdrm/mobile2/src/util/ustl-1.0/ulaalgo.h deleted file mode 100644 index 1efc9770efd288eedb78c30c00c531905a8d4ea2..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ulaalgo.h +++ /dev/null @@ -1,223 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ulaalgo.h -// - -#ifndef ULAALGO_H_2E403D182E83FB596AFB800E68B255A1 -#define ULAALGO_H_2E403D182E83FB596AFB800E68B255A1 - -#include "umatrix.h" -#include "simd.h" - -namespace ustl { - -/// \brief Creates an identity matrix in \p m -/// \ingroup NumericAlgorithms -template -void load_identity (matrix& m) -{ - fill_n (m.begin(), NX * NY, 0); - for (typename matrix::iterator i = m.begin(); i < m.end(); i += NX + 1) - *i = 1; -} - -/// \brief Multiplies two matrices -/// \ingroup NumericAlgorithms -template -matrix operator* (const matrix& m1, const matrix& m2) -{ - matrix mr; - for (uoff_t ry = 0; ry < NY; ++ ry) { - for (uoff_t rx = 0; rx < NY; ++ rx) { - T dpv (0); - for (uoff_t x = 0; x < NX; ++ x) - dpv += m1[ry][x] * m2[x][rx]; - mr[ry][rx] = dpv; - } - } - return (mr); -} - -/// \brief Transforms vector \p t with matrix \p m -/// \ingroup NumericAlgorithms -template -tuple operator* (const tuple& t, const matrix& m) -{ - tuple tr; - for (uoff_t x = 0; x < NX; ++ x) { - T dpv (0); - for (uoff_t y = 0; y < NY; ++ y) - dpv += t[y] * m[y][x]; - tr[x] = dpv; - } - return (tr); -} - -/// \brief Transposes (exchanges rows and columns) matrix \p m. -/// \ingroup NumericAlgorithms -template -void transpose (matrix& m) -{ - for (uoff_t x = 0; x < N; ++ x) - for (uoff_t y = x; y < N; ++ y) - swap (m[x][y], m[y][x]); -} - -#if WANT_UNROLLED_COPY - -#if CPU_HAS_SSE - -#if linux // Non-linux gcc versions (BSD, Solaris) can't handle "x" constraint and provide no alternative. -template <> -inline void load_identity (matrix<4,4,float>& m) -{ - asm ( - "movaps %4, %%xmm1 \n\t" // 1 0 0 0 - "movups %4, %0 \n\t" // 1 0 0 0 - "shufps $0xB1,%%xmm1,%%xmm1 \n\t" // 0 1 0 0 - "movups %%xmm1, %1 \n\t" // 0 1 0 0 - "shufps $0x4F,%4,%%xmm1 \n\t" // 0 0 1 0 - "shufps $0x1B,%4,%4 \n\t" // 0 0 0 1 - "movups %%xmm1, %2 \n\t" // 0 0 1 0 - "movups %4, %3" // 0 0 0 1 - : "=m"(m[0][0]), "=m"(m[1][0]), "=m"(m[2][0]), "=m"(m[3][0]) - : "x"(1.0f) - : "xmm1" - ); -} -#endif - -inline void _sse_load_matrix (const float* m) -{ - asm ( - "movups %0, %%xmm4 \n\t" // xmm4 = m[1 2 3 4] - "movups %1, %%xmm5 \n\t" // xmm5 = m[1 2 3 4] - "movups %2, %%xmm6 \n\t" // xmm6 = m[1 2 3 4] - "movups %3, %%xmm7" // xmm7 = m[1 2 3 4] - : : "m"(m[0]), "m"(m[4]), "m"(m[8]), "m"(m[12]) - : "xmm4", "xmm5", "xmm6", "xmm7" - ); -} - -inline void _sse_transform_to_vector (float* result) -{ - asm ( - "movaps %%xmm0, %%xmm1 \n\t" // xmm1 = t[0 1 2 3] - "movaps %%xmm0, %%xmm2 \n\t" // xmm1 = t[0 1 2 3] - "movaps %%xmm0, %%xmm3 \n\t" // xmm1 = t[0 1 2 3] - "shufps $0x00, %%xmm0, %%xmm0 \n\t" // xmm0 = t[0 0 0 0] - "shufps $0x66, %%xmm1, %%xmm1 \n\t" // xmm1 = t[1 1 1 1] - "shufps $0xAA, %%xmm2, %%xmm2 \n\t" // xmm2 = t[2 2 2 2] - "shufps $0xFF, %%xmm3, %%xmm3 \n\t" // xmm3 = t[3 3 3 3] - "mulps %%xmm4, %%xmm0 \n\t" // xmm0 = t[0 0 0 0] * m[0 1 2 3] - "mulps %%xmm5, %%xmm1 \n\t" // xmm1 = t[1 1 1 1] * m[0 1 2 3] - "addps %%xmm1, %%xmm0 \n\t" // xmm0 = xmm0 + xmm1 - "mulps %%xmm6, %%xmm2 \n\t" // xmm2 = t[2 2 2 2] * m[0 1 2 3] - "mulps %%xmm7, %%xmm3 \n\t" // xmm3 = t[3 3 3 3] * m[0 1 2 3] - "addps %%xmm3, %%xmm2 \n\t" // xmm2 = xmm2 + xmm3 - "addps %%xmm2, %%xmm0 \n\t" // xmm0 = result - "movups %%xmm0, %0" - : "=m"(result[0]) : - : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" - ); -} - -template <> -tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m) -{ - tuple<4,float> result; - _sse_load_matrix (m.begin()); - asm ("movups %0, %%xmm0" : : "m"(t[0]) : "xmm0"); - _sse_transform_to_vector (result.begin()); - return (result); -} - -template <> -matrix<4,4,float> operator* (const matrix<4,4,float>& m1, const matrix<4,4,float>& m2) -{ - matrix<4,4,float> result; - _sse_load_matrix (m2.begin()); - for (uoff_t r = 0; r < 4; ++ r) { - asm ("movups %0, %%xmm0" : : "m"(m1[r][0]) : "xmm0"); - _sse_transform_to_vector (result[r]); - } - return (result); -} - -#elif CPU_HAS_3DNOW - -/// Specialization for 4-component vector transform, the slow part of 3D graphics. -template <> -tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m) -{ - tuple<4,float> result; - // This is taken from "AMD Athlon Code Optimization Guide" from AMD. 18 cycles! - // If you are writing a 3D engine, you may want to copy it instead of calling it - // because of the femms instruction at the end, which takes 2 cycles. - asm ( - "movq %2, %%mm0 \n\t" // y | x - "movq %3, %%mm1 \n\t" // w | z - "movq %%mm0, %%mm2 \n\t" // y | x - "movq %4, %%mm3 \n\t" // m[0][1] | m[0][0] - "punpckldq %%mm0, %%mm0 \n\t" // x | x - "movq %6, %%mm4 \n\t" // m[1][1] | m[1][0] - "pfmul %%mm0, %%mm3 \n\t" // x*m[0][1] | x*m[0][0] - "punpckhdq %%mm2, %%mm2 \n\t" // y | y - "pfmul %%mm2, %%mm4 \n\t" // y*m[1][1] | y*m[1][0] - "movq %5, %%mm5 \n\t" // m[0][3] | m[0][2] - "movq %7, %%mm7 \n\t" // m[1][3] | m[1][2] - "movq %%mm1, %%mm6 \n\t" // w | z - "pfmul %%mm0, %%mm5 \n\t" // x*m[0][3] | v0>x*m[0][2] - "movq %8, %%mm0 \n\t" // m[2][1] | m[2][0] - "punpckldq %%mm1, %%mm1 \n\t" // z | z - "pfmul %%mm2, %%mm7 \n\t" // y*m[1][3] | y*m[1][2] - "movq %9, %%mm2 \n\t" // m[2][3] | m[2][2] - "pfmul %%mm1, %%mm0 \n\t" // z*m[2][1] | z*m[2][0] - "pfadd %%mm4, %%mm3 \n\t" // x*m[0][1]+y*m[1][1] | x*m[0][0]+y*m[1][0] - "movq %10, %%mm4 \n\t" // m[3][1] | m[3][0] - "pfmul %%mm1, %%mm2 \n\t" // z*m[2][3] | z*m[2][2] - "pfadd %%mm7, %%mm5 \n\t" // x*m[0][3]+y*m[1][3] | x*m[0][2]+y*m[1][2] - "movq %11, %%mm1 \n\t" // m[3][3] | m[3][2] - "punpckhdq %%mm6, %%mm6 \n\t" // w | w - "pfadd %%mm0, %%mm3 \n\t" // x*m[0][1]+y*m[1][1]+z*m[2][1] | x*m[0][0]+y*m[1][0]+z*m[2][0] - "pfmul %%mm6, %%mm4 \n\t" // w*m[3][1] | w*m[3][0] - "pfmul %%mm6, %%mm1 \n\t" // w*m[3][3] | w*m[3][2] - "pfadd %%mm2, %%mm5 \n\t" // x*m[0][3]+y*m[1][3]+z*m[2][3] | x*m[0][2]+y*m[1][2]+z*m[2][2] - "pfadd %%mm4, %%mm3 \n\t" // x*m[0][1]+y*m[1][1]+z*m[2][1]+w*m[3][1] | x*m[0][0]+y*m[1][0]+z*m[2][0]+w*m[3][0] - "movq %%mm3, %0 \n\t" // store result->y | result->x - "pfadd %%mm1, %%mm5 \n\t" // x*m[0][3]+y*m[1][3]+z*m[2][3]+w*m[3][3] | x*m[0][2]+y*m[1][2]+z*m[2][2]+w*m[3][2] - "movq %%mm5, %1" // store result->w | result->z - : "=m"(result[0]), "=m"(result[2]) - : "m"(t[0]), "m"(t[2]), - "m"(m[0][0]), "m"(m[0][2]), - "m"(m[1][0]), "m"(m[1][2]), - "m"(m[2][0]), "m"(m[2][2]), - "m"(m[3][0]), "m"(m[3][2]) - : "mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7" - ); - simd::reset_mmx(); - return (result); -} - -#else // If no processor extensions, just unroll the multiplication - -/// Specialization for 4-component vector transform, the slow part of 3D graphics. -template <> -tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m) -{ - tuple<4,float> tr; - for (uoff_t i = 0; i < 4; ++ i) - tr[i] = t[0] * m[0][i] + t[1] * m[1][i] + t[2] * m[2][i] + t[3] * m[3][i]; - return (tr); -} - -#endif // CPU_HAS_3DNOW -#endif // WANT_UNROLLED_COPY - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ulimits.h b/media/libdrm/mobile2/src/util/ustl-1.0/ulimits.h deleted file mode 100644 index 85f1db18ce93ec8236c7349275dbd3e239421279..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ulimits.h +++ /dev/null @@ -1,108 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ulimits.h -// - -#ifndef ULIMITS_H_1C2192EA3821E0811BBAF86B0F048364 -#define ULIMITS_H_1C2192EA3821E0811BBAF86B0F048364 - -#include "utypes.h" -#include - -namespace ustl { - -// Android -#ifndef UINTPTR_MAX -#define UINTPTR_MAX UINT32_MAX -#endif - -#ifndef UINT32_MAX -#define UINT32_MAX (0xffffffff) -#endif - -/// \class numeric_limits ulimits.h ustl.h -/// \brief Defines numeric limits for a type. -/// -template -struct numeric_limits { - /// Returns the minimum value for type T. - static inline T min (void) { return (T(0)); } - /// Returns the minimum value for type T. - static inline T max (void) { return (T(0)); } - static const bool is_signed = false; ///< True if the type is signed. - static const bool is_integer = false; ///< True if stores an exact value. - static const bool is_integral = false; ///< True if fixed size and cast-copyable. -}; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -template -struct numeric_limits { - static inline T* min (void) { return (NULL); } - static inline T* max (void) { return (UINTPTR_MAX); } - static const bool is_signed = false; - static const bool is_integer = true; - static const bool is_integral = true; -}; - -#define _NUMERIC_LIMITS(type, minVal, maxVal, bSigned, bInteger, bIntegral) \ -template <> \ -struct numeric_limits { \ - static inline type min (void) { return (minVal); } \ - static inline type max (void) { return (maxVal); } \ - static const bool is_signed = bSigned; \ - static const bool is_integer = bInteger; \ - static const bool is_integral = bIntegral; \ -} - -//-------------------------------------------------------------------------------------- -// type min max signed integer integral -//-------------------------------------------------------------------------------------- -_NUMERIC_LIMITS (bool, false, true, false, true, true); -_NUMERIC_LIMITS (char, SCHAR_MIN, SCHAR_MAX, true, true, true); -_NUMERIC_LIMITS (int, INT_MIN, INT_MAX, true, true, true); -_NUMERIC_LIMITS (short, SHRT_MIN, SHRT_MAX, true, true, true); -_NUMERIC_LIMITS (long, LONG_MIN, LONG_MAX, true, true, true); -#if HAVE_THREE_CHAR_TYPES -_NUMERIC_LIMITS (signed char, SCHAR_MIN, SCHAR_MAX, true, true, true); -#endif -_NUMERIC_LIMITS (unsigned char, 0, UCHAR_MAX, false, true, true); -_NUMERIC_LIMITS (unsigned int, 0, UINT_MAX, false, true, true); -_NUMERIC_LIMITS (unsigned short,0, USHRT_MAX, false, true, true); -_NUMERIC_LIMITS (unsigned long, 0, ULONG_MAX, false, true, true); -_NUMERIC_LIMITS (wchar_t, 0, WCHAR_MAX, false, true, true); -_NUMERIC_LIMITS (float, FLT_MIN, FLT_MAX, true, false, true); -_NUMERIC_LIMITS (double, DBL_MIN, DBL_MAX, true, false, true); -_NUMERIC_LIMITS (long double, LDBL_MIN, LDBL_MAX, true, false, true); -#ifdef HAVE_LONG_LONG -_NUMERIC_LIMITS (long long, LLONG_MIN, LLONG_MAX, true, true, true); -_NUMERIC_LIMITS (unsigned long long, 0, ULLONG_MAX, false, true, true); -#endif -//-------------------------------------------------------------------------------------- - -#endif // DOXYGEN_SHOULD_SKIP_THIS - -/// Macro for defining numeric_limits specializations -#define NUMERIC_LIMITS(type, minVal, maxVal, bSigned, bInteger, bIntegral) \ -namespace ustl { _NUMERIC_LIMITS (type, minVal, maxVal, bSigned, bInteger, bIntegral); } - -/// Returns the recommended stream alignment for type \p T. Override with ALIGNOF. -template -inline size_t alignof (const T&) -{ - if (numeric_limits::is_integral) - return (__alignof__(T)); - return (4); -} - -#define ALIGNOF(type,grain) \ -namespace ustl { \ - template <> inline size_t alignof (const type&) { return (grain); } } - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ulist.h b/media/libdrm/mobile2/src/util/ustl-1.0/ulist.h deleted file mode 100644 index 842bbde2a6a67cbc2a314e7ee4fee440331cd447..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ulist.h +++ /dev/null @@ -1,78 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ulist.h -// - -#ifndef ULIST_H_54E3B510498982C87A0A1E1932E6729D -#define ULIST_H_54E3B510498982C87A0A1E1932E6729D - -#include "uvector.h" -#include "uctralgo.h" - -namespace ustl { - -/// \class list ulist.h ustl.h -/// \ingroup Sequences -/// -/// \brief Linked list, defined as an alias to \ref vector. -/// -template -class list : public vector { -public: - typedef typename vector::size_type size_type; - typedef typename vector::iterator iterator; - typedef typename vector::const_iterator const_iterator; - typedef typename vector::reference reference; - typedef typename vector::const_reference const_reference; -public: - inline list (void) : vector () {} - inline explicit list (size_type n) : vector (n) {} - inline list (size_type n, const T& v) : vector (n, v) {} - inline list (const list& v) : vector (v) {} - inline list (const_iterator i1, const_iterator i2) : vector (i1, i2) {} - inline size_type size (void) const { return (vector::size()); } - inline iterator begin (void) { return (vector::begin()); } - inline const_iterator begin (void) const { return (vector::begin()); } - inline iterator end (void) { return (vector::end()); } - inline const_iterator end (void) const { return (vector::end()); } - inline void push_front (const T& v) { insert (begin(), v); } - inline void pop_front (void) { erase (begin()); } - inline const_reference front (void) const { return (*begin()); } - inline reference front (void) { return (*begin()); } - inline void remove (const T& v) { ::ustl::remove (*this, v); } - inline void unique (void) { ::ustl::unique (*this); } - inline void sort (void) { ::ustl::sort (*this); } - void merge (list& l); - void splice (iterator ip, list& l, iterator first = NULL, iterator last = NULL); -}; - -/// Merges the contents with \p l. Assumes both lists are sorted. -template -void list::merge (list& l) -{ - list::resize (size() + l.size()); - iterator me = merge (begin(), end(), l.begin(), l.end(), begin()); - list::resize (distance (begin(), me)); -} - -/// Moves the range [first, last) from \p l to this list at \p ip. -template -void list::splice (iterator ip, list& l, iterator first, iterator last) -{ - if (!first) - first = l.begin(); - if (!last) - last = l.end(); - insert (ip, first, last); - l.erase (first, last); -} - -#define deque list ///< list has all the functionality provided by deque - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/umap.h b/media/libdrm/mobile2/src/util/ustl-1.0/umap.h deleted file mode 100644 index 938c5073652772d98b7a27d6165af654f89a0f39..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/umap.h +++ /dev/null @@ -1,165 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// umap.h -// - -#ifndef UMAP_H_45643F516E02A87A3DCEA5024052A6F5 -#define UMAP_H_45643F516E02A87A3DCEA5024052A6F5 - -#include "uassert.h" -#include "ufunction.h" -#include "uvector.h" - -namespace ustl { - -/// \class map umap.h ustl.h -/// \ingroup AssociativeContainers -/// -/// \brief A sorted associative container of pair -/// -template -class map : public vector > { -public: - typedef K key_type; - typedef V data_type; - typedef const K& const_key_ref; - typedef const V& const_data_ref; - typedef const map& rcself_t; - typedef vector > base_class; - typedef typename base_class::value_type value_type; - typedef typename base_class::size_type size_type; - typedef typename base_class::pointer pointer; - typedef typename base_class::const_pointer const_pointer; - typedef typename base_class::reference reference; - typedef typename base_class::const_reference const_reference; - typedef typename base_class::const_iterator const_iterator; - typedef typename base_class::iterator iterator; - typedef typename base_class::reverse_iterator reverse_iterator; - typedef typename base_class::const_reverse_iterator const_reverse_iterator; - typedef pair const_range_t; - typedef pair range_t; -public: - inline map (void) : vector > () {} - explicit inline map (size_type n) : vector > (n) {} - inline map (rcself_t v) : vector > (v) {} - inline map (const_iterator i1, const_iterator i2) : vector >() { insert (i1, i2); } - inline rcself_t operator= (rcself_t v) { base_class::operator= (v); return (*this); } - inline const_data_ref operator[] (const_key_ref i) const; - data_type& operator[] (const_key_ref i); - inline size_type size (void) const { return (base_class::size()); } - inline iterator begin (void) { return (base_class::begin()); } - inline const_iterator begin (void) const { return (base_class::begin()); } - inline iterator end (void) { return (base_class::end()); } - inline const_iterator end (void) const { return (base_class::end()); } - inline void assign (const_iterator i1, const_iterator i2) { clear(); insert (i1, i2); } - inline void push_back (const_reference v) { insert (v); } - inline const_iterator find (const_key_ref k) const; - inline iterator find (const_key_ref k) { return (const_cast (const_cast(*this).find (k))); } - inline const_iterator find_data (const_data_ref v, const_iterator first = NULL, const_iterator last = NULL) const; - inline iterator find_data (const_data_ref v, iterator first = NULL, iterator last = NULL); - iterator insert (const_reference v); - void insert (const_iterator i1, const_iterator i2); - inline void erase (const_key_ref k); - inline iterator erase (iterator ep) { return (base_class::erase (ep)); } - inline iterator erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); } - inline void clear (void) { base_class::clear(); } -private: - const_iterator lower_bound (const_key_ref k) const; - inline iterator lower_bound (const_key_ref k) { return (const_cast(const_cast(*this).lower_bound (k))); } -}; - -template -typename map::const_iterator map::lower_bound (const_key_ref k) const -{ - const_iterator first (begin()), last (end()); - while (first != last) { - const_iterator mid = advance (first, distance (first,last) / 2); - if (mid->first < k) - first = advance (mid, 1); - else - last = mid; - } - return (first); -} - -/// Returns the pair where K = \p k. -template -inline typename map::const_iterator map::find (const_key_ref k) const -{ - const_iterator i = lower_bound (k); - return ((i < end() && k < i->first) ? end() : i); -} - -/// Returns the pair where V = \p v, occuring in range [first,last). -template -inline typename map::const_iterator map::find_data (const_data_ref v, const_iterator first, const_iterator last) const -{ - if (!first) first = begin(); - if (!last) last = end(); - for (; first != last && first->second != v; ++first); - return (first); -} - -/// Returns the pair where V = \p v, occuring in range [first,last). -template -inline typename map::iterator map::find_data (const_data_ref v, iterator first, iterator last) -{ - return (const_cast (find_data (v, const_cast(first), const_cast(last)))); -} - -/// Returns data associated with key \p k. -template -inline const typename map::data_type& map::operator[] (const_key_ref k) const -{ - assert (find(k) != end() && "operator[] const can not insert non-existent keys"); - return (find(k)->second); -} - -/// Returns data associated with key \p k. -template -typename map::data_type& map::operator[] (const_key_ref k) -{ - iterator ip = lower_bound (k); - if (ip == end() || k < ip->first) - ip = base_class::insert (ip, make_pair (k, V())); - return (ip->second); -} - -/// Inserts the pair into the container. -template -typename map::iterator map::insert (const_reference v) -{ - iterator ip = lower_bound (v.first); - if (ip == end() || v.first < ip->first) - ip = base_class::insert (ip, v); - else - *ip = v; - return (ip); -} - -/// Inserts elements from range [i1,i2) into the container. -template -void map::insert (const_iterator i1, const_iterator i2) -{ - assert (i1 <= i2); - reserve (size() + distance (i1, i2)); - for (; i1 != i2; ++i1) - insert (*i1); -} - -/// Erases the element with key value \p k. -template -inline void map::erase (const_key_ref k) -{ - iterator ip = find (k); - if (ip != end()) - erase (ip); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/umatrix.h b/media/libdrm/mobile2/src/util/ustl-1.0/umatrix.h deleted file mode 100644 index e6810f13c907fe047e43ea425663c35416180da6..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/umatrix.h +++ /dev/null @@ -1,80 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// umatrix.h -// - -#ifndef UMATRIX_H_740EBFEF554E833645E0FD72419A8185 -#define UMATRIX_H_740EBFEF554E833645E0FD72419A8185 - -#include "utuple.h" - -namespace ustl { - -/// \class matrix umatrix.h ustl.h -/// \ingroup Sequences -/// -/// \brief A two-dimensional array of NX*NY elements of type T. -/// -template -class matrix : public tuple { -public: - typedef tuple row_type; - typedef tuple column_type; - typedef tuple tuple_type; - typedef typename tuple_type::value_type value_type; - typedef typename tuple_type::size_type size_type; - typedef typename tuple_type::pointer pointer; - typedef typename tuple_type::const_pointer const_pointer; - typedef typename tuple_type::reference reference; - typedef typename tuple_type::const_reference const_reference; - typedef typename tuple_type::iterator iterator; - typedef typename tuple_type::const_iterator const_iterator; - typedef typename tuple_type::range_t range_t; - typedef typename tuple_type::const_range_t const_range_t; - typedef typename tuple_type::reverse_iterator reverse_iterator; - typedef typename tuple_type::const_reverse_iterator const_reverse_iterator; -public: - inline matrix (void) { fill_n (matrix::begin(), NX*NY, T()); } - inline size_type columns (void) const { return (NX); } - inline size_type rows (void) const { return (NY); } - inline const_iterator at (size_type i) const { return (matrix::begin() + i * NX); } - inline iterator at (size_type i) { return (matrix::begin() + i * NX); } - inline const_iterator operator[] (size_type i) const { return (at (i)); } - inline iterator operator[] (size_type i) { return (at (i)); } - inline row_type row (size_type r) const { return (row_type (at (r))); } - inline column_type column (size_type c) const; - template - inline const matrix& operator= (const matrix& src) { tuple_type::operator= (src); return (*this); } - inline const matrix& operator= (const matrix& src) { tuple_type::operator= (src); return (*this); } - inline const matrix& operator+= (const_reference v) { tuple_type::operator+= (v); return (*this); } - inline const matrix& operator-= (const_reference v) { tuple_type::operator-= (v); return (*this); } - inline const matrix& operator*= (const_reference v) { tuple_type::operator*= (v); return (*this); } - inline const matrix& operator/= (const_reference v) { tuple_type::operator/= (v); return (*this); } - inline const matrix operator+ (const_reference v) const - { matrix result (*this); result += v; return (result); } - inline const matrix operator- (const_reference v) const - { matrix result (*this); result -= v; return (result); } - inline const matrix operator* (const_reference v) const - { matrix result (*this); result *= v; return (result); } - inline const matrix operator/ (const_reference v) const - { matrix result (*this); result /= v; return (result); } -}; - -template -inline typename matrix::column_type matrix::column (size_type c) const -{ - column_type result; - const_iterator src (matrix::begin() + c); - iterator dest (result.begin()); - for (uoff_t i = 0; i < NY; ++ i, ++ dest, src += NX) - *dest = *src; - return (result); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/umemory.h b/media/libdrm/mobile2/src/util/ustl-1.0/umemory.h deleted file mode 100644 index 75a9005fe9f492a939883886e57d6af0c9cc0113..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/umemory.h +++ /dev/null @@ -1,199 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// umemory.h -// - -#ifndef UMEMORY_H_4AB5B0DB5BF09140541409CC47BCD17A -#define UMEMORY_H_4AB5B0DB5BF09140541409CC47BCD17A - -#include "unew.h" -#ifdef HAVE_ALLOCA_H - #include -#else - #include -#endif -#include "upair.h" -#include "uiterator.h" -#include "ulimits.h" - -namespace ustl { - -/// \class auto_ptr umemory.h ustl.h -/// \ingroup MemoryManagement -/// -/// \brief A smart pointer. -/// -/// Calls delete in the destructor; assignment transfers ownership. -/// This class does not work with void pointers due to the absence -/// of the required dereference operator. -/// -template -class auto_ptr { -public: - typedef T value_type; - typedef T* pointer; - typedef T& reference; -public: - /// Takes ownership of \p p. - inline explicit auto_ptr (pointer p = NULL) : m_p (p) {} - /// Takes ownership of pointer in \p p. \p p relinquishes ownership. - inline auto_ptr (auto_ptr& p) : m_p (p.release()) {} - /// Deletes the owned pointer. - inline ~auto_ptr (void) { delete m_p; } - /// Returns the pointer without relinquishing ownership. - inline pointer get (void) const { return (m_p); } - /// Returns the pointer and gives up ownership. - inline pointer release (void) { pointer rv (m_p); m_p = NULL; return (rv); } - /// Deletes the pointer and sets it equal to \p p. - inline void reset (pointer p) { if (p != m_p) { delete m_p; m_p = p; } } - /// Takes ownership of \p p. - inline auto_ptr& operator= (pointer p) { reset (p); return (*this); } - /// Takes ownership of pointer in \p p. \p p relinquishes ownership. - inline auto_ptr& operator= (auto_ptr& p) { reset (p.release()); return (*this); } - inline reference operator* (void) const { return (*m_p); } - inline pointer operator-> (void) const { return (m_p); } - inline bool operator== (const pointer p) const { return (m_p == p); } - inline bool operator== (const auto_ptr& p) const { return (m_p == p.m_p); } - inline bool operator< (const auto_ptr& p) const { return (p.m_p < m_p); } -private: - pointer m_p; -}; - -/// Calls the placement new on \p p. -/// \ingroup RawStorageAlgorithms -/// -template -inline void construct (T* p) -{ - new (p) T; -} - -/// Calls the placement new on \p p. -/// \ingroup RawStorageAlgorithms -/// -template -inline void construct (ForwardIterator first, ForwardIterator last) -{ - typedef typename iterator_traits::value_type value_type; - if (!numeric_limits::is_integral) { - while (first < last) { - construct (&*first); - ++ first; - } - } -} - -/// Calls the placement new on \p p. -/// \ingroup RawStorageAlgorithms -/// -template -inline void construct (T* p, const T& value) -{ - new (p) T (value); -} - -/// Calls the destructor of \p p without calling delete. -/// \ingroup RawStorageAlgorithms -/// -template -inline void destroy (T* p) throw() -{ - p->~T(); -} - -/// Calls the destructor on elements in range [first, last) without calling delete. -/// \ingroup RawStorageAlgorithms -/// -template -inline void destroy (ForwardIterator first, ForwardIterator last) throw() -{ - typedef typename iterator_traits::value_type value_type; - if (!numeric_limits::is_integral) - for (; first < last; ++ first) - destroy (&*first); -} - -/// Casts \p p to the type of the second pointer argument. -template inline T* cast_to_type (void* p, const T*) { return ((T*) p); } - -/// \brief Creates a temporary buffer pair from \p p and \p n -/// This is intended to be used with alloca to create temporary buffers. -/// The size in the returned pair is set to 0 if the allocation is unsuccessful. -/// \ingroup RawStorageAlgorithms -/// -template -inline pair make_temporary_buffer (void* p, size_t n, const T* ptype) -{ - return (make_pair (cast_to_type(p,ptype), ptrdiff_t(p ? n : 0))); -} - -#ifdef HAVE_ALLOCA_H - /// \brief Allocates a temporary buffer, if possible. - /// \ingroup RawStorageAlgorithms - #define get_temporary_buffer(size, ptype) make_temporary_buffer (alloca(size_of_elements(size, ptype)), size, ptype) - #define return_temporary_buffer(p) -#else - #define get_temporary_buffer(size, ptype) make_temporary_buffer (malloc(size_of_elements(size, ptype)), size, ptype) - #define return_temporary_buffer(p) if (p) free (p), p = NULL -#endif - -/// Copies [first, last) into result by calling copy constructors in result. -/// \ingroup RawStorageAlgorithms -/// -template -ForwardIterator uninitialized_copy (InputIterator first, InputIterator last, ForwardIterator result) -{ - while (first < last) { - construct (&*result, *first); - ++ result; - ++ first; - } - return (result); -} - -/// Copies [first, first + n) into result by calling copy constructors in result. -/// \ingroup RawStorageAlgorithms -/// -template -ForwardIterator uninitialized_copy_n (InputIterator first, size_t n, ForwardIterator result) -{ - while (n--) { - construct (&*result, *first); - ++ result; - ++ first; - } - return (result); -} - -/// Calls construct on all elements in [first, last) with value \p v. -/// \ingroup RawStorageAlgorithms -/// -template -void uninitialized_fill (ForwardIterator first, ForwardIterator last, const T& v) -{ - while (first < last) { - construct (&*first, v); - ++ first; - } -} - -/// Calls construct on all elements in [first, first + n) with value \p v. -/// \ingroup RawStorageAlgorithms -/// -template -ForwardIterator uninitialized_fill_n (ForwardIterator first, size_t n, const T& v) -{ - while (n--) { - construct (&*first, v); - ++ first; - } - return (first); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/umultimap.h b/media/libdrm/mobile2/src/util/ustl-1.0/umultimap.h deleted file mode 100644 index dd6ca48a30dbdb2f8579bbd5ca326bf9b7c9fee4..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/umultimap.h +++ /dev/null @@ -1,121 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// umultimap.h -// - -#ifndef UMULTIMAP_H_45743F516E02A87A3FCEA5024052A6F5 -#define UMULTIMAP_H_45743F516E02A87A3FCEA5024052A6F5 - -#include "uassert.h" -#include "ufunction.h" -#include "uvector.h" - -namespace ustl { - -/// \class multimap umultimap.h ustl.h -/// \ingroup AssociativeContainers -/// -/// \brief A sorted associative container that may container multiple entries for each key. -/// -template -class multimap : public vector > { -public: - typedef K key_type; - typedef V data_type; - typedef const K& const_key_ref; - typedef const V& const_data_ref; - typedef const multimap& rcself_t; - typedef vector > base_class; - typedef typename base_class::value_type value_type; - typedef typename base_class::size_type size_type; - typedef typename base_class::pointer pointer; - typedef typename base_class::const_pointer const_pointer; - typedef typename base_class::reference reference; - typedef typename base_class::const_reference const_reference; - typedef typename base_class::const_iterator const_iterator; - typedef typename base_class::iterator iterator; - typedef typename base_class::reverse_iterator reverse_iterator; - typedef typename base_class::const_reverse_iterator const_reverse_iterator; - typedef pair const_range_t; - typedef pair range_t; -public: - inline multimap (void) : vector > () {} - explicit inline multimap (size_type n) : vector > (n) {} - inline multimap (rcself_t v) : vector > (v) {} - inline multimap (const_iterator i1, const_iterator i2) : vector > () { insert (i1, i2); } - inline rcself_t operator= (rcself_t v) { base_class::operator= (v); return (*this); } - inline size_type size (void) const { return (base_class::size()); } - inline iterator begin (void) { return (base_class::begin()); } - inline const_iterator begin (void) const { return (base_class::begin()); } - inline iterator end (void) { return (base_class::end()); } - inline const_iterator end (void) const { return (base_class::end()); } - inline void assign (const_iterator i1, const_iterator i2) { clear(); insert (i1, i2); } - inline size_type count (const_key_ref k) const { return (upper_bound(k) - lower_bound(k)); } - inline void push_back (const_reference v) { insert (v); } - inline const_range_t equal_range (const_key_ref k) const { return (make_pair (lower_bound(k), upper_bound(k))); } - inline range_t equal_range (const_key_ref k) { return (make_pair (const_cast(lower_bound(k)), const_cast(upper_bound(k)))); } - const_iterator lower_bound (const_key_ref k) const; - const_iterator upper_bound (const_key_ref k) const; - inline iterator insert (const_reference v); - void insert (const_iterator i1, const_iterator i2); - inline void erase (const_key_ref k) { erase (const_cast(lower_bound(k)), const_cast(upper_bound(k))); } - inline iterator erase (iterator ep) { return (base_class::erase (ep)); } - inline iterator erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); } - inline void clear (void) { base_class::clear(); } -}; - -/// Returns an iterator to the first element with key value \p k. -template -typename multimap::const_iterator multimap::lower_bound (const_key_ref k) const -{ - const_iterator first (begin()), last (end()); - while (first != last) { - const_iterator mid = advance (first, distance (first,last) / 2); - if (mid->first < k) - first = advance (mid, 1); - else - last = mid; - } - return (first); -} - -/// Returns an iterator to the first element with key value \p k. -template -typename multimap::const_iterator multimap::upper_bound (const_key_ref k) const -{ - const_iterator first (begin()), last (end()); - while (first != last) { - const_iterator mid = advance (first, distance (first,last) / 2); - if (k < mid->first) - last = mid; - else - first = advance (mid, 1); - } - return (last); -} - -/// Inserts the pair into the container. -template -inline typename multimap::iterator multimap::insert (const_reference v) -{ - iterator ip = const_cast (upper_bound (v.first)); - return (base_class::insert (ip, v)); -} - -/// Inserts elements from range [i1,i2) into the container. -template -void multimap::insert (const_iterator i1, const_iterator i2) -{ - assert (i1 <= i2); - reserve (size() + distance (i1, i2)); - for (; i1 != i2; ++i1) - insert (*i1); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/umultiset.h b/media/libdrm/mobile2/src/util/ustl-1.0/umultiset.h deleted file mode 100644 index 404b8771a60b29d664c87df727b478d7b3f415c4..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/umultiset.h +++ /dev/null @@ -1,106 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// umultiset.h -// - -#ifndef UMULTISET_H_446AEDBB7F61C6994DC228C25D5FA3A1 -#define UMULTISET_H_446AEDBB7F61C6994DC228C25D5FA3A1 - -#include "uassert.h" -#include "ualgo.h" -#include "uvector.h" - -namespace ustl { - -/// \class multiset umultiset.h ustl.h -/// \ingroup AssociativeContainers -/// -/// \brief Multiple sorted container. -/// Unlike set, it may contain multiple copies of each element. -/// -template -class multiset : public vector { -public: - typedef const multiset& rcself_t; - typedef vector base_class; - typedef typename base_class::value_type value_type; - typedef typename base_class::size_type size_type; - typedef typename base_class::pointer pointer; - typedef typename base_class::const_pointer const_pointer; - typedef typename base_class::reference reference; - typedef typename base_class::const_reference const_reference; - typedef typename base_class::const_iterator const_iterator; - typedef typename base_class::iterator iterator; - typedef typename base_class::reverse_iterator reverse_iterator; - typedef typename base_class::const_reverse_iterator const_reverse_iterator; -public: - inline multiset (void) : vector () {} - explicit inline multiset (size_type n) : vector (n) {} - inline multiset (rcself_t v) : vector (v) {} - inline multiset (const_iterator i1, const_iterator i2) : vector () { insert (i1, i2); } - inline rcself_t operator= (rcself_t v) { base_class::operator= (v); return (*this); } - inline size_type size (void) const { return (base_class::size()); } - inline iterator begin (void) { return (base_class::begin()); } - inline const_iterator begin (void) const { return (base_class::begin()); } - inline iterator end (void) { return (base_class::end()); } - inline const_iterator end (void) const { return (base_class::end()); } - inline void assign (const_iterator i1, const_iterator i2); - size_type count (const_reference v) const; - inline void push_back (const_reference v) { insert (v); } - inline iterator insert (const_reference v); - void insert (const_iterator i1, const_iterator i2); - void erase (const_reference v); - inline iterator erase (iterator ep) { return (base_class::erase (ep)); } - inline iterator erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); } - inline void clear (void) { base_class::clear(); } -}; - -/// Copies contents of range [i1,i2) -template -inline void multiset::assign (const_iterator i1, const_iterator i2) -{ - base_class::clear(); - insert (i1, i2); -} - -/// Returns the number of elements of value \p v. -template -typename multiset::size_type multiset::count (const_reference v) const -{ - const pair fr = equal_range (begin(), end(), v); - return (distance (fr.first, fr.second)); -} - -/// Inserts \p v. -template -inline typename multiset::iterator multiset::insert (const_reference v) -{ - iterator ip = upper_bound (begin(), end(), v); - return (base_class::insert (ip, v)); -} - -/// Inserts all elements from range [i1,i2). -template -void multiset::insert (const_iterator i1, const_iterator i2) -{ - assert (i1 <= i2); - reserve (size() + distance (i1, i2)); - for (; i1 < i2; ++i1) - push_back (*i1); -} - -/// Erases all elements with value \p v. -template -void multiset::erase (const_reference v) -{ - pair epr = equal_range (begin(), end(), v); - erase (epr.first, epr.second); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/unew.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/unew.cpp deleted file mode 100644 index 084e053c67d7a1a6ae5e7785b07741dfdbf8efff..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/unew.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// unew.cc -// - -#include "unew.h" -#include - -#if PLATFORM_ANDROID -#include -#endif - -void* throwing_malloc (size_t n) throw (ustl::bad_alloc) -{ - void* p = malloc (n); - if (!p) -#if PLATFORM_ANDROID - printf("bad alloc\n"); -#else - throw ustl::bad_alloc (n); -#endif - return (p); -} - -void free_nullok (void* p) throw() -{ - if (p) - free (p); -} - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/unew.h b/media/libdrm/mobile2/src/util/ustl-1.0/unew.h deleted file mode 100644 index c4ffb6230ad7867a4f5e7484127b22f4bf6acd0e..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/unew.h +++ /dev/null @@ -1,52 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -/// \file unew.h -/// -/// \brief Same as \, but throws ustl:: exceptions. -// - -#ifndef UNEW_H_11D237512B324C9C05A55DAF1BF086F1 -#define UNEW_H_11D237512B324C9C05A55DAF1BF086F1 - -#include "uexception.h" - -/// Just like malloc, but throws on failure. -void* throwing_malloc (size_t n) throw (ustl::bad_alloc); -/// Just like free, but doesn't crash when given a NULL. -void free_nullok (void* p) throw(); - -#ifdef WITHOUT_LIBSTDCPP - -// -// These are replaceable signatures: -// - normal single new and delete (no arguments, throw @c bad_alloc on error) -// - normal array new and delete (same) -// - @c nothrow single new and delete (take a @c nothrow argument, return -// @c NULL on error) -// - @c nothrow array new and delete (same) -// -// Placement new and delete signatures (take a memory address argument, -// does nothing) may not be replaced by a user's program. -// -inline void* operator new (size_t n) throw (ustl::bad_alloc) { return (throwing_malloc (n)); } -inline void* operator new[] (size_t n) throw (ustl::bad_alloc) { return (throwing_malloc (n)); } -inline void operator delete (void* p) throw() { free_nullok (p); } -inline void operator delete[] (void* p) throw() { free_nullok (p); } - -// Default placement versions of operator new. -inline void* operator new (size_t, void* p) throw() { return (p); } -inline void* operator new[] (size_t, void* p) throw() { return (p); } - -// Default placement versions of operator delete. -inline void operator delete (void*, void*) throw() { } -inline void operator delete[](void*, void*) throw() { } - -#else -#include -#endif // WITHOUT_LIBSTDCPP - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/unumeric.h b/media/libdrm/mobile2/src/util/ustl-1.0/unumeric.h deleted file mode 100644 index 4883eb47cbe1e3bc3ce54dedf57023fdda7fe2ac..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/unumeric.h +++ /dev/null @@ -1,160 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// unumeric.h -// -// This file contains numeric algorithm templates. -// - -#ifndef UNUMERIC_H_6C99D6F6363832C644A6FFF336E84E18 -#define UNUMERIC_H_6C99D6F6363832C644A6FFF336E84E18 - -namespace ustl { - -/// Returns the sum of all elements in [first, last) added to \p init. -/// \ingroup NumericAlgorithms -/// -template -inline T accumulate (InputIterator first, InputIterator last, T init) -{ - while (first < last) - init += *first++; - return (init); -} - -/// Returns the sum of all elements in [first, last) via \p op, added to \p init. -/// \ingroup NumericAlgorithms -/// -template -inline T accumulate (InputIterator first, InputIterator last, T init, BinaryFunction binary_op) -{ - while (first < last) - init = binary_op (init, *first++); - return (init); -} - -/// Assigns range [value, value + (last - first)) to [first, last) -/// \ingroup NumericAlgorithms -/// -template -inline void iota (ForwardIterator first, ForwardIterator last, T value) -{ - while (first < last) - *first++ = value++; -} - -/// Returns the sum of products of respective elements in the given ranges. -/// \ingroup NumericAlgorithms -/// -template -inline T inner_product (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init) -{ - while (first1 < last1) - init += *first1++ * *first2++; - return (init); -} - -/// Returns the sum of products of respective elements in the given ranges. -/// \ingroup NumericAlgorithms -/// -template -inline T inner_product -(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, - BinaryOperation1 sumOp, BinaryOperation2 productOp) -{ - while (first1 < last1) - init = sumOp (init, productOp (*first1++, *first2++)); - return (init); -} - -/// Writes result such that result[i] = sum (first...first+i) -/// \ingroup NumericAlgorithms -/// -template -inline OutputIterator partial_sum (InputIterator first, InputIterator last, OutputIterator result) -{ - if (first < last) - *result = *first++; - while (first < last) - *++result = *first++ + *result; - return (result); -} - -/// Writes result such that result[i] = sumOp (first...first+i) -/// \ingroup NumericAlgorithms -/// -template -inline OutputIterator partial_sum (InputIterator first, InputIterator last, OutputIterator result, BinaryOperation sumOp) -{ - if (first < last) - *result = *first++; - while (first < last) - *++result = sumOp (*first++, *result); - return (result); -} - -/// Writes result such that result[i] = first[i] - first[i - 1] -/// \ingroup NumericAlgorithms -/// -template -inline OutputIterator adjacent_difference (InputIterator first, InputIterator last, OutputIterator result) -{ - if (first < last) - *result++ = *first++; - while (first < last) - *result++ = *first - *(first - 1); - return (result); -} - -/// Writes result such that result[i] = differenceOp (first[i], first[i - 1]) -/// \ingroup NumericAlgorithms -/// -template -inline OutputIterator adjacent_difference (InputIterator first, InputIterator last, OutputIterator result, BinaryOperation differenceOp) -{ - if (first < last) - *result++ = *first++; - while (first < last) - *result++ = differenceOp (*first, *(first - 1)); - return (result); -} - -/// \brief Returns x^n. -/// Donald Knuth's Russian Peasant algorithm. -/// \ingroup NumericAlgorithms -/// -template -inline T power (T x, unsigned n) -{ - T result (n % 2 ? x : 1); - while (n /= 2) { - x *= x; - if (n % 2) - result *= x; - } - return (result); -} - -/// \brief Returns x^n, using \p op instead of multiplication. -/// Donald Knuth's Russian Peasant algorithm. -/// \ingroup NumericAlgorithms -/// -template -inline T power (T x, unsigned n, BinaryOperation op) -{ - T result (n % 2 ? x : 1); - while (n /= 2) { - x = op (x, x); - if (n % 2) - result = op (result, x); - } - return (result); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/upair.h b/media/libdrm/mobile2/src/util/ustl-1.0/upair.h deleted file mode 100644 index b4cc3b7b04e4ef8bf4a329c093ea4c4139f9a70f..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/upair.h +++ /dev/null @@ -1,63 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -/// \file upair.h -/// \brief Pair-related functionality. - -#ifndef UPAIR_H_7DC08F1B7FECF8AE6856D84C3B617A75 -#define UPAIR_H_7DC08F1B7FECF8AE6856D84C3B617A75 - -#include "utypes.h" - -namespace ustl { - -/// \class pair upair.h ustl.h -/// \ingroup AssociativeContainers -/// -/// \brief Container for two values. -/// -template -class pair { -public: - typedef T1 first_type; - typedef T2 second_type; -public: - /// Default constructor. - inline pair (void) : first (T1()), second (T2()) {} - /// Initializes members with \p a, and \p b. - inline pair (const T1& a, const T2& b) : first (a), second (b) {} - inline pair& operator= (const pair& p2) { first = p2.first; second = p2.second; return (*this); } - template - inline pair& operator= (const pair& p2) { first = p2.first; second = p2.second; return (*this); } -public: - first_type first; - second_type second; -}; - -/// Compares both values of \p p1 to those of \p p2. -template -inline bool operator== (const pair& p1, const pair& p2) -{ - return (p1.first == p2.first && p1.second == p2.second); -} - -/// Compares both values of \p p1 to those of \p p2. -template -bool operator< (const pair& p1, const pair& p2) -{ - return (p1.first < p2.first || (p1.first == p2.first && p1.second < p2.second)); -} - -/// Returns a pair object with (a,b) -template -inline pair make_pair (const T1& a, const T2& b) -{ - return (pair (a, b)); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/upredalgo.h b/media/libdrm/mobile2/src/util/ustl-1.0/upredalgo.h deleted file mode 100644 index 562a3d60de685903a05cce04662831ffc57b38a1..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/upredalgo.h +++ /dev/null @@ -1,597 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ualgo.h -// -// Implementation of STL algorithms with custom predicates. -// -// The function prototypes are copied -// exactly from the SGI version of STL documentation along with comments about -// their use. The code is NOT the same, though the functionality usually is. -// - -#ifndef UPREDALGO_H_2CB058AE0807A01A2F6A51BA5D5820A5 -#define UPREDALGO_H_2CB058AE0807A01A2F6A51BA5D5820A5 - -namespace ustl { - -/// Copy_if copies elements from the range [first, last) to the range -/// [result, result + (last - first)) if pred(*i) returns true. -/// \ingroup MutatingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline OutputIterator copy_if (InputIterator first, InputIterator last, OutputIterator result, Predicate pred) -{ - for (; first != last; ++first) { - if (pred(*first)) { - *result = *first; - ++ result; - } - } - return (result); -} - -/// Returns the first iterator i in the range [first, last) such that -/// pred(*i) is true. Returns last if no such iterator exists. -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline InputIterator find_if (InputIterator first, InputIterator last, Predicate pred) -{ - while (first != last && !pred (*first)) - ++ first; - return (first); -} - -/// Returns the first iterator such that p(*i, *(i + 1)) == true. -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last, BinaryPredicate p) -{ - if (first != last) - for (ForwardIterator prev = first; ++first != last; ++ prev) - if (p (*prev, *first)) - return (prev); - return (last); -} - -/// Returns the pointer to the first pair of unequal elements. -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline pair -mismatch (InputIterator first1, InputIterator last1, InputIterator first2, BinaryPredicate comp) -{ - while (first1 != last1 && comp(*first1, *first2)) - ++ first1, ++ first2; - return (make_pair (first1, first2)); -} - -/// Returns true if two ranges are equal. -/// This is an extension, present in uSTL and SGI STL. -/// \ingroup ConditionAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline bool equal (InputIterator first1, InputIterator last1, InputIterator first2, BinaryPredicate comp) -{ - return (mismatch (first1, last1, first2, comp).first == last1); -} - -/// Count_if finds the number of elements in [first, last) that satisfy the -/// predicate pred. More precisely, the first version of count_if returns the -/// number of iterators i in [first, last) such that pred(*i) is true. -/// \ingroup ConditionAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline size_t count_if (InputIterator first, InputIterator last, Predicate pred) -{ - size_t total = 0; - for (; first != last; ++first) - if (pred (*first)) - ++ total; - return (total); -} - -/// Replace_if replaces every element in the range [first, last) for which -/// pred returns true with new_value. That is: for every iterator i, if -/// pred(*i) is true then it performs the assignment *i = new_value. -/// \ingroup MutatingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline void replace_if (ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value) -{ - for (; first != last; ++first) - if (pred (*first)) - *first = new_value; -} - -/// Replace_copy_if copies elements from the range [first, last) to the range -/// [result, result + (last-first)), except that any element for which pred is -/// true is not copied; new_value is copied instead. More precisely, for every -/// integer n such that 0 <= n < last-first, replace_copy_if performs the -/// assignment *(result+n) = new_value if pred(*(first+n)), -/// and *(result+n) = *(first+n) otherwise. -/// \ingroup MutatingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline OutputIterator replace_copy_if (InputIterator first, InputIterator last, OutputIterator result, Predicate pred, const T& new_value) -{ - for (; first != last; ++result, ++first) - *result = pred(*first) ? new_value : *first; -} - -/// Remove_copy_if copies elements from the range [first, last) to a range -/// beginning at result, except that elements for which pred is true are not -/// copied. The return value is the end of the resulting range. This operation -/// is stable, meaning that the relative order of the elements that are copied -/// is the same as in the range [first, last). -/// \ingroup MutatingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline OutputIterator remove_copy_if (InputIterator first, InputIterator last, OutputIterator result, Predicate pred) -{ - for (; first != last; ++first) - if (pred (*first)) - *result++ = *first; - return (result); -} - -/// Remove_if removes from the range [first, last) every element x such that -/// pred(x) is true. That is, remove_if returns an iterator new_last such that -/// the range [first, new_last) contains no elements for which pred is true. -/// The iterators in the range [new_last, last) are all still dereferenceable, -/// but the elements that they point to are unspecified. Remove_if is stable, -/// meaning that the relative order of elements that are not removed is -/// unchanged. -/// \ingroup MutatingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline ForwardIterator remove_if (ForwardIterator first, ForwardIterator last, Predicate pred) -{ - return (remove_copy_if (first, last, first, pred)); -} - -/// The reason there are two different versions of unique_copy is that there -/// are two different definitions of what it means for a consecutive group of -/// elements to be duplicates. In the first version, the test is simple -/// equality: the elements in a range [f, l) are duplicates if, for every -/// iterator i in the range, either i == f or else *i == *(i-1). In the second, -/// the test is an arbitrary Binary Predicate binary_pred: the elements in -/// [f, l) are duplicates if, for every iterator i in the range, either -/// i == f or else binary_pred(*i, *(i-1)) is true. -/// \ingroup MutatingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -OutputIterator unique_copy (InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate binary_pred) -{ - if (first != last) { - *result = *first; - while (++first != last) - if (!binary_pred (*first, *result)) - *++result = *first; - ++ result; - } - return (result); -} - -/// Every time a consecutive group of duplicate elements appears in the range -/// [first, last), the algorithm unique removes all but the first element. -/// That is, unique returns an iterator new_last such that the range [first, -/// new_last) contains no two consecutive elements that are duplicates. -/// The iterators in the range [new_last, last) are all still dereferenceable, -/// but the elements that they point to are unspecified. Unique is stable, -/// meaning that the relative order of elements that are not removed is -/// unchanged. -/// \ingroup MutatingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline ForwardIterator unique (ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred) -{ - return (unique_copy (first, last, first, binary_pred)); -} - -/// Returns the furthermost iterator i in [first, last) such that, -/// for every iterator j in [first, i), comp(*j, value) is true. -/// Assumes the range is sorted. -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp) -{ - ForwardIterator mid; - while (first != last) { - mid = advance (first, distance (first,last) / 2); - if (comp (*mid, value)) - first = mid + 1; - else - last = mid; - } - return (first); -} - -/// Performs a binary search inside the sorted range. -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline ForwardIterator binary_search (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp) -{ - ForwardIterator found = lower_bound (first, last, value, comp); - return ((found == last || comp(value, *found)) ? last : found); -} - -/// Returns the furthermost iterator i in [first,last) such that for -/// every iterator j in [first,i), comp(value,*j) is false. -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp) -{ - ForwardIterator mid; - while (first != last) { - mid = advance (first, distance (first,last) / 2); - if (comp (value, *mid)) - last = mid; - else - first = mid + 1; - } - return (last); -} - -/// Returns pair -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline pair equal_range (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp) -{ - pair rv; - rv.second = rv.first = lower_bound (first, last, value, comp); - while (rv.second != last && !comp(value, *(rv.second))) - ++ rv.second; - return (rv); -} - -/// \brief Puts \p nth element into its sorted position. -/// In this implementation, the entire array is sorted. The performance difference is -/// so small and the function use is so rare, there is no need to have code for it. -/// \ingroup SortingAlgorithms -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -/// -template -inline void nth_element (RandomAccessIterator first, RandomAccessIterator, RandomAccessIterator last, Compare comp) -{ - sort (first, last, comp); -} - -/// \brief Searches for the first subsequence [first2,last2) in [first1,last1) -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -template -ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate comp) -{ - const ForwardIterator1 slast = last1 - distance(first2, last2) + 1; - for (; first1 < slast; ++first1) { - ForwardIterator2 i = first2; - ForwardIterator1 j = first1; - for (; i != last2 && comp(*j, *i); ++i, ++j); - if (i == last2) - return (first1); - } - return (last1); -} - -/// \brief Searches for the last subsequence [first2,last2) in [first1,last1) -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -template -ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate comp) -{ - ForwardIterator1 s = last1 - distance(first2, last2); - for (; first1 < s; --s) { - ForwardIterator2 i = first2, j = s; - for (; i != last2 && comp(*j, *i); ++i, ++j); - if (i == last2) - return (s); - } - return (last1); -} - -/// \brief Searches for the first occurence of \p count \p values in [first, last) -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -template -Iterator search_n (Iterator first, Iterator last, size_t count, const T& value, BinaryPredicate comp) -{ - size_t n = 0; - for (; first != last; ++first) { - if (!comp (*first, value)) - n = 0; - else if (++n == count) - return (first - --n); - } - return (last); -} - -/// \brief Searches [first1,last1) for the first occurrence of an element from [first2,last2) -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -template -InputIterator find_first_of (InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2, BinaryPredicate comp) -{ - for (; first1 != last1; ++first1) - for (ForwardIterator i = first2; i != last2; ++i) - if (comp (*first1, *i)) - return (first1); - return (first1); -} - -/// \brief Returns true if [first2,last2) is a subset of [first1,last1) -/// \ingroup ConditionAlgorithms -/// \ingroup SetAlgorithms -/// \ingroup PredicateAlgorithms -template -bool includes (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, StrictWeakOrdering comp) -{ - for (; (first1 != last1) & (first2 != last2); ++first1) { - if (comp (*first2, *first1)) - return (false); - first2 += !comp (*first1, *first2); - } - return (first2 == last2); -} - -/// \brief Merges [first1,last1) with [first2,last2) -/// -/// Result will contain every element that is in either set. If duplicate -/// elements are present, max(n,m) is placed in the result. -/// -/// \ingroup SetAlgorithms -/// \ingroup PredicateAlgorithms -template -OutputIterator set_union (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp) -{ - for (; (first1 != last1) & (first2 != last2); ++result) { - if (comp (*first2, *first1)) - *result = *first2++; - else { - first2 += !comp (*first1, *first2); - *result = *first1++; - } - } - return (copy (first2, last2, copy (first1, last1, result))); -} - -/// \brief Creates a set containing elements shared by the given ranges. -/// \ingroup SetAlgorithms -/// \ingroup PredicateAlgorithms -template -OutputIterator set_intersection (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp) -{ - while ((first1 != last1) & (first2 != last2)) { - bool b1ge2 = !comp (*first1, *first2), b2ge1 = !comp (*first2, *first1); - if (b1ge2 & b2ge1) - *result++ = *first1; - first1 += b2ge1; - first2 += b1ge2; - } - return (result); -} - -/// \brief Removes from [first1,last1) elements present in [first2,last2) -/// \ingroup SetAlgorithms -/// \ingroup PredicateAlgorithms -template -OutputIterator set_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp) -{ - while ((first1 != last1) & (first2 != last2)) { - bool b1ge2 = !comp (*first1, *first2), b2ge1 = !comp (*first2, *first1); - if (!b1ge2) - *result++ = *first1; - first1 += b2ge1; - first2 += b1ge2; - } - return (copy (first1, last1, result)); -} - -/// \brief Performs union of sets A-B and B-A. -/// \ingroup SetAlgorithms -/// \ingroup PredicateAlgorithms -template -OutputIterator set_symmetric_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp) -{ - while ((first1 != last1) & (first2 != last2)) { - bool b1l2 = comp (*first1, *first2), b2l1 = comp (*first2, *first1); - if (b1l2) - *result++ = *first1; - else if (b2l1) - *result++ = *first2; - first1 += !b2l1; - first2 += !b1l2; - } - return (copy (first2, last2, copy (first1, last1, result))); -} - -/// \brief Returns true if the given range is sorted. -/// \ingroup ConditionAlgorithms -/// \ingroup PredicateAlgorithms -template -bool is_sorted (ForwardIterator first, ForwardIterator last, StrictWeakOrdering comp) -{ - for (ForwardIterator i = first; ++i < last; ++first) - if (comp (*i, *first)) - return (false); - return (true); -} - -/// \brief Compares two given containers like strcmp compares strings. -/// \ingroup ConditionAlgorithms -/// \ingroup PredicateAlgorithms -template -bool lexicographical_compare (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate comp) -{ - for (; (first1 != last1) & (first2 != last2); ++first1, ++first2) { - if (comp (*first1, *first2)) - return (true); - if (comp (*first2, *first1)) - return (false); - } - return ((first1 == last1) & (first2 != last2)); -} - -/// \brief Creates the next lexicographical permutation of [first,last). -/// Returns false if no further permutations can be created. -/// \ingroup GeneratorAlgorithms -/// \ingroup PredicateAlgorithms -template -bool next_permutation (BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering comp) -{ - if (distance (first, last) < 2) - return (false); - BidirectionalIterator i = last; - for (--i; i != first; ) { - --i; - if (comp (i[0], i[1])) { - BidirectionalIterator j = last; - while (!comp (*i, *--j)); - iter_swap (i, j); - reverse (i + 1, last); - return (true); - } - } - reverse (first, last); - return (false); -} - -/// \brief Creates the previous lexicographical permutation of [first,last). -/// Returns false if no further permutations can be created. -/// \ingroup GeneratorAlgorithms -/// \ingroup PredicateAlgorithms -template -bool prev_permutation (BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering comp) -{ - if (distance (first, last) < 2) - return (false); - BidirectionalIterator i = last; - for (--i; i != first; ) { - --i; - if (comp(i[1], i[0])) { - BidirectionalIterator j = last; - while (!comp (*--j, *i)); - iter_swap (i, j); - reverse (i + 1, last); - return (true); - } - } - reverse (first, last); - return (false); -} - -/// \brief Returns iterator to the max element in [first,last) -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -template -inline ForwardIterator max_element (ForwardIterator first, ForwardIterator last, BinaryPredicate comp) -{ - ForwardIterator result = first; - for (; first != last; ++first) - if (comp (*result, *first)) - result = first; - return (result); -} - -/// \brief Returns iterator to the min element in [first,last) -/// \ingroup SearchingAlgorithms -/// \ingroup PredicateAlgorithms -template -inline ForwardIterator min_element (ForwardIterator first, ForwardIterator last, BinaryPredicate comp) -{ - ForwardIterator result = first; - for (; first != last; ++first) - if (comp (*first, *result)) - result = first; - return (result); -} - -/// \brief Makes [first,middle) a part of the sorted array. -/// Contents of [middle,last) is undefined. This implementation just calls stable_sort. -/// \ingroup SortingAlgorithms -/// \ingroup PredicateAlgorithms -template -inline void partial_sort (RandomAccessIterator first, RandomAccessIterator, RandomAccessIterator last, StrictWeakOrdering comp) -{ - stable_sort (first, last, comp); -} - -/// \brief Like partial_sort, but outputs to [result_first,result_last) -/// \ingroup SortingAlgorithms -/// \ingroup PredicateAlgorithms -template -RandomAccessIterator partial_sort_copy (InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, StrictWeakOrdering comp) -{ - RandomAccessIterator rend = result_first; - for (; first != last; ++first) { - RandomAccessIterator i = result_first; - for (; i != rend && comp (*i, *first); ++i); - if (i == result_last) - continue; - rend += (rend < result_last); - copy_backward (i, rend - 1, rend); - *i = *first; - } - return (rend); -} - -/// \brief Like \ref partition, but preserves equal element order. -/// \ingroup SortingAlgorithms -/// \ingroup PredicateAlgorithms -template -ForwardIterator stable_partition (ForwardIterator first, ForwardIterator last, Predicate pred) -{ - if (first == last) - return (first); - ForwardIterator l, r, m = advance (first, distance (first, last) / 2); - if (first == m) - return (pred(*first) ? last : first); - l = stable_partition (first, m, pred); - r = stable_partition (m, last, pred); - rotate (l, m, r); - return (advance (l, distance (m, r))); -} - -/// \brief Splits [first,last) in two by \p pred. -/// -/// Creates two ranges [first,middle) and [middle,last), where every element -/// in the former is less than every element in the latter. -/// The return value is middle. -/// -/// \ingroup SortingAlgorithms -/// \ingroup PredicateAlgorithms -template -inline ForwardIterator partition (ForwardIterator first, ForwardIterator last, Predicate pred) -{ - return (stable_partition (first, last, pred)); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uqueue.h b/media/libdrm/mobile2/src/util/ustl-1.0/uqueue.h deleted file mode 100644 index 99eef80bc6e24272dc1b865f777071c2d19ba5a6..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uqueue.h +++ /dev/null @@ -1,71 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// uqueue.h -// - -#ifndef UQUEUE_H_27F01FDB0D59B75277E0E5C41ABC6B5B -#define UQUEUE_H_27F01FDB0D59B75277E0E5C41ABC6B5B - -namespace ustl { - -/// \class queue uqueue.h ustl.h -/// \ingroup Sequences -/// -/// \brief Queue adapter to uSTL containers. -/// -/// The most efficient way to use this implementation is to fill the queue -/// and the completely empty it before filling again. -/// -template -class queue { -public: - typedef typename Sequence::value_type value_type; - typedef typename Sequence::size_type size_type; - typedef typename Sequence::difference_type difference_type; - typedef typename Sequence::reference reference; - typedef typename Sequence::const_reference const_reference; - typedef typename Sequence::pointer pointer; -public: - inline queue (void) : m_Storage (), m_Front (0) { } - explicit inline queue (const Sequence& s) : m_Storage (s), m_Front (0) { } - inline size_type size (void) const { return (m_Storage.size() - m_Front); } - inline bool empty (void) const { return (!size()); } - inline reference front (void) { return (m_Storage [m_Front]); } - inline const_reference front (void) const { return (m_Storage [m_Front]); } - inline reference back (void) { return (m_Storage.back()); } - inline const_reference back (void) const { return (m_Storage.back()); } - inline void push (const value_type& v); - inline void pop (void); - inline bool operator== (const queue& s) { return (m_Storage == s.m_Storage && m_Front == s.m_Front); } - inline bool operator< (const queue& s) { return (size() < s.size()); } -private: - Sequence m_Storage; ///< Where the data actually is. - size_type m_Front; ///< Index of the element returned by next pop. -}; - -/// Pushes \p v on the queue. -template -inline void queue::push (const value_type& v) -{ - if (m_Front) { - m_Storage.erase (m_Storage.begin(), m_Front); - m_Front = 0; - } - m_Storage.push_back (v); -} - -/// Pops the topmost element from the queue. -template -inline void queue::pop (void) -{ - if (++m_Front >= m_Storage.size()) - m_Storage.resize (m_Front = 0); -} - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uset.h b/media/libdrm/mobile2/src/util/ustl-1.0/uset.h deleted file mode 100644 index 958d4b09dd9422eb456cbc3164ee0ff2b4e3fdca..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uset.h +++ /dev/null @@ -1,97 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// uset.h -// - -#ifndef USET_H_45543F516E02A87A3FCEA5024052A6F5 -#define USET_H_45543F516E02A87A3FCEA5024052A6F5 - -#include "uassert.h" -#include "uvector.h" - -namespace ustl { - -/// \class set uset.h ustl.h -/// \ingroup Sequences -/// -/// \brief Unique sorted container. Sorted vector with all values unique. -/// -template -class set : public vector { -public: - typedef const set& rcself_t; - typedef vector base_class; - typedef typename base_class::value_type key_type; - typedef typename base_class::value_type data_type; - typedef typename base_class::value_type value_type; - typedef typename base_class::size_type size_type; - typedef typename base_class::pointer pointer; - typedef typename base_class::const_pointer const_pointer; - typedef typename base_class::reference reference; - typedef typename base_class::const_reference const_reference; - typedef typename base_class::const_iterator const_iterator; - typedef typename base_class::iterator iterator; - typedef typename base_class::reverse_iterator reverse_iterator; - typedef typename base_class::const_reverse_iterator const_reverse_iterator; -public: - inline set (void) : vector () { } - explicit inline set (size_type n) : vector (n) { } - inline set (rcself_t v) : vector (v) { } - inline set (const_iterator i1, const_iterator i2) : vector () { insert (i1, i2); } - inline rcself_t operator= (rcself_t v) { base_class::operator= (v); return (*this); } - inline size_type size (void) const { return (base_class::size()); } - inline iterator begin (void) { return (base_class::begin()); } - inline const_iterator begin (void) const { return (base_class::begin()); } - inline iterator end (void) { return (base_class::end()); } - inline const_iterator end (void) const { return (base_class::end()); } - inline void assign (const_iterator i1, const_iterator i2) { clear(); insert (i1, i2); } - inline void push_back (const_reference v) { insert (v); } - inline const_iterator find (const_reference v) const { return (binary_search (begin(), end(), v)); } - inline iterator find (const_reference v) { return (const_cast(const_cast(*this).find (v))); } - iterator insert (const_reference v); - inline void insert (const_iterator i1, const_iterator i2); - inline void erase (const_reference v); - inline iterator erase (iterator ep) { return (base_class::erase (ep)); } - inline iterator erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); } - inline void clear (void) { base_class::clear(); } -}; - -/// Inserts \p v into the container, maintaining the sort order. -template -typename set::iterator set::insert (const_reference v) -{ - iterator ip = lower_bound (begin(), end(), v); - if (ip == end() || v < *ip) - ip = base_class::insert (ip, v); - else - *ip = v; - return (ip); -} - -/// Inserts the contents of range [i1,i2) -template -void set::insert (const_iterator i1, const_iterator i2) -{ - assert (i1 <= i2); - reserve (size() + distance (i1, i2)); - for (; i1 < i2; ++i1) - push_back (*i1); -} - -/// Erases the element with value \p v. -template -inline void set::erase (const_reference v) -{ - iterator ip = find (v); - if (ip != end()) - erase (ip); -} - - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uspecial.h b/media/libdrm/mobile2/src/util/ustl-1.0/uspecial.h deleted file mode 100644 index 0b87a5462f6fc360b75e33ab6a09b86d2d7753fd..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uspecial.h +++ /dev/null @@ -1,267 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// uspecial.h -// -// Template specializations for uSTL classes. -// - -#ifndef USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0 -#define USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0 - -#include "uassert.h" -#include "uvector.h" -#include "ustring.h" -#include "uset.h" -#include "umultiset.h" -#include "ubitset.h" -#include "ulaalgo.h" -#include "uctralgo.h" -#include "ufunction.h" -#include "uctrstrm.h" -#include "sistream.h" -#include - -namespace ustl { - -//---------------------------------------------------------------------- -// Alogrithm specializations not in use by the library code. -//---------------------------------------------------------------------- - -template <> inline void swap (cmemlink& a, cmemlink& b) { a.swap (b); } -template <> inline void swap (memlink& a, memlink& b) { a.swap (b); } -template <> inline void swap (memblock& a, memblock& b) { a.swap (b); } -template <> inline void swap (string& a, string& b) { a.swap (b); } -#define TEMPLATE_SWAP_PSPEC(type, template_decl) \ -template_decl inline void swap (type& a, type& b) { a.swap (b); } -TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (vector,T), TEMPLATE_DECL1 (T)) -TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (set,T), TEMPLATE_DECL1 (T)) -TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (multiset,T), TEMPLATE_DECL1 (T)) -TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE2 (tuple,N,T), TEMPLATE_FULL_DECL2 (size_t,N,typename,T)) - -//---------------------------------------------------------------------- -// Streamable definitions. Not used in the library and require streams. -//---------------------------------------------------------------------- - -//----{ pair }---------------------------------------------------------- - -/// \brief Reads pair \p p from stream \p is. -template -istream& operator>> (istream& is, pair& p) -{ - is >> p.first; - is.align (alignof(T2())); - is >> p.second; - is.align (alignof(T1())); - return (is); -} - -/// Writes pair \p p to stream \p os. -template -ostream& operator<< (ostream& os, const pair& p) -{ - os << p.first; - os.align (alignof(T2())); - os << p.second; - os.align (alignof(T1())); - return (os); -} - -/// Writes pair \p p to stream \p os. -template -ostringstream& operator<< (ostringstream& os, const pair& p) -{ - os << '(' << p.first << ',' << p.second << ')'; - return (os); -} - -/// Returns the written size of the object. -template -inline size_t stream_size_of (const pair& v) -{ - return (Align (stream_size_of(v.first), alignof(T2())) + - Align (stream_size_of(v.second), alignof(T1()))); -} - -/// \brief Takes a pair and returns pair.first -/// This is an extension, available in uSTL and the SGI STL. -template struct select1st : public unary_function { - typedef typename Pair::first_type result_type; - inline const result_type& operator()(const Pair& a) const { return (a.first); } - inline result_type& operator()(Pair& a) const { return (a.first); } -}; - -/// \brief Takes a pair and returns pair.second -/// This is an extension, available in uSTL and the SGI STL. -template struct select2nd : public unary_function { - typedef typename Pair::second_type result_type; - inline const result_type& operator()(const Pair& a) const { return (a.second); } - inline result_type& operator()(Pair& a) const { return (a.second); } -}; - -/// \brief Converts a const_iterator pair into an iterator pair -/// Useful for converting pair ranges returned by equal_range, for instance. -/// This is an extension, available in uSTL. -template -inline pair -unconst (const pair& i, Container& ctr) -{ - assert (i.first >= ctr.begin() && i.first <= ctr.end() && "unconst algorithm must be given iterators from the argument container"); - pair result; - result.first = ctr.begin() + (i.first - ctr.begin()); - result.second = ctr.begin() + (i.second - ctr.begin()); - return (result); -} - -//----{ vector }-------------------------------------------------------- - -STD_TEMPLATE_CTR_STREAMABLE (TEMPLATE_TYPE1 (vector,T), TEMPLATE_DECL1 (T)) - -template -inline size_t alignof (const vector&) -{ - typedef typename vector::written_size_type written_size_type; - return (alignof (written_size_type())); -} - -//----{ bitset }-------------------------------------------------------- - -/// Reads bitset \p v from stream \p is. -template -inline istream& operator>> (istream& is, bitset& v) -{ - return (nr_container_read (is, v)); -} - -/// Writes bitset \p v into stream \p os. -template -inline ostream& operator<< (ostream& os, const bitset& v) -{ - return (nr_container_write (os, v)); -} - -/// Writes bitset \p v into stream \p os. -template -inline ostringstream& operator<< (ostringstream& os, const bitset& v) -{ - return (os << v.to_string()); -} - -/// Writes bitset \p v into stream \p os. -template -istringstream& operator>> (istringstream& is, bitset& v) -{ - char c; - for (int i = Size; --i >= 0 && (is >> c).good();) - v.set (i, c == '1'); - return (is); -} - -/// Returns the number of bytes necessary to write this object to a stream -template -inline size_t stream_size_of (const bitset& v) -{ - return (v.capacity() / CHAR_BIT); -} - -//----{ tuple }--------------------------------------------------------- - -STD_TEMPLATE_NR_CTR_STREAMABLE ( - TEMPLATE_TYPE2 (tuple,N,T), - TEMPLATE_FULL_DECL2 (size_t,N,typename,T) -) - -template -struct numeric_limits > { - typedef numeric_limits value_limits; - static inline tuple min (void) { tuple v; fill (v, value_limits::min()); return (v); } - static inline tuple max (void) { tuple v; fill (v, value_limits::max()); return (v); } - static const bool is_signed = value_limits::is_signed; - static const bool is_integer = value_limits::is_integer; - static const bool is_integral = value_limits::is_integral; -}; - -template -inline size_t alignof (const tuple&) { return (alignof (T())); } - -template -inline ostringstream& chartype_text_write (ostringstream& os, const T& v) -{ - if (isprint(v)) - os << '\'' << v << '\''; - else - os << (IntT)(v); - return (os); -} - -template <> -inline ostringstream& container_element_text_write (ostringstream& os, const uint8_t& v) -{ return (chartype_text_write (os, v)); } -template <> -inline ostringstream& container_element_text_write (ostringstream& os, const int8_t& v) -{ return (chartype_text_write (os, v)); } - -//----{ matrix }-------------------------------------------------------- - -/// Writes tuple \p v into stream \p os. -template -ostringstream& operator<< (ostringstream& os, const matrix& v) -{ - os << '('; - for (uoff_t row = 0; row < NY; ++ row) { - os << '('; - for (uoff_t column = 0; column < NX; ++ column) { - os << v[row][column]; - if (column < NX - 1) - os << ','; - } - os << ')'; - } - os << ')'; - return (os); -} - -//---------------------------------------------------------------------- - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -#ifndef WITHOUT_LIBSTDCPP - -/// \todo Need a better solution to getting the hash value. -inline hashvalue_t hash_value (const string::const_pointer& v) -{ - string::const_pointer first (v), last (v + strlen(v)); - hashvalue_t h = 0; - // This has the bits flowing into each other from both sides of the number - for (; first < last; ++ first) - h = *first + ((h << 7) | (h >> BitsInType(hashvalue_t) - 7)); - return (h); -} - -#endif -#endif - -//---------------------------------------------------------------------- - -} // namespace ustl - -// This is here because there really is no other place to put it. -#if SIZE_OF_BOOL != SIZE_OF_CHAR -// bool is a big type on some machines (like DEC Alpha), so it's written as a byte. -ALIGNOF(bool, sizeof(uint8_t)) -#endif -STD_STREAMABLE(cmemlink) -STD_STREAMABLE(istream) -STD_STREAMABLE(ostream) -STD_STREAMABLE(string) -STD_STREAMABLE(exception) -STD_STREAMABLE(CBacktrace) -TEXT_STREAMABLE(cmemlink) -TEXT_STREAMABLE(istream) -TEXT_STREAMABLE(ostream) -TEXT_STREAMABLE(exception) -TEXT_STREAMABLE(CBacktrace) - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustack.h b/media/libdrm/mobile2/src/util/ustl-1.0/ustack.h deleted file mode 100644 index c48e3b3645ad225d69ffcbc9df805a804c36bd5d..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ustack.h +++ /dev/null @@ -1,46 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ustack.h -// - -#ifndef USTACK_H_5242F5635322B2EC44A9AEE73022C6E9 -#define USTACK_H_5242F5635322B2EC44A9AEE73022C6E9 - -namespace ustl { - -/// \class stack ustack.h ustl.h -/// \ingroup Sequences -/// -/// \brief Stack adapter to uSTL containers. -/// -template -class stack { -public: - typedef typename Sequence::value_type value_type; - typedef typename Sequence::size_type size_type; - typedef typename Sequence::difference_type difference_type; - typedef typename Sequence::reference reference; - typedef typename Sequence::const_reference const_reference; - typedef typename Sequence::pointer pointer; -public: - inline stack (void) : m_Storage () { } - explicit inline stack (const Sequence& s) : m_Storage (s) { } - inline bool empty (void) const { return (m_Storage.empty()); } - inline size_type size (void) const { return (m_Storage.size()); } - inline reference top (void) { return (m_Storage.back()); } - inline const_reference top (void) const { return (m_Storage.back()); } - inline void push (const value_type& v) { m_Storage.push_back (v); } - inline void pop (void) { m_Storage.pop_back(); } - inline bool operator== (const stack& s) { return (m_Storage == s.m_Storage); } - inline bool operator< (const stack& s) { return (m_Storage.size() < s.m_Storage.size()); } -private: - Sequence m_Storage; ///< Where the data actually is. -}; - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.cpp deleted file mode 100644 index ce731f7de2b426f35c8857397ec31253ab9bf9de..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ustdxept.cc -// - -#include "ustdxept.h" -#include "mistream.h" -#include "mostream.h" -#include "strmsize.h" -#include "uiosfunc.h" -#include "uspecial.h" - -namespace ustl { - -//---------------------------------------------------------------------- - -/// \p arg contains a description of the error. -error_message::error_message (const char* arg) throw() -: m_Arg () -{ -#if PLATFORM_ANDROID - m_Arg = arg; -#else /* !PLATFORM_ANDROID */ - try { m_Arg = arg; } catch (...) {} -#endif - set_format (xfmt_ErrorMessage); -} - -/// Virtual destructor -error_message::~error_message (void) throw() -{ -} - -/// Returns a descriptive error message. fmt="%s: %s" -void error_message::info (string& msgbuf, const char* fmt) const throw() -{ - if (!fmt) fmt = "%s: %s"; -#if PLATFORM_ANDROID - msgbuf.format (fmt, what(), m_Arg.cdata()); -#else /* !PLATFORM_ANDROID */ - try { msgbuf.format (fmt, what(), m_Arg.cdata()); } catch (...) {} -#endif -} - -/// Reads the object from stream \p is. -void error_message::read (istream& is) -{ - exception::read (is); - is >> m_Arg >> ios::align(); -} - -/// Writes the object to stream \p os. -void error_message::write (ostream& os) const -{ - exception::write (os); - os << m_Arg << ios::align(); -} - -/// Returns the size of the written object. -size_t error_message::stream_size (void) const -{ - return (exception::stream_size() + Align (stream_size_of (m_Arg))); -} - -//---------------------------------------------------------------------- - -} // namespace ustl - - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.h b/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.h deleted file mode 100644 index 4f50953701cb76afb6731be8b4c3f1c60c49ca50..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.h +++ /dev/null @@ -1,143 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ustdxept.h -// - -#ifndef USTDXEPT_H_46F7AE967738B588038F95E41158D7FF -#define USTDXEPT_H_46F7AE967738B588038F95E41158D7FF - -#include "uexception.h" -#include "ustring.h" - -namespace ustl { - -enum { - xfmt_ErrorMessage = 2, - xfmt_LogicError = xfmt_ErrorMessage, - xfmt_RuntimeError = xfmt_ErrorMessage -}; - -/// \class logic_error ustdxept.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Logic errors represent problems in the internal logic of the program. -/// -class error_message : public exception { -public: - explicit error_message (const char* arg) throw(); - virtual ~error_message (void) throw(); - inline virtual const char* what (void) const throw() { return ("error"); } - virtual void info (string& msgbuf, const char* fmt = NULL) const throw(); - virtual void read (istream& is); - virtual void write (ostream& os) const; - virtual size_t stream_size (void) const; -protected: - string m_Arg; -}; - -/// \class logic_error ustdxept.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Logic errors represent problems in the internal logic of the program. -/// -class logic_error : public error_message { -public: - inline explicit logic_error (const char* arg) throw() : error_message (arg) {} - inline virtual const char* what (void) const throw() { return ("logic error"); } -}; - -/// \class domain_error ustdxept.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Reports domain errors ("domain" is in the mathematical sense) -/// -class domain_error : public logic_error { -public: - inline explicit domain_error (const char* arg) throw() : logic_error (arg) {} - inline virtual const char* what (void) const throw() { return ("domain error"); } -}; - -/// \class invalid_argument ustdxept.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Reports an invalid argument to a function. -/// -class invalid_argument : public logic_error { -public: - inline explicit invalid_argument (const char* arg) throw() : logic_error (arg) {} - inline virtual const char* what (void) const throw() { return ("invalid argument"); } -}; - -/// \class length_error ustdxept.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Reports when an object exceeds its allowed size. -/// -class length_error : public logic_error { -public: - inline explicit length_error (const char* arg) throw() : logic_error (arg) {} - inline virtual const char* what (void) const throw() { return ("length error"); } -}; - -/// \class out_of_range ustdxept.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Reports arguments with values out of allowed range. -/// -class out_of_range : public logic_error { -public: - inline explicit out_of_range (const char* arg) throw() : logic_error (arg) {} - inline virtual const char* what (void) const throw() { return ("out of range"); } -}; - -/// \class runtime_error ustdxept.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Reports errors that are dependent on the data being processed. -/// -class runtime_error : public error_message { -public: - inline explicit runtime_error (const char* arg) throw() : error_message (arg) {} - inline virtual const char* what (void) const throw() { return ("runtime error"); } -}; - -/// \class range_error ustdxept.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Reports data that does not fall within the permitted range. -/// -class range_error : public runtime_error { -public: - inline explicit range_error (const char* arg) throw() : runtime_error (arg) {} - inline virtual const char* what (void) const throw() { return ("range error"); } -}; - -/// \class overflow_error ustdxept.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Reports arithmetic overflow. -/// -class overflow_error : public runtime_error { -public: - inline explicit overflow_error (const char* arg) throw() : runtime_error (arg) {} - inline virtual const char* what (void) const throw() { return ("overflow error"); } -}; - -/// \class underflow_error ustdxept.h ustl.h -/// \ingroup Exceptions -/// -/// \brief Reports arithmetic underflow. -/// -class underflow_error : public runtime_error { -public: - inline explicit underflow_error (const char* arg) throw() : runtime_error (arg) {} - inline virtual const char* what (void) const throw() { return ("underflow error"); } -}; - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustl.tbff b/media/libdrm/mobile2/src/util/ustl-1.0/ustl.tbff deleted file mode 100644 index b8ad374087cd4c643164fe53f064e81f8f653536..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ustl.tbff +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustring.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/ustring.cpp deleted file mode 100644 index db87d341f3a2dee6a4530282bad1eeabde0ca12e..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ustring.cpp +++ /dev/null @@ -1,425 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ustring.cpp -// -// STL basic_string equivalent functionality. -// - -#include "uassert.h" -#include "ustring.h" -#include "mistream.h" -#include "mostream.h" -#include "ualgo.h" -#include // for vsnprintf (in string::format) - -#include "uassert.h" - -namespace ustl { - -//---------------------------------------------------------------------- - -const uoff_t string::npos; -const string::size_type string::size_Terminator; -const string::value_type string::c_Terminator; -const char string::empty_string[string::size_Terminator] = ""; - -typedef utf8in_iterator utf8icstring_iterator; -typedef utf8in_iterator utf8istring_iterator; -typedef utf8out_iterator utf8ostring_iterator; - -//---------------------------------------------------------------------- - -/// Creates an empty string. -string::string (void) -: memblock () -{ - link (empty_string, 0U); -} - -/// Assigns itself the value of string \p s -string::string (const string& s) -: memblock() -{ - if (s.is_linked()) - link (s.c_str(), s.size()); - else - assign (s); -} - -/// Links to \p s -string::string (const_pointer s) -: memblock () -{ - if (!s) - s = empty_string; - link (s, strlen(s)); -} - -/// Creates a string of length \p n filled with character \p c. -string::string (size_type n, value_type c) -: memblock () -{ - resize (n); - fill_n (begin(), n, c); -} - -/// Resize the string to \p n characters. New space contents is undefined. -void string::resize (size_type n) -{ - memblock::resize (n); - at(n) = c_Terminator; -} - -/// Assigns itself the value of string \p s -void string::assign (const_pointer s) -{ - if (!s) - s = empty_string; - assign (s, strlen (s)); -} - -/// Assigns itself the value of string \p s of length \p len. -void string::assign (const_pointer s, size_type len) -{ - while (len && s[len - 1] == c_Terminator) - -- len; - resize (len); - copy (s, len); -} - -/// Appends to itself the value of string \p s of length \p len. -void string::append (const_pointer s) -{ - if (!s) - s = empty_string; - append (s, strlen (s)); -} - -/// Appends to itself the value of string \p s of length \p len. -void string::append (const_pointer s, size_type len) -{ - while (len && s[len - 1] == c_Terminator) - -- len; - resize (size() + len); - copy_n (s, len, end() - len); -} - -/// Appends to itself \p n characters of value \p c. -void string::append (size_type n, value_type c) -{ - resize (size() + n); - fill_n (end() - n, n, c); -} - -/// Copies into itself at offset \p start, the value of string \p p of length \p n. -string::size_type string::copyto (pointer p, size_type n, const_iterator start) const -{ - assert (p && n); - if (!start) - start = begin(); - const size_type btc = min(n - size_Terminator, size()); - copy_n (start, btc, p); - p[btc] = c_Terminator; - return (btc + size_Terminator); -} - -/// Returns comparison value regarding string \p s. -/// The return value is: -/// \li 1 if this string is greater (by value, not length) than string \p s -/// \li 0 if this string is equal to string \p s -/// \li -1 if this string is less than string \p s -/// -/*static*/ int string::compare (const_iterator first1, const_iterator last1, const_iterator first2, const_iterator last2) -{ - assert (first1 <= last1 && (first2 <= last2 || !last2) && "Negative ranges result in memory allocation errors."); - const size_type len1 = distance (first1, last1), len2 = distance (first2, last2); - const int rvbylen = sign (int(len1 - len2)); - int rv = memcmp (first1, first2, min (len1, len2)); - return (rv ? rv : rvbylen); -} - -/// Returns true if this string is equal to string \p s. -bool string::operator== (const_pointer s) const -{ - if (!s) - s = empty_string; - return (size() == strlen(s) && 0 == memcmp (c_str(), s, size())); -} - -/// Returns the beginning of character \p i. -string::iterator string::utf8_iat (uoff_t i) -{ - utf8istring_iterator cfinder (begin()); - cfinder += i; - return (cfinder.base()); -} - -/// Inserts wide character \p c at \p ip \p n times as a UTF-8 string. -/// -/// \p ip is a character position, not a byte position, and must fall in -/// the 0 through length() range. -/// The first argument is not an iterator because it is rather difficult -/// to get one. You'd have to use ((utf8begin() + n).base()) as the first -/// argument, which is rather ugly. Besides, then this insert would be -/// ambiguous with the regular character insert. -/// -void string::insert (const uoff_t ip, wchar_t c, size_type n) -{ - iterator ipp (utf8_iat (ip)); - ipp = iterator (memblock::insert (memblock::iterator(ipp), n * Utf8Bytes(c))); - fill_n (utf8out (ipp), n, c); - *end() = c_Terminator; -} - -/// Inserts sequence of wide characters at \p ip. -void string::insert (const uoff_t ip, const wchar_t* first, const wchar_t* last, const size_type n) -{ - iterator ipp (utf8_iat (ip)); - size_type nti = distance (first, last), bti = 0; - for (uoff_t i = 0; i < nti; ++ i) - bti += Utf8Bytes(first[i]); - ipp = iterator (memblock::insert (memblock::iterator(ipp), n * bti)); - utf8ostring_iterator uout (utf8out (ipp)); - for (uoff_t j = 0; j < n; ++ j) - for (uoff_t k = 0; k < nti; ++ k, ++ uout) - *uout = first[k]; - *end() = c_Terminator; -} - -/// Inserts character \p c into this string at \p start. -string::iterator string::insert (iterator start, const_reference c, size_type n) -{ - start = iterator (memblock::insert (memblock::iterator(start), n)); - fill_n (start, n, c); - *end() = c_Terminator; - return (start); -} - -/// Inserts \p count instances of string \p s at offset \p start. -string::iterator string::insert (iterator start, const_pointer s, size_type n) -{ - if (!s) - s = empty_string; - return (insert (start, s, s + strlen(s), n)); -} - -/// Inserts [first,last] \p n times. -string::iterator string::insert (iterator start, const_pointer first, const_pointer last, size_type n) -{ - assert (first <= last); - assert (begin() <= start && end() >= start); - assert ((first < begin() || first >= end() || size() + abs_distance(first,last) < capacity()) && "Insertion of self with autoresize is not supported"); - start = iterator (memblock::insert (memblock::iterator(start), distance(first, last) * n)); - fill (memblock::iterator(start), first, distance(first, last), n); - *end() = c_Terminator; - return (start); -} - -/// Erases \p size bytes at \p start. -string::iterator string::erase (iterator ep, size_type n) -{ - string::iterator rv = memblock::erase (memblock::iterator(ep), n); - *end() = c_Terminator; - return (rv); -} - -/// Erases \p size characters at \p start. -/// \p start is a character position, not a byte position, and must be -/// in the 0..length() range. -/// -void string::erase (uoff_t ep, size_type n) -{ - iterator first (utf8_iat(ep)); - size_t nbytes (utf8_iat(ep + n) - first); - memblock::erase (first, nbytes); - *end() = c_Terminator; -} - -/// Replaces range [\p start, \p start + \p len] with string \p s. -void string::replace (iterator first, iterator last, const_pointer s) -{ - if (!s) - s = empty_string; - replace (first, last, s, s + strlen(s)); -} - -/// Replaces range [\p start, \p start + \p len] with \p count instances of string \p s. -void string::replace (iterator first, iterator last, const_pointer i1, const_pointer i2, size_type n) -{ - assert (first <= last); - assert (n || distance(first, last)); - assert (first >= begin() && first <= end() && last >= first && last <= end()); - assert ((i1 < begin() || i1 >= end() || abs_distance(i1,i2) * n + size() < capacity()) && "Replacement by self can not autoresize"); - const size_type bte = distance(first, last), bti = distance(i1, i2) * n; - if (bti < bte) - first = iterator (memblock::erase (memblock::iterator(first), bte - bti)); - else if (bte < bti) - first = iterator (memblock::insert (memblock::iterator(first), bti - bte)); - fill (memblock::iterator(first), i1, distance(i1, i2), n); - *end() = c_Terminator; -} - -/// Returns the offset of the first occurence of \p c after \p pos. -uoff_t string::find (const_reference c, uoff_t pos) const -{ - const_iterator found = ::ustl::find (iat(pos), end(), c); - return (found < end() ? distance(begin(),found) : npos); -} - -/// Returns the offset of the first occurence of substring \p s of length \p n after \p pos. -uoff_t string::find (const string& s, uoff_t pos) const -{ - if (s.empty() || s.size() > size() - pos) - return (npos); - const uoff_t endi = s.size() - 1; - const_reference endchar = s[endi]; - uoff_t lastPos = endi; - while (lastPos-- && s[lastPos] != endchar); - const size_type skip = endi - lastPos; - const_iterator i = iat(pos) + endi; - for (; i < end() && (i = ::ustl::find (i, end(), endchar)) < end(); i += skip) - if (memcmp (i - endi, s.c_str(), s.size()) == 0) - return (distance (begin(), i) - endi); - return (npos); -} - -/// Returns the offset of the last occurence of character \p c before \p pos. -uoff_t string::rfind (const_reference c, uoff_t pos) const -{ - for (int i = min(pos,size()-1); i >= 0; --i) - if (at(i) == c) - return (i); - return (npos); -} - -/// Returns the offset of the last occurence of substring \p s of size \p n before \p pos. -uoff_t string::rfind (const string& s, uoff_t pos) const -{ - const_iterator d = iat(pos) - 1; - const_iterator sp = begin() + s.size() - 1; - const_iterator m = s.end() - 1; - for (uoff_t i = 0; d > sp && i < s.size(); -- d) - for (i = 0; i < s.size(); ++ i) - if (m[-i] != d[-i]) - break; - return (d > sp ? distance (begin(), d + 2 - s.size()) : npos); -} - -/// Returns the offset of the first occurence of one of characters in \p s of size \p n after \p pos. -uoff_t string::find_first_of (const string& s, uoff_t pos) const -{ - for (uoff_t i = min(pos,size()); i < size(); ++ i) - if (s.find (at(i)) != npos) - return (i); - return (npos); -} - -/// Returns the offset of the first occurence of one of characters not in \p s of size \p n after \p pos. -uoff_t string::find_first_not_of (const string& s, uoff_t pos) const -{ - for (uoff_t i = min(pos,size()); i < size(); ++ i) - if (s.find (at(i)) == npos) - return (i); - return (npos); -} - -/// Returns the offset of the last occurence of one of characters in \p s of size \p n before \p pos. -uoff_t string::find_last_of (const string& s, uoff_t pos) const -{ - for (int i = min(pos,size()-1); i >= 0; -- i) - if (s.find (at(i)) != npos) - return (i); - return (npos); -} - -/// Returns the offset of the last occurence of one of characters not in \p s of size \p n before \p pos. -uoff_t string::find_last_not_of (const string& s, uoff_t pos) const -{ - for (int i = min(pos,size()-1); i >= 0; -- i) - if (s.find (at(i)) == npos) - return (i); - return (npos); -} - -/// Equivalent to a vsprintf on the string. -int string::vformat (const char* fmt, va_list args) -{ -#if HAVE_VA_COPY - va_list args2; -#else - #define args2 args - #undef __va_copy - #define __va_copy(x,y) -#endif - size_t rv = size(); - do { - reserve (rv); - __va_copy (args2, args); - rv = vsnprintf (data(), memblock::capacity(), fmt, args2); - rv = min (rv, memblock::capacity()); - } while (rv > capacity()); - resize (min (rv, capacity())); - return (rv); -} - -/// Equivalent to a sprintf on the string. -int string::format (const char* fmt, ...) -{ - va_list args; - va_start (args, fmt); - const int rv = vformat (fmt, args); - va_end (args); - return (rv); -} - -/// Returns the number of bytes required to write this object to a stream. -size_t string::stream_size (void) const -{ - return (Utf8Bytes(size()) + size()); -} - -/// Reads the object from stream \p os -void string::read (istream& is) -{ - char szbuf [8]; - is >> szbuf[0]; - size_t szsz (Utf8SequenceBytes (szbuf[0]) - 1), n = 0; - is.verify_remaining ("read", "ustl::string", szsz); - is.read (szbuf + 1, szsz); - n = *utf8in(szbuf); - is.verify_remaining ("read", "ustl::string", n); - resize (n); - is.read (data(), size()); -} - -/// Writes the object to stream \p os -void string::write (ostream& os) const -{ - const written_size_type sz (size()); - assert (sz == size() && "No support for writing strings larger than 4G"); - - char szbuf [8]; - utf8out_iterator szout (szbuf); - *szout = sz; - size_t szsz = distance (szbuf, szout.base()); - - os.verify_remaining ("write", "ustl::string", szsz + sz); - os.write (szbuf, szsz); - os.write (cdata(), sz); -} - -/// Returns a hash value for [first, last) -/*static*/ hashvalue_t string::hash (const char* first, const char* last) -{ - hashvalue_t h = 0; - // This has the bits flowing into each other from both sides of the number - for (; first < last; ++ first) - h = *first + ((h << 7) | (h >> BitsInType(hashvalue_t) - 7)); - return (h); -} - -} // namespace ustl - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustring.h b/media/libdrm/mobile2/src/util/ustl-1.0/ustring.h deleted file mode 100644 index 9ecf6e78631dbc11dbbbb20586036494c8fd23a6..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/ustring.h +++ /dev/null @@ -1,263 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// ustring.h -// - -#ifndef USTRING_H_1249CB7A098A9010763AAC6D37B133CF -#define USTRING_H_1249CB7A098A9010763AAC6D37B133CF - -#include "memblock.h" -#include "utf8.h" -#include // for va_list, va_start, and va_end (in string::format) - -namespace ustl { - -/// \class string ustring.h ustl.h -/// \ingroup Sequences -/// -/// \brief STL basic_string<char> equivalent. -/// -/// An STL container for text string manipulation. -/// Differences from C++ standard: -/// - string is a class, not a template. Wide characters are assumed to be -/// encoded with utf8 at all times except when rendering or editing, -/// where you would use a utf8 iterator. -/// - format member function - you can, of course use an \ref ostringstream, -/// which also have format functions, but most of the time this way -/// is more convenient. Because uSTL does not implement locales, -/// format is the only way to create localized strings. -/// - const char* cast operator. It is much clearer to use this than having -/// to type .c_str() every time. -/// - length returns the number of _characters_, not bytes. -/// This function is O(N), so use wisely. -/// -class string : public memblock { -public: - typedef char value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef wchar_t wvalue_type; - typedef wvalue_type* wpointer; - typedef const wvalue_type* const_wpointer; - typedef pointer iterator; - typedef const_pointer const_iterator; - typedef value_type& reference; - typedef value_type const_reference; - typedef ::ustl::reverse_iterator reverse_iterator; - typedef ::ustl::reverse_iterator const_reverse_iterator; - typedef utf8in_iterator utf8_iterator; -public: - static const uoff_t npos = static_cast(-1); ///< Value that means the end of string. - static const value_type c_Terminator = 0; ///< String terminator - static const size_type size_Terminator = sizeof(c_Terminator); ///< Most systems terminate strings with '\\0' - static const char empty_string [size_Terminator]; ///< An empty string. -public: - string (void); - string (const string& s); - inline string (const string& s, uoff_t o, size_type n); - inline explicit string (const cmemlink& l); - string (const_pointer s); - inline string (const_pointer s, size_type len); - inline string (const_pointer s1, const_pointer s2); - explicit string (size_type n, value_type c = c_Terminator); - inline pointer data (void) { return (string::pointer (memblock::data())); } - inline const_pointer c_str (void) const { return (string::const_pointer (memblock::cdata())); } - inline size_type max_size (void) const { size_type s (memblock::max_size()); return (s - !!s); } - inline size_type capacity (void) const { size_type c (memblock::capacity()); return (c - !!c); } - void resize (size_type n); - inline void clear (void) { resize (0); } - inline const_iterator begin (void) const { return (const_iterator (memblock::begin())); } - inline iterator begin (void) { return (iterator (memblock::begin())); } - inline const_iterator end (void) const { return (const_iterator (memblock::end())); } - inline iterator end (void) { return (iterator (memblock::end())); } - inline const_reverse_iterator rbegin (void) const { return (const_reverse_iterator (end())); } - inline reverse_iterator rbegin (void) { return (reverse_iterator (end())); } - inline const_reverse_iterator rend (void) const { return (const_reverse_iterator (begin())); } - inline reverse_iterator rend (void) { return (reverse_iterator (begin())); } - inline utf8_iterator utf8_begin (void) const { return (utf8_iterator (begin())); } - inline utf8_iterator utf8_end (void) const { return (utf8_iterator (end())); } - inline const_reference at (uoff_t pos) const { assert (pos <= size() && begin()); return (begin()[pos]); } - inline reference at (uoff_t pos) { assert (pos <= size() && begin()); return (begin()[pos]); } - inline const_iterator iat (uoff_t pos) const { return (begin() + min (pos, size())); } - inline iterator iat (uoff_t pos) { return (begin() + min (pos, size())); } - inline size_type length (void) const { return (distance (utf8_begin(), utf8_end())); } - inline void append (const_iterator i1, const_iterator i2) { append (i1, distance (i1, i2)); } - void append (const_pointer s, size_type len); - void append (const_pointer s); - void append (size_type n, const_reference c); - inline void append (size_type n, wvalue_type c) { insert (size(), c, n); } - inline void append (const_wpointer s1, const_wpointer s2) { insert (size(), s1, s2); } - inline void append (const_wpointer s) { const_wpointer se (s); for (;se&&*se;++se); append (s, se); } - inline void append (const string& s) { append (s.begin(), s.end()); } - inline void append (const string& s, uoff_t o, size_type n) { append (s.iat(o), s.iat(o+n)); } - inline void assign (const_iterator i1, const_iterator i2) { assign (i1, distance (i1, i2)); } - void assign (const_pointer s, size_type len); - void assign (const_pointer s); - inline void assign (const_wpointer s1, const_wpointer s2) { clear(); append (s1, s2); } - inline void assign (const_wpointer s1) { clear(); append (s1); } - inline void assign (const string& s) { assign (s.begin(), s.end()); } - inline void assign (const string& s, uoff_t o, size_type n) { assign (s.iat(o), s.iat(o+n)); } - size_type copyto (pointer p, size_type n, const_iterator start = NULL) const; - inline int compare (const string& s) const { return (compare (begin(), end(), s.begin(), s.end())); } - inline int compare (const_pointer s) const { return (compare (begin(), end(), s, s + strlen(s))); } - static int compare (const_iterator first1, const_iterator last1, const_iterator first2, const_iterator last2); - inline operator const value_type* (void) const; - inline operator value_type* (void); - inline const string& operator= (const string& s) { assign (s.begin(), s.end()); return (*this); } - inline const string& operator= (const_reference c) { assign (&c, 1); return (*this); } - inline const string& operator= (const_pointer s) { assign (s); return (*this); } - inline const string& operator= (const_wpointer s) { assign (s); return (*this); } - inline const string& operator+= (const string& s) { append (s.begin(), s.size()); return (*this); } - inline const string& operator+= (const_reference c) { append (1, c); return (*this); } - inline const string& operator+= (const_pointer s) { append (s); return (*this); } - inline const string& operator+= (wvalue_type c) { append (1, c); return (*this); } - inline const string& operator+= (const_wpointer s) { append (s); return (*this); } - inline string operator+ (const string& s) const; - inline bool operator== (const string& s) const { return (memblock::operator== (s)); } - bool operator== (const_pointer s) const; - inline bool operator== (const_reference c) const { return (size() == 1 && c == at(0)); } - inline bool operator!= (const string& s) const { return (!operator== (s)); } - inline bool operator!= (const_pointer s) const { return (!operator== (s)); } - inline bool operator!= (const_reference c) const { return (!operator== (c)); } - inline bool operator< (const string& s) const { return (0 > compare (s)); } - inline bool operator< (const_pointer s) const { return (0 > compare (s)); } - inline bool operator< (const_reference c) const { return (0 > compare (begin(), end(), &c, &c + 1)); } - inline bool operator> (const_pointer s) const { return (0 < compare (s)); } - void insert (const uoff_t ip, wvalue_type c, size_type n = 1); - void insert (const uoff_t ip, const_wpointer first, const_wpointer last, const size_type n = 1); - iterator insert (iterator start, const_reference c, size_type n = 1); - iterator insert (iterator start, const_pointer s, size_type n = 1); - iterator insert (iterator start, const_pointer first, const_iterator last, size_type n = 1); - inline void insert (uoff_t ip, const_pointer s, size_type nlen) { insert (iat(ip), s, s + nlen); } - inline void insert (uoff_t ip, size_type n, value_type c) { insert (iat(ip), c, n); } - inline void insert (uoff_t ip, const string& s, uoff_t sp, size_type slen) { insert (iat(ip), s.iat(sp), s.iat(sp + slen)); } - iterator erase (iterator start, size_type size = 1); - void erase (uoff_t start, size_type size = 1); - inline iterator erase (iterator first, const_iterator last) { return (erase (first, size_type(distance(first,last)))); } - OVERLOAD_POINTER_AND_SIZE_T_V2(erase, iterator) - inline void push_back (const_reference c) { append (1, c); } - inline void push_back (wvalue_type c) { append (1, c); } - inline void pop_back (void) { resize (size() - 1); } - void replace (iterator first, iterator last, const_pointer s); - void replace (iterator first, iterator last, const_pointer i1, const_pointer i2, size_type n = 1); - inline void replace (iterator first, iterator last, const string& s) { replace (first, last, s.begin(), s.end()); } - inline void replace (iterator first, iterator last, const_pointer s, size_type slen) { replace (first, last, s, s + slen); } - inline void replace (iterator first, iterator last, size_type n, value_type c) { replace (first, last, &c, &c + 1, n); } - inline void replace (uoff_t rp, size_type n, const string& s) { replace (iat(rp), iat(rp + n), s); } - inline void replace (uoff_t rp, size_type n, const string& s, uoff_t sp, size_type slen) { replace (iat(rp), iat(rp + n), s.iat(sp), s.iat(sp + slen)); } - inline void replace (uoff_t rp, size_type n, const_pointer s, size_type slen) { replace (iat(rp), iat(rp + n), s, s + slen); } - inline void replace (uoff_t rp, size_type n, const_pointer s) { replace (iat(rp), iat(rp + n), string(s)); } - inline void replace (uoff_t rp, size_type n, size_type count, value_type c) { replace (iat(rp), iat(rp + n), count, c); } - inline string substr (uoff_t o, size_type n) const { return (string (*this, o, n)); } - uoff_t find (const_reference c, uoff_t pos = 0) const; - uoff_t find (const string& s, uoff_t pos = 0) const; - uoff_t rfind (const_reference c, uoff_t pos = npos) const; - uoff_t rfind (const string& s, uoff_t pos = npos) const; - uoff_t find_first_of (const string& s, uoff_t pos = 0) const; - uoff_t find_first_not_of (const string& s, uoff_t pos = 0) const; - uoff_t find_last_of (const string& s, uoff_t pos = npos) const; - uoff_t find_last_not_of (const string& s, uoff_t pos = npos) const; - int vformat (const char* fmt, va_list args); - int format (const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))); - void read (istream&); - void write (ostream& os) const; - size_t stream_size (void) const; - static hashvalue_t hash (const char* f1, const char* l1); -private: - DLL_LOCAL iterator utf8_iat (uoff_t i); -protected: - inline virtual size_type minimumFreeCapacity (void) const { return (size_Terminator); } -}; - -//---------------------------------------------------------------------- - -/// Assigns itself the value of string \p s -inline string::string (const cmemlink& s) -: memblock () -{ - assign (const_iterator (s.begin()), s.size()); -} - -/// Assigns itself a [o,o+n) substring of \p s. -inline string::string (const string& s, uoff_t o, size_type n) -: memblock() -{ - assign (s, o, n); -} - -/// Copies the value of \p s of length \p len into itself. -inline string::string (const_pointer s, size_type len) -: memblock () -{ - assign (s, len); -} - -/// Copies into itself the string data between \p s1 and \p s2 -inline string::string (const_pointer s1, const_pointer s2) -: memblock () -{ - assert (s1 <= s2 && "Negative ranges result in memory allocation errors."); - assign (s1, s2); -} - -/// Returns the pointer to the first character. -inline string::operator const string::value_type* (void) const -{ - assert ((!end() || *end() == c_Terminator) && "This string is linked to data that is not 0-terminated. This may cause serious security problems. Please assign the data instead of linking."); - return (begin()); -} - -/// Returns the pointer to the first character. -inline string::operator string::value_type* (void) -{ - assert ((end() && *end() == c_Terminator) && "This string is linked to data that is not 0-terminated. This may cause serious security problems. Please assign the data instead of linking."); - return (begin()); -} - -/// Concatenates itself with \p s -inline string string::operator+ (const string& s) const -{ - string result (*this); - result += s; - return (result); -} - -//---------------------------------------------------------------------- -// Operators needed to avoid comparing pointer to pointer - -#define PTR_STRING_CMP(op, impl) \ -inline bool op (const char* s1, const string& s2) { return impl; } -PTR_STRING_CMP (operator==, (s2 == s1)) -PTR_STRING_CMP (operator!=, (s2 != s1)) -PTR_STRING_CMP (operator<, (s2 > s1)) -PTR_STRING_CMP (operator<=, (s2 >= s1)) -PTR_STRING_CMP (operator>, (s2 < s1)) -PTR_STRING_CMP (operator>=, (s2 <= s1)) -#undef PTR_STRING_CMP - -//---------------------------------------------------------------------- - -template -inline hashvalue_t hash_value (const T& v) -{ return (string::hash (v.begin(), v.end())); } - -template <> -inline hashvalue_t hash_value (const string::const_pointer& v) -{ return (string::hash (v, v + strlen(v))); } - -template <> -inline hashvalue_t hash_value (const string::pointer& v) -{ return (string::hash (v, v + strlen(v))); } - -//---------------------------------------------------------------------- - -} // namespace ustl - -// Specialization for stream alignment -ALIGNOF (ustl::string, alignof (string::value_type())) - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/utf8.h b/media/libdrm/mobile2/src/util/ustl-1.0/utf8.h deleted file mode 100644 index f829e7d6b92c154b10032f505b563a650a71ba42..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/utf8.h +++ /dev/null @@ -1,200 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// utf8.h -// -// This file contains stream iterators that read and write UTF-8 encoded -// characters. The encoding is defined as follows: -// -// U-00000000 - U-0000007F: 0xxxxxxx -// U-00000080 - U-000007FF: 110xxxxx 10xxxxxx -// U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx -// U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx -// U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx -// U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx -// U-80000000 - U-FFFFFFFF: 11111110 100000xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx -// -// The last range in not in the UTF-8 standard because Unicode forbids -// characters of those values. However, since ustl::string uses this code -// to write its length, the support is here. The reason it was put here -// in the first place, is that extra code would have been necessary to -// flag that range as invalid. -// -#ifndef UTF8_H_3D7AEEEB3A88928D4D280B785F78B6F4 -#define UTF8_H_3D7AEEEB3A88928D4D280B785F78B6F4 - -#include "uiterator.h" - -namespace ustl { - -//---------------------------------------------------------------------- - -typedef uint8_t utf8subchar_t; ///< Type for the encoding subcharacters. - -//---------------------------------------------------------------------- - -/// Returns the number of bytes required to UTF-8 encode \p v. -inline size_t Utf8Bytes (wchar_t v) -{ - static const uint32_t c_Bounds[] = { 0x0000007F, 0x000007FF, 0x0000FFFF, 0x001FFFFF, 0x03FFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, }; - size_t bi = 0; - while (c_Bounds[bi++] < uint32_t(v)); - return (bi); -} - -/// Returns the number of bytes in a UTF-8 sequence that starts with \p c. -inline size_t Utf8SequenceBytes (wchar_t c) // a wchar_t to keep c in a full register -{ - // Count the leading bits. Header bits are 1 * nBytes followed by a 0. - // 0 - single byte character. Take 7 bits (0xFF >> 1) - // 1 - error, in the middle of the character. Take 6 bits (0xFF >> 2) - // so you will keep reading invalid entries until you hit the next character. - // >2 - multibyte character. Take remaining bits, and get the next bytes. - // All errors are ignored, since the user can not correct them. - // - wchar_t mask = 0x80; - size_t nBytes = 0; - for (; c & mask; ++nBytes) - mask >>= 1; - return (nBytes ? nBytes : 1); // A sequence is always at least 1 byte. -} - -//---------------------------------------------------------------------- - -/// \class utf8in_iterator utf8.h ustl.h -/// \ingroup IteratorAdaptors -/// -/// \brief An iterator adaptor to character containers for reading UTF-8 encoded text. -/// -/// For example, you can copy from ustl::string to ustl::vector with -/// copy (utf8in (str.begin()), utf8in (str.end()), back_inserter(wvect)); -/// There is no error handling; if the reading frame slips you'll get extra -/// characters, one for every misaligned byte. Although it is possible to skip -/// to the start of the next character, that would result in omitting the -/// misformatted character and the one after it, making it very difficult to -/// detect by the user. It is better to write some strange characters and let -/// the user know his file is corrupted. Another problem is overflow on bad -/// encodings (like a 0xFF on the end of a string). This is checked through -/// the end-of-string nul character, which will always be there as long as -/// you are using the string class. -/// -template -class utf8in_iterator { -public: - typedef typename iterator_traits::value_type value_type; - typedef typename iterator_traits::difference_type difference_type; - typedef typename iterator_traits::pointer pointer; - typedef typename iterator_traits::reference reference; -public: - explicit utf8in_iterator (const Iterator& is) : m_i (is), m_v (0) { Read(); } - utf8in_iterator (const utf8in_iterator& i) : m_i (i.m_i), m_v (i.m_v) {} - inline const utf8in_iterator& operator= (const utf8in_iterator& i) { m_i = i.m_i; m_v = i.m_v; return (*this); } - inline Iterator base (void) const { return (m_i - (Utf8Bytes(m_v) - 1)); } - /// Reads and returns the next value. - inline WChar operator* (void) const { return (m_v); } - inline utf8in_iterator& operator++ (void) { ++m_i; Read(); return (*this); } - inline utf8in_iterator operator++ (int) { utf8in_iterator old (*this); operator++(); return (old); } - inline utf8in_iterator& operator+= (uoff_t n) { while (n--) operator++(); return (*this); } - inline utf8in_iterator operator+ (uoff_t n) { utf8in_iterator v (*this); return (v += n); } - inline bool operator== (const utf8in_iterator& i) const { return (m_i == i.m_i); } - inline bool operator< (const utf8in_iterator& i) const { return (m_i < i.m_i); } - difference_type operator- (const utf8in_iterator& i) const; -private: - void Read (void); -private: - Iterator m_i; - WChar m_v; -}; - -/// Steps to the next character and updates current returnable value. -template -void utf8in_iterator::Read (void) -{ - const utf8subchar_t c = *m_i; - size_t nBytes = Utf8SequenceBytes (c); - m_v = c & (0xFF >> nBytes); // First byte contains bits after the header. - while (--nBytes && *++m_i) // Each subsequent byte has 6 bits. - m_v = (m_v << 6) | (*m_i & 0x3F); -} - -/// Returns the distance in characters (as opposed to the distance in bytes). -template -typename utf8in_iterator::difference_type -utf8in_iterator::operator- (const utf8in_iterator& last) const -{ - difference_type dist = 0; - for (Iterator first (last.m_i); first < m_i; ++dist) - first = advance (first, Utf8SequenceBytes (*first)); - return (dist); -} - -//---------------------------------------------------------------------- - -/// \class utf8out_iterator utf8.h ustl.h -/// \ingroup IteratorAdaptors -/// -/// \brief An iterator adaptor to character containers for writing UTF-8 encoded text. -/// -template -class utf8out_iterator { -public: - typedef typename iterator_traits::value_type value_type; - typedef typename iterator_traits::difference_type difference_type; - typedef typename iterator_traits::pointer pointer; - typedef typename iterator_traits::reference reference; -public: - explicit utf8out_iterator (const Iterator& os) : m_i (os) {} - utf8out_iterator (const utf8out_iterator& i) : m_i (i.m_i) {} - inline const Iterator& base (void) const { return (m_i); } - /// Writes \p v into the stream. - utf8out_iterator& operator= (WChar v); - inline utf8out_iterator& operator* (void) { return (*this); } - inline utf8out_iterator& operator++ (void) { return (*this); } - inline utf8out_iterator operator++ (int) { return (*this); } - inline bool operator== (const utf8out_iterator& i) const { return (m_i == i.m_i); } - inline bool operator< (const utf8out_iterator& i) const { return (m_i < i.m_i); } -private: - Iterator m_i; -}; - -/// Writes \p v into the stream. -template -utf8out_iterator& utf8out_iterator::operator= (WChar v) -{ - const size_t nBytes = Utf8Bytes (v); - if (nBytes > 1) { - // Write the bits 6 bits at a time, except for the first one, - // which may be less than 6 bits. - register wchar_t shift = nBytes * 6; - *m_i++ = ((v >> (shift -= 6)) & 0x3F) | (0xFF << (8 - nBytes)); - while (shift) - *m_i++ = ((v >> (shift -= 6)) & 0x3F) | 0x80; - } else // If only one byte, there is no header. - *m_i++ = v; - return (*this); -} - -//---------------------------------------------------------------------- - -/// Returns a UTF-8 adaptor writing to \p i. Useful in conjuction with back_insert_iterator. -template -inline utf8out_iterator utf8out (Iterator i) -{ - return (utf8out_iterator (i)); -} - -/// Returns a UTF-8 adaptor reading from \p i. -template -inline utf8in_iterator utf8in (Iterator i) -{ - return (utf8in_iterator (i)); -} - -//---------------------------------------------------------------------- - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/utuple.h b/media/libdrm/mobile2/src/util/ustl-1.0/utuple.h deleted file mode 100644 index 8a003ab14f41754c08f809a4bb26412b6da78ea9..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/utuple.h +++ /dev/null @@ -1,247 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// utuple.h -// - -#ifndef UTUPLE_H_7324ADEC49B397CA74A56F6050FD5A6B -#define UTUPLE_H_7324ADEC49B397CA74A56F6050FD5A6B - -#include "ualgo.h" - -#if PLATFORM_ANDROID -#undef CPU_HAS_MMX -#endif - -namespace ustl { - -/// \class tuple utuple.h ustl.h -/// \ingroup Sequences -/// -/// \brief A fixed-size array of \p N \p Ts. -/// -template -class tuple { -public: - typedef T value_type; - typedef size_t size_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef pointer iterator; - typedef const_pointer const_iterator; - typedef ::ustl::reverse_iterator reverse_iterator; - typedef ::ustl::reverse_iterator const_reverse_iterator; - typedef pair range_t; - typedef pair const_range_t; -public: - template - inline tuple (const tuple& t); - inline tuple (const tuple& t); - inline tuple (const_pointer v); - inline tuple (void) { for (uoff_t i = 0; i < N; ++ i) m_v[i] = T(); } - explicit inline tuple (const_reference v0, const_reference v1 = T(), const_reference v2 = T(), const_reference v3 = T()); - inline iterator begin (void) { return (m_v); } - inline const_iterator begin (void) const { return (m_v); } - inline iterator end (void) { return (begin() + N); } - inline const_iterator end (void) const { return (begin() + N); } - inline size_type size (void) const { return (N); } - inline size_type max_size (void) const { return (N); } - inline bool empty (void) const { return (N == 0); } - inline const_reference at (size_type i) const { return (m_v[i]); } - inline reference at (size_type i) { return (m_v[i]); } - inline const_reference operator[] (size_type i) const { return (m_v[i]); } - inline reference operator[] (size_type i) { return (m_v[i]); } - template - inline const tuple& operator= (const tuple& src); - inline const tuple& operator= (const tuple& src); - inline const tuple& operator+= (const_reference v) - { for (uoff_t i = 0; i < N; ++ i) m_v[i] += v; return (*this); } - inline const tuple& operator-= (const_reference v) - { for (uoff_t i = 0; i < N; ++ i) m_v[i] -= v; return (*this); } - inline const tuple& operator*= (const_reference v) - { for (uoff_t i = 0; i < N; ++ i) m_v[i] *= v; return (*this); } - inline const tuple& operator/= (const_reference v) - { for (uoff_t i = 0; i < N; ++ i) m_v[i] /= v; return (*this); } - inline const tuple operator+ (const_reference v) const - { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] + v; return (result); } - inline const tuple operator- (const_reference v) const - { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] - v; return (result); } - inline const tuple operator* (const_reference v) const - { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] * v; return (result); } - inline const tuple operator/ (const_reference v) const - { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] / v; return (result); } - inline void swap (tuple& v) - { for (uoff_t i = 0; i < N; ++ i) ::ustl::swap (m_v[i], v.m_v[i]); } -private: - T m_v [N]; -}; - -} // namespace ustl - -#include "simd.h" - -namespace ustl { - -template -template -inline tuple::tuple (const tuple& t) -{ simd::pconvert (t, *this, simd::fcast()); } - -template -inline tuple::tuple (const tuple& t) -{ simd::passign (t, *this); } - -template -inline tuple::tuple (const_pointer v) -{ simd::ipassign (v, *this); } - -template -inline tuple::tuple (const_reference v0, const_reference v1, const_reference v2, const_reference v3) -{ - m_v[0] = v0; - if (N > 1) m_v[1] = v1; - if (N > 2) m_v[2] = v2; - if (N > 3) m_v[3] = v3; - if (N > 4) fill_n (m_v + 4, N - 4, T()); -} - -template -template -inline const tuple& tuple::operator= (const tuple& src) -{ simd::pconvert (src, *this, simd::fcast()); return (*this); } - -template -inline const tuple& tuple::operator= (const tuple& src) -{ simd::passign (src, *this); return (*this); } - -template -inline bool operator== (const tuple& t1, const tuple& t2) -{ - for (uoff_t i = 0; i < N; ++ i) - if (t1[i] != t2[i]) - return (false); - return (true); -} - -template -inline bool operator< (const tuple& t1, const tuple& t2) -{ - for (uoff_t i = 0; i < N && t1[i] <= t2[i]; ++ i) - if (t1[i] < t2[i]) - return (true); - return (false); -} - -template -inline const tuple& operator+= (tuple& t1, const tuple& t2) - { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] + t2[i]); return (t1); } - -template -inline const tuple& operator-= (tuple& t1, const tuple& t2) - { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] - t2[i]); return (t1); } - -template -inline const tuple& operator*= (tuple& t1, const tuple& t2) - { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] * t2[i]); return (t1); } - -template -inline const tuple& operator/= (tuple& t1, const tuple& t2) - { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] / t2[i]); return (t1); } - -template -inline const tuple operator+ (const tuple& t1, const tuple& t2) -{ - tuple result; - for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] + t2[i]); - return (result); -} - -template -inline const tuple operator- (const tuple& t1, const tuple& t2) -{ - tuple result; - for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] - t2[i]); - return (result); -} - -template -inline const tuple operator* (const tuple& t1, const tuple& t2) -{ - tuple result; - for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] * t2[i]); - return (result); -} - -template -inline const tuple operator/ (const tuple& t1, const tuple& t2) -{ - tuple result; - for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] / t2[i]); - return (result); -} - -#if CPU_HAS_SSE -#define SSE_TUPLE_SPECS(n,type) \ -template <> inline tuple::tuple (void) \ -{ asm ("xorps %%xmm0, %%xmm0\n\tmovups %%xmm0, %0"::"m"(m_v[0]):"xmm0","memory"); } \ -template<> inline void tuple::swap (tuple& v) \ -{ asm ("movups %0,%%xmm0\n\tmovups %1,%%xmm1\n\tmovups %%xmm0,%1\n\tmovups %%xmm1,%0"::"m"(m_v[0]),"m"(v.m_v[0]):"xmm0","xmm1","memory"); } -SSE_TUPLE_SPECS(4,float) -SSE_TUPLE_SPECS(4,int32_t) -SSE_TUPLE_SPECS(4,uint32_t) -#undef SSE_TUPLE_SPECS -#endif -#if CPU_HAS_MMX -#define MMX_TUPLE_SPECS(n,type) \ -template <> inline tuple::tuple (void) \ -{ asm ("pxor %%mm0, %%mm0\n\tmovq %%mm0, %0"::"m"(m_v[0]):"mm0","memory"); simd::reset_mmx(); } \ -template<> inline void tuple::swap (tuple& v) \ -{ asm ("movq %0,%%mm0\n\tmovq %1,%%mm1\n\tmovq %%mm0,%1\n\tmovq %%mm1,%0"::"m"(m_v[0]),"m"(v.m_v[0]):"mm0","mm1","memory"); simd::reset_mmx(); } -MMX_TUPLE_SPECS(2,float) -MMX_TUPLE_SPECS(4,int16_t) -MMX_TUPLE_SPECS(4,uint16_t) -MMX_TUPLE_SPECS(2,int32_t) -MMX_TUPLE_SPECS(2,uint32_t) -MMX_TUPLE_SPECS(8,int8_t) -MMX_TUPLE_SPECS(8,uint8_t) -#undef MMX_TUPLE_SPECS -#endif - -#define SIMD_TUPLE_PACKOP(N,T) \ -template <> inline const tuple& operator+= (tuple& t1, const tuple& t2) \ - { simd::padd (t2, t1); return (t1); } \ -template <> inline const tuple& operator-= (tuple& t1, const tuple& t2) \ - { simd::psub (t2, t1); return (t1); } \ -template <> inline const tuple& operator*= (tuple& t1, const tuple& t2) \ - { simd::pmul (t2, t1); return (t1); } \ -template <> inline const tuple& operator/= (tuple& t1, const tuple& t2) \ - { simd::pdiv (t2, t1); return (t1); } \ -template <> inline const tuple operator+ (const tuple& t1, const tuple& t2) \ - { tuple result (t1); simd::padd (t2, result); return (result); } \ -template <> inline const tuple operator- (const tuple& t1, const tuple& t2) \ - { tuple result (t1); simd::psub (t2, result); return (result); } \ -template <> inline const tuple operator* (const tuple& t1, const tuple& t2) \ - { tuple result (t1); simd::pmul (t2, result); return (result); } \ -template <> inline const tuple operator/ (const tuple& t1, const tuple& t2) \ - { tuple result (t1); simd::pdiv (t2, result); return (result); } -SIMD_TUPLE_PACKOP(4,float) -SIMD_TUPLE_PACKOP(2,float) -SIMD_TUPLE_PACKOP(2,double) -SIMD_TUPLE_PACKOP(4,int32_t) -SIMD_TUPLE_PACKOP(4,uint32_t) -SIMD_TUPLE_PACKOP(4,int16_t) -SIMD_TUPLE_PACKOP(4,uint16_t) -SIMD_TUPLE_PACKOP(2,int32_t) -SIMD_TUPLE_PACKOP(2,uint32_t) -SIMD_TUPLE_PACKOP(8,int8_t) -SIMD_TUPLE_PACKOP(8,uint8_t) -#undef SIMD_TUPLE_PACKOP - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/utypes.h b/media/libdrm/mobile2/src/util/ustl-1.0/utypes.h deleted file mode 100644 index f0b0265ebf6ad5e44be7676e80df57ac74211161..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/utypes.h +++ /dev/null @@ -1,69 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// utypes.h -// -// Types used by this library. -// - -#ifndef UTYPES_H_118BBB3B50B7DBF22F5460C52E515C83 -#define UTYPES_H_118BBB3B50B7DBF22F5460C52E515C83 - -#include "config.h" -#ifndef STDC_HEADERS - #error This library requires standard C and C++ headers to compile. -#endif -#ifndef STDUNIX_HEADERS - #error This library compiles only on UNIX systems. -#endif -#define __STDC_LIMIT_MACROS // For WCHAR_MIN and WCHAR_MAX in stdint. -#define __STDC_CONSTANT_MACROS // For UINT??_C macros to avoid using L and UL suffixes on constants. -#ifdef HAVE_STDINT_H - #include -#elif HAVE_INTTYPES_H - #include -#else - #error Need standard integer types definitions, usually in stdint.h -#endif -#include // For ptrdiff_t, size_t -#include -#include -#ifdef HAVE_SYS_TYPES_H - #include -#endif -#ifndef SIZE_MAX - #define SIZE_MAX UINT_MAX -#endif -#if sun || __sun // Solaris defines UINTPTR_MAX as empty. - #undef UINTPTR_MAX - #define UINTPTR_MAX ULONG_MAX -#endif -#ifndef WCHAR_MAX - #ifdef __WCHAR_MAX__ - #define WCHAR_MAX __WCHAR_MAX__ - #else - #define WCHAR_MAX CHAR_MAX - #endif -#endif -#ifdef HAVE_LONG_LONG - #ifndef LLONG_MAX - #define ULLONG_MAX UINT64_C(0xFFFFFFFFFFFFFFFF) - #define LLONG_MAX INT64_C(0x7FFFFFFFFFFFFFFF) - #define LLONG_MIN ULLONG_MAX - #endif -#endif -#if !PLATFORM_ANDROID -#ifndef BYTE_ORDER - #define LITTLE_ENDIAN USTL_LITTLE_ENDIAN - #define BIG_ENDIAN USTL_BIG_ENDIAN - #define BYTE_ORDER USTL_BYTE_ORDER -#endif -#endif - -typedef size_t uoff_t; ///< A type for storing offsets into blocks measured by size_t. -typedef uint32_t hashvalue_t; ///< Value type returned by the hash functions. - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uutility.h b/media/libdrm/mobile2/src/util/ustl-1.0/uutility.h deleted file mode 100644 index 7b5ae649768ed0c869761a28d92dad3165a67c7a..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uutility.h +++ /dev/null @@ -1,387 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -/// \file uutility.h -/// -/// \brief Utility templates. -/// -/// Everything in here except min(), max(), distance(), and advance() -/// are uSTL extensions and are absent from other STL implementations. -/// - -#ifndef UUTILITY_H_6A58BD296269A82A4AAAA4FD19FDB3AC -#define UUTILITY_H_6A58BD296269A82A4AAAA4FD19FDB3AC - -#include "uassert.h" -#include "utypes.h" - -#if PLATFORM_ANDROID -#include -#undef CPU_HAS_MMX -#endif - -namespace ustl { - -#ifdef __GNUC__ - /// Returns the number of elements in a static vector - #define VectorSize(v) (sizeof(v) / sizeof(*v)) -#else - // Old compilers will not be able to evaluate *v on an empty vector. - // The tradeoff here is that VectorSize will not be able to measure arrays of local structs. - #define VectorSize(v) (sizeof(v) / ustl::size_of_elements(1, v)) -#endif - -/// Expands into a ptr,size expression for the given static vector; useful as link arguments. -#define VectorBlock(v) (v)+0, VectorSize(v) // +0 makes it work under gcc 2.95 -/// Expands into a begin,end expression for the given static vector; useful for algorithm arguments. -#define VectorRange(v) VectorBlock(v)+(v) - -/// Returns the number of bits in the given type -#define BitsInType(t) (sizeof(t) * CHAR_BIT) - -/// Returns the mask of type \p t with the lowest \p n bits set. -#define BitMask(t,n) (t(~t(0)) >> ((sizeof(t) * CHAR_BIT) - (n))) - -/// Argument that is used only in debug builds (as in an assert) -#ifndef NDEBUG - #define DebugArg(x) x -#else - #define DebugArg(x) -#endif - -/// Shorthand for container iteration. -#define foreach(type,i,ctr) for (type i = (ctr).begin(); i != (ctr).end(); ++ i) -/// Shorthand for container reverse iteration. -#define eachfor(type,i,ctr) for (type i = (ctr).rbegin(); i != (ctr).rend(); ++ i) - -/// Macro for passing template types as macro arguments. -/// \@{ -#define TEMPLATE_FULL_DECL1(d1,t1) template -#define TEMPLATE_FULL_DECL2(d1,t1,d2,t2) template -#define TEMPLATE_FULL_DECL3(d1,t1,d2,t2,d3,t3) template -#define TEMPLATE_DECL1(t1) TEMPLATE_FULL_DECL1(typename,t1) -#define TEMPLATE_DECL2(t1,t2) TEMPLATE_FULL_DECL2(typename,t1,typename,t2) -#define TEMPLATE_DECL3(t1,t2,t3) TEMPLATE_FULL_DECL3(typename,t1,typename,t2,typename,t3) -#define TEMPLATE_TYPE1(type,a1) type -#define TEMPLATE_TYPE2(type,a1,a2) type -#define TEMPLATE_TYPE3(type,a1,a2,a3) type -/// \@} - -/// Returns the minimum of \p a and \p b -template -inline const T1 min (const T1& a, const T2& b) -{ - return (a < b ? a : b); -} - -/// Returns the maximum of \p a and \p b -template -inline const T1 max (const T1& a, const T2& b) -{ - return (b < a ? a : b); -} - -/// \brief Divides \p n1 by \p n2 and rounds the result up. -/// This is in contrast to regular division, which rounds down. -/// Negative numbers are rounded down because they are an unusual case, supporting -/// which would require a branch. Since this is frequently used in graphics, the -/// speed is important. -/// -template -inline T1 DivRU (T1 n1, T2 n2) -{ - return (n1 / n2 + (n1 % n2 > 0)); -} - -/// The alignment performed by default. -const size_t c_DefaultAlignment = __alignof__(void*); - -/// \brief Rounds \p n up to be divisible by \p grain -template -inline T Align (T n, size_t grain = c_DefaultAlignment) -{ - T a, r = n % grain; - if (grain == 2) return (n + r); - switch (grain) { - case 4: case 8: case 16: a = (n & ~(grain - 1)) + grain; break; - default: a = n + (grain - r); - }; - return (r ? a : n); -} - -/// Offsets an iterator -template -inline T advance (T i, ssize_t offset) -{ - return (i + offset); -} - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -/// Offsets a void pointer -template <> -inline const void* advance (const void* p, ssize_t offset) -{ - assert (p || !offset); - return (reinterpret_cast(p) + offset); -} - -/// Offsets a void pointer -template <> -inline void* advance (void* p, ssize_t offset) -{ - assert (p || !offset); - return (reinterpret_cast(p) + offset); -} -#endif - -/// Returns the difference \p p1 - \p p2 -template -inline ptrdiff_t distance (T1 i1, T2 i2) -{ - return (i2 - i1); -} - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -#define UNVOID_DISTANCE(T1const,T2const) \ -template <> inline ptrdiff_t distance (T1const void* p1, T2const void* p2) \ -{ return ((T2const uint8_t*)(p2) - (T1const uint8_t*)(p1)); } -UNVOID_DISTANCE(,) -UNVOID_DISTANCE(const,const) -UNVOID_DISTANCE(,const) -UNVOID_DISTANCE(const,) -#undef UNVOID_DISTANCE -#endif - -/// \brief Returns the absolute value of \p v -/// Unlike the stdlib functions, this is inline and works with all types. -template -inline T absv (T v) -{ - return (v < 0 ? -v : v); -} - -/// \brief Returns -1 for negative values, 1 for positive, and 0 for 0 -template -inline T sign (T v) -{ - return ((0 < v) - (v < 0)); -} - -/// Returns the absolute value of the distance i1 and i2 -template -inline size_t abs_distance (T1 i1, T2 i2) -{ - return (absv (distance(i1, i2))); -} - -/// Returns the size of \p n elements of size \p T -template -inline size_t size_of_elements (size_t n, const T*) -{ - return (n * sizeof(T)); -} - -// Defined in byteswap.h, which is usually unusable. -#undef bswap_16 -#undef bswap_32 -#undef bswap_64 - -#if CPU_HAS_CMPXCHG8 // If it has that, it has bswap. -inline uint16_t bswap_16 (uint16_t v) { asm ("rorw $8, %w0" : "=r"(v) : "0"(v) : "cc"); return (v); } -inline uint32_t bswap_32 (uint32_t v) { asm ("bswap %0" : "=r"(v) : "0"(v)); return (v); } -#else -inline uint16_t bswap_16 (uint16_t v) { return (v << 8 | v >> 8); } -inline uint32_t bswap_32 (uint32_t v) { return (v << 24 | (v & 0xFF00) << 8 | (v >> 8) & 0xFF00 | v >> 24); } -#endif -#if HAVE_INT64_T -inline uint64_t bswap_64 (uint64_t v) { return ((uint64_t(bswap_32(v)) << 32) | bswap_32(v >> 32)); } -#endif - -/// \brief Swaps the byteorder of \p v. -template -inline T bswap (const T& v) -{ - switch (BitsInType(T)) { - default: return (v); - case 16: return (T (bswap_16 (uint16_t (v)))); - case 32: return (T (bswap_32 (uint32_t (v)))); -#if HAVE_INT64_T - case 64: return (T (bswap_64 (uint64_t (v)))); -#endif - }; -} - -#if USTL_BYTE_ORDER == USTL_BIG_ENDIAN -template inline T le_to_native (const T& v) { return (bswap (v)); } -template inline T be_to_native (const T& v) { return (v); } -template inline T native_to_le (const T& v) { return (bswap (v)); } -template inline T native_to_be (const T& v) { return (v); } -#elif USTL_BYTE_ORDER == USTL_LITTLE_ENDIAN -template inline T le_to_native (const T& v) { return (v); } -template inline T be_to_native (const T& v) { return (bswap (v)); } -template inline T native_to_le (const T& v) { return (v); } -template inline T native_to_be (const T& v) { return (bswap (v)); } -#endif // USTL_BYTE_ORDER - -/// Deletes \p p and sets it to NULL -template -inline void Delete (T*& p) -{ - delete p; - p = NULL; -} - -/// Deletes \p p as an array and sets it to NULL -template -inline void DeleteVector (T*& p) -{ - delete [] p; - p = NULL; -} - -/// Template of making != from ! and == -template -inline bool operator!= (const T& x, const T& y) -{ - return (!(x == y)); -} - -/// Template of making > from < -template -inline bool operator> (const T& x, const T& y) -{ - return (y < x); -} - -/// Template of making <= from < and == -template -inline bool operator<= (const T& x, const T& y) -{ - return (!(y < x)); -} - -/// Template of making >= from < and == -template -inline bool operator>= (const T& x, const T& y) -{ - return (!(x < y)); -} - -/// Packs \p s multiple times into \p b. Useful for loop unrolling. -template -inline void pack_type (TSmall s, TBig& b) -{ - const size_t n = sizeof(TBig) / sizeof(TSmall); - b = s; - // Calls to min are here to avoid warnings for shifts bigger than the type. min will be gone when optimized. - if (n < 2) return; - b = (b << min (BitsInType(TSmall), BitsInType(TBig))) | b; - if (n < 4) return; - b = (b << min (BitsInType(TSmall) * 2, BitsInType(TBig))) | b; - if (n < 8) return; - b = (b << min (BitsInType(TSmall) * 4, BitsInType(TBig))) | b; -} - -#if __GNUC__ >= 3 -inline bool TestAndSet (int* pm) __attribute__((always_inline)); -#endif -/// Sets the contents of \p pm to 1 and returns true if the previous value was 0. -inline bool TestAndSet (int* pm) -{ -#if CPU_HAS_CMPXCHG8 - bool rv; - int oldVal (1); - asm volatile ( // cmpxchg compares to %eax and swaps if equal - "cmpxchgl %3, %1\n\t" - "sete %0" - : "=a" (rv), "=m" (*pm), "=r" (oldVal) - : "2" (oldVal), "a" (0) - : "memory"); - return (rv); -#elif __i386__ || __x86_64__ - int oldVal (1); - asm volatile ("xchgl %0, %1" : "=r"(oldVal), "=m"(*pm) : "0"(oldVal), "m"(*pm) : "memory"); - return (!oldVal); -#elif __sparc32__ // This has not been tested - int rv; - asm volatile ("ldstub %1, %0" : "=r"(rv), "=m"(*pm) : "m"(pm)); - return (!rv); -#else - const int oldVal (*pm); - *pm = 1; - return (!oldVal); -#endif -} - -/// \brief This template is to be used for dereferencing a type-punned pointer without a warning. -/// -/// When casting a local variable to an unrelated type through a pointer (for -/// example, casting a float to a uint32_t without conversion), the resulting -/// memory location can be accessed through either pointer, which violates the -/// strict aliasing rule. While -fno-strict-aliasing option can be given to -/// the compiler, eliminating this warning, inefficient code may result in -/// some instances, because aliasing inhibits some optimizations. By using -/// this template, and by ensuring the memory is accessed in one way only, -/// efficient code can be produced without the warning. For gcc 4.1.0+. -/// -template -inline DEST noalias (DEST, SRC* s) -{ - union UPun { SRC s; DEST d; }; - return (((UPun*)(s))->d); -} - -namespace simd { - /// Call after you are done using SIMD algorithms for 64 bit tuples. -#if CPU_HAS_MMX - inline void reset_mmx (void) __attribute__((always_inline)); - #define ALL_MMX_REGS_CHANGELIST "mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7","st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)" - #if CPU_HAS_3DNOW - inline void reset_mmx (void) { asm ("femms":::ALL_MMX_REGS_CHANGELIST); } - #else - inline void reset_mmx (void) { asm ("emms":::ALL_MMX_REGS_CHANGELIST); } - #endif -#else - inline void reset_mmx (void) {} -#endif -} // namespace simd - -/// \brief Type that is not size_t -/// -/// Because size_t may be declared as unsigned long or unsigned int on -/// different machines, this macro is convenient when defining overloads -/// of size_t to use other types. -/// -#if defined(SIZE_T_IS_LONG) && !defined(__ARM_EABI__) - #define NOT_SIZE_T_I_OR_L unsigned int -#else - #define NOT_SIZE_T_I_OR_L unsigned long -#endif - -/// \brief Required when you want to overload size_t and a pointer. -/// -/// The compiler will happily cast a number to a pointer and declare -/// that the overload is ambiguous unless you define overloads for all -/// possible integral types that a number may represent. This behaviour, -/// although braindead, is in the ANSI standard, and thus not a bug. If -/// you want to change the standard, the best solution is to disallow any -/// implicit casts to pointer from an integral type. Ironically, such an -/// implicit cast is already detected by gcc. -/// -#if defined(USTL_ANDROID_X86) -#define OVERLOAD_POINTER_AND_SIZE_T_V2(name, arg1type) -#else -#define OVERLOAD_POINTER_AND_SIZE_T_V2(name, arg1type) \ - inline void name (arg1type a1, short a2) { name (a1, size_t(a2)); } \ - inline void name (arg1type a1, unsigned short a2) { name (a1, size_t(a2)); } \ - inline void name (arg1type a1, int a2) { name (a1, size_t(a2)); } \ - inline void name (arg1type a1, long a2) { name (a1, size_t(a2)); } \ - inline void name (arg1type a1, NOT_SIZE_T_I_OR_L a2) { name (a1, size_t(a2)); } -#endif -} // namespace ustl - - -#endif - diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uvector.h b/media/libdrm/mobile2/src/util/ustl-1.0/uvector.h deleted file mode 100644 index ccbc45b327e9d14558e296df59c5d5fe95630f68..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/ustl-1.0/uvector.h +++ /dev/null @@ -1,277 +0,0 @@ -// This file is part of the ustl library, an STL implementation. -// -// Copyright (C) 2005 by Mike Sharov -// This file is free software, distributed under the MIT License. -// -// uvector.h -// - -#ifndef UVECTOR_H_00BB13AF082BEB7829C031B265518169 -#define UVECTOR_H_00BB13AF082BEB7829C031B265518169 - -#include "uassert.h" -#include "memblock.h" -#include "umemory.h" - -namespace ustl { - -/// \class vector uvector.h ustl.h -/// \ingroup Sequences -/// -/// \brief STL vector equivalent. -/// -/// Provides a typed array-like interface to a managed memory block, including -/// element access, iteration, modification, resizing, and serialization. In -/// this design elements frequently undergo bitwise move, so don't put it in -/// here if it doesn't support it. This mostly means having no self-pointers. -/// -template -class vector { -public: - typedef T value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef pointer iterator; - typedef const_pointer const_iterator; - typedef memblock::size_type size_type; - typedef memblock::written_size_type written_size_type; - typedef memblock::difference_type difference_type; - typedef ::ustl::reverse_iterator reverse_iterator; - typedef ::ustl::reverse_iterator const_reverse_iterator; -public: - inline vector (void); - inline explicit vector (size_type n); - vector (size_type n, const T& v); - vector (const vector& v); - vector (const_iterator i1, const_iterator i2); - ~vector (void) throw(); - inline const vector& operator= (const vector& v); - inline bool operator== (const vector& v) { return (m_Data == v.m_Data); } - inline operator cmemlink (void) const { return (cmemlink (m_Data)); } - inline operator cmemlink (void) { return (cmemlink (m_Data)); } - inline operator memlink (void) { return (memlink (m_Data)); } - inline void reserve (size_type n, bool bExact = true); - inline void resize (size_type n, bool bExact = true); - inline size_type capacity (void) const { return (m_Data.capacity() / sizeof(T)); } - inline size_type size (void) const { return (m_Data.size() / sizeof(T)); } - inline size_type max_size (void) const { return (m_Data.max_size() / sizeof(T)); } - inline bool empty (void) const { return (m_Data.empty()); } - inline iterator begin (void) { return (iterator (m_Data.begin())); } - inline const_iterator begin (void) const { return (const_iterator (m_Data.begin())); } - inline iterator end (void) { return (iterator (m_Data.end())); } - inline const_iterator end (void) const { return (const_iterator (m_Data.end())); } - inline reverse_iterator rbegin (void) { return (reverse_iterator (end())); } - inline const_reverse_iterator rbegin (void) const { return (const_reverse_iterator (end())); } - inline reverse_iterator rend (void) { return (reverse_iterator (begin())); } - inline const_reverse_iterator rend (void) const { return (const_reverse_iterator (begin())); } - inline iterator iat (size_type i) { assert (i <= size()); return (begin() + i); } - inline const_iterator iat (size_type i) const { assert (i <= size()); return (begin() + i); } - inline reference at (size_type i) { assert (i < size()); return (begin()[i]); } - inline const_reference at (size_type i) const { assert (i < size()); return (begin()[i]); } - inline reference operator[] (size_type i) { return (at (i)); } - inline const_reference operator[] (size_type i) const { return (at (i)); } - inline reference front (void) { return (at(0)); } - inline const_reference front (void) const { return (at(0)); } - inline reference back (void) { assert (!empty()); return (end()[-1]); } - inline const_reference back (void) const { assert (!empty()); return (end()[-1]); } - inline void push_back (const T& v = T()); - inline void pop_back (void) { m_Data.memlink::resize (m_Data.size() - sizeof(T)); } - inline void clear (void) { m_Data.clear(); } - void deallocate (void) throw(); - inline void assign (const_iterator i1, const_iterator i2); - inline void assign (size_type n, const T& v); - inline void swap (vector& v) { m_Data.swap (v.m_Data); } - inline iterator insert (iterator ip, const T& v = T()); - inline iterator insert (iterator ip, size_type n, const T& v); - inline iterator insert (iterator ip, const_iterator i1, const_iterator i2); - inline iterator erase (iterator ep, size_type n = 1); - inline iterator erase (iterator ep1, iterator ep2); - inline void manage (pointer p, size_type n) { m_Data.manage (p, n * sizeof(T)); } - inline bool is_linked (void) const { return (m_Data.is_linked()); } - inline void unlink (void) { m_Data.unlink(); } - inline void copy_link (void) { m_Data.copy_link(); } - inline void link (const_pointer p, size_type n) { m_Data.link (p, n * sizeof(T)); } - inline void link (pointer p, size_type n) { m_Data.link (p, n * sizeof(T)); } - inline void link (const vector& v) { m_Data.link (v); } - inline void link (vector& v) { m_Data.link (v); } - inline void link (const_pointer first, const_pointer last) { m_Data.link (first, last); } - inline void link (pointer first, pointer last) { m_Data.link (first, last); } - OVERLOAD_POINTER_AND_SIZE_T_V2(link, pointer) - OVERLOAD_POINTER_AND_SIZE_T_V2(link, const_pointer) -private: - inline iterator insert_space (iterator ip, size_type n); -private: - memblock m_Data; ///< Raw element data, consecutively stored. -}; - -/// Allocates space for at least \p n elements. -template -void vector::reserve (size_type n, bool bExact) -{ - const size_type oldCapacity = capacity(); - m_Data.reserve (n * sizeof(T), bExact); - if (capacity() > oldCapacity) - construct (begin() + oldCapacity, begin() + capacity()); -} - -/// Resizes the vector to contain \p n elements. -template -void vector::resize (size_type n, bool bExact) -{ - if (m_Data.capacity() < n * sizeof(T)) - reserve (n, bExact); - m_Data.memlink::resize (n * sizeof(T)); -} - -/// Calls element destructors and frees storage. -template -void vector::deallocate (void) throw() -{ - if (!is_linked()) - destroy (begin(), begin() + capacity()); - m_Data.deallocate(); -} - -/// Initializes empty vector. -template -inline vector::vector (void) -: m_Data () -{ -} - -/// Initializes a vector of size \p n. -template -inline vector::vector (size_type n) -: m_Data () -{ - resize (n); -} - -/// Copies \p n elements from \p v. -template -vector::vector (size_type n, const T& v) -: m_Data () -{ - resize (n); - ::ustl::fill (begin(), end(), v); -} - -/// Copies \p v. -template -vector::vector (const vector& v) -: m_Data () -{ - resize (v.size()); - ::ustl::copy (v.begin(), v.end(), begin()); -} - -/// Copies range [\p i1, \p i2] -template -vector::vector (const_iterator i1, const_iterator i2) -: m_Data () -{ - resize (distance (i1, i2)); - ::ustl::copy (i1, i2, begin()); -} - -/// Destructor -template -inline vector::~vector (void) throw() -{ - if (!numeric_limits::is_integral) - deallocate(); -} - -/// Copies the range [\p i1, \p i2] -template -inline void vector::assign (const_iterator i1, const_iterator i2) -{ - assert (i1 <= i2); - resize (distance (i1, i2)); - ::ustl::copy (i1, i2, begin()); -} - -/// Copies \p n elements with value \p v. -template -inline void vector::assign (size_type n, const T& v) -{ - resize (n); - ::ustl::fill (begin(), end(), v); -} - -/// Copies contents of \p v. -template -inline const vector& vector::operator= (const vector& v) -{ - assign (v.begin(), v.end()); - return (*this); -} - -/// Inserts \p n uninitialized elements at \p ip. -template -typename vector::iterator vector::insert_space (iterator ip, size_type n) -{ - const uoff_t ipmi = distance (m_Data.begin(), memblock::iterator(ip)); - reserve (size() + n, false); - return (iterator (m_Data.insert (m_Data.iat(ipmi), n * sizeof(T)))); -} - -/// Inserts \p n elements with value \p v at offsets \p ip. -template -typename vector::iterator vector::insert (iterator ip, size_type n, const T& v) -{ - ip = insert_space (ip, n); - ::ustl::fill (ip, ip + n, v); - return (ip); -} - -/// Inserts value \p v at offset \p ip. -template -typename vector::iterator vector::insert (iterator ip, const T& v) -{ - *(ip = insert_space (ip, 1)) = v; - return (ip); -} - -/// Inserts range [\p i1, \p i2] at offset \p ip. -template -typename vector::iterator vector::insert (iterator ip, const_iterator i1, const_iterator i2) -{ - assert (i1 <= i2); - ip = insert_space (ip, distance (i1, i2)); - ::ustl::copy (i1, i2, ip); - return (ip); -} - -/// Removes \p count elements at offset \p ep. -template -inline typename vector::iterator vector::erase (iterator ep, size_type n) -{ - return (iterator (m_Data.erase (memblock::iterator(ep), n * sizeof(T)))); -} - -/// Removes elements from \p ep1 to \p ep2. -template -inline typename vector::iterator vector::erase (iterator ep1, iterator ep2) -{ - assert (ep1 <= ep2); - return (erase (ep1, distance(ep1, ep2))); -} - -/// Inserts value \p v at the end of the vector. -template -void vector::push_back (const T& v) -{ - resize (size() + 1, false); - back() = v; -} - -/// Use with vector classes to allocate and link to stack space. \p n is in elements. -#define typed_alloca_link(m,T,n) (m).link ((T*) alloca ((n) * sizeof(T)), (n)) - -} // namespace ustl - -#endif - diff --git a/media/libdrm/mobile2/src/util/xml/DomExpatAgent.cpp b/media/libdrm/mobile2/src/util/xml/DomExpatAgent.cpp deleted file mode 100644 index 4cde706ec1528ff059dabf7cb2a561ec50851830..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/xml/DomExpatAgent.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - * 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. - */ -#include -#include -#include -#include -using namespace ustl; - -/** see DomExpatAgent.h */ -DomExpatAgent::DomExpatAgent(XMLDocumentImpl* xmlDocPtr) -{ - mXMLDocumentPtr = xmlDocPtr; - mTopElementPtr = NULL; -} - -/** see DomExpatAgent.h */ -DomExpatAgent::~DomExpatAgent() -{ - -} - -/** see DomExpatAgent.h */ -bool DomExpatAgent::generateDocumentFromXML(istringstream *xmlStream) -{ - char ch; - string content; - - if (NULL == mXMLDocumentPtr || NULL == xmlStream) - { - return false; - } - - while ((ch = xmlStream->get()) != '\0') - { - content += ch; - } - - if (ExpatWrapper::decode(content.c_str(), content.length(), 1) == 0) - - { - return false; - } - return true; -} - -/** see DomExpatAgent.h */ -void DomExpatAgent::pushTag(const DOMString *name, const XML_Char **atts) -{ - ElementImpl *elementNode = mXMLDocumentPtr->createElement(name); - - if (NULL == elementNode) - { - return; - } - - if (NULL != atts) - { - while (NULL != *atts) - { - //set attributes into element node. - DOMString key(atts[0]), value(atts[1]); - elementNode->setAttribute(&key, &value); - atts += 2; - } - } - - if (!mStack.empty()) - { - mTopElementPtr->appendChild(elementNode); - } - else - { - mXMLDocumentPtr->setFirstChild(elementNode); - } - - mTopElementPtr = (XMLElementImpl *)elementNode; - mStack.push_back(elementNode); -} - -/** see DomExpatAgent.h */ -void DomExpatAgent::popTag(const DOMString *name) -{ - if (NULL == name) - { - return; - } - - if (mTopElementPtr != NULL) - { - if (!name->compare(mTopElementPtr->getTagName()->c_str())) - { - mStack.pop_back(); - if (!mStack.empty()) - { - mTopElementPtr =(XMLElementImpl *) mStack.back(); - } - else - { - mTopElementPtr = NULL; - } - } - } -} - -/** see DomExpatAgent.h */ -void DomExpatAgent::appendText(const DOMString *text) -{ - if ((mTopElementPtr != NULL) && (text != NULL)) - { - TextImpl *textNode = mXMLDocumentPtr->createTextNode(text); - - if (NULL == textNode) - { - return; - } - - mTopElementPtr->appendChild(textNode); - } -} - -/** see DomExpatAgent.h */ -void DomExpatAgent::startElement(const XML_Char *name, const XML_Char **atts) -{ - if (name) - { - DOMString tagName(name); - - pushTag(&tagName, atts); - } -} - -/** see DomExpatAgent.h */ -void DomExpatAgent::dataHandler(const XML_Char *s, int len) -{ - if (s != NULL && len >= 1 && *s != '\n') - { - DOMString text; - text.assign((char*)s, len); - appendText(&text); - } -} - -/** see DomExpatAgent.h */ -void DomExpatAgent::endElement(const XML_Char *name) -{ - if (name) - { - DOMString tagName(name); - popTag(&tagName); - } -} - -/** see DomExpatAgent.h */ -ostringstream* DomExpatAgent::generateXMLFromDocument() -{ - if (NULL == mXMLDocumentPtr) - { - return NULL; - } - - ElementImpl *root = mXMLDocumentPtr->getDocumentElement(); - - traverse(root); - - return &mXMLostream; -} - -/** see DomExpatAgent.h */ -void DomExpatAgent::traverse(ElementImpl *root) -{ - if (NULL == root) - { - return; - } - - mXMLostream << "<" << *(root->getNodeName()); - - if (root->hasAttributes()) - { - mXMLostream << endl; - const DOMStringMap* attrMapPtr = (static_cast(root))->getAttributeMap(); - DOMStringMap::const_reverse_iterator pos; - - for (pos=attrMapPtr->rbegin(); pos != attrMapPtr->rend(); pos++) - { - mXMLostream << pos->first << "=" << "\"" << pos->second << "\""; - - if (pos + 1 != attrMapPtr->rend()) - { - mXMLostream << endl; - } - } - } - - mXMLostream << ">" << endl; - - NodeImpl *child = root->getFirstChild(); - - while (child != NULL) - { - NodeType what = child->getNodeType(); - - if (what == ELEMENT_NODE) - { - traverse(static_cast(child)); - } else if (what == TEXT_NODE) - { - mXMLostream << *(static_cast(child)->getData()) << endl; - } - - child = child->getNextSibling(); - } - - mXMLostream << "getNodeName()) << ">" << endl; -} diff --git a/media/libdrm/mobile2/src/util/xml/ExpatWrapper.cpp b/media/libdrm/mobile2/src/util/xml/ExpatWrapper.cpp deleted file mode 100644 index fe99a88a0278f64e33a233c77e4ac7de6e0cda9a..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/xml/ExpatWrapper.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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. - */ -#include -#include -using namespace ustl; - -/** see ExpatWrapper.h */ -ExpatWrapper::ExpatWrapper() -{ - mParser = XML_ParserCreate(NULL); - ::XML_SetUserData(mParser, this); - ::XML_SetElementHandler(mParser, startElementCallback, endElementCallback); - ::XML_SetCharacterDataHandler(mParser, dataHandlerCallback); - -} - -/** see ExpatWrapper.h */ -ExpatWrapper::~ExpatWrapper() -{ - if (mParser) - { - ::XML_ParserFree(mParser); - } -} - -/** see ExpatWrapper.h */ -int ExpatWrapper::decode(const char* buf, int len, int isFinal) -{ - return ::XML_Parse(mParser, buf, len, isFinal); -} - -/** see ExpatWrapper.h */ -void ExpatWrapper::startElementCallback(void *userData, const XML_Char *name, - const XML_Char **atts) -{ - ((ExpatWrapper *)userData)->startElement(name, atts); -} - -/** see ExpatWrapper.h */ -void ExpatWrapper::endElementCallback(void *userData, const XML_Char *name) -{ - ((ExpatWrapper *)userData)->endElement(name); -} - -/** see ExpatWrapper.h */ -void ExpatWrapper::dataHandlerCallback(void *userData, const XML_Char *s, int len) -{ - ((ExpatWrapper *)userData)->dataHandler(s, len); -} - -/** see ExpatWrapper.h */ -void ExpatWrapper::startElement(const XML_Char *name, const XML_Char **atts) -{ -} - -/** see ExpatWrapper.h */ -void ExpatWrapper::endElement(const XML_Char *name) -{ -} - -/** see ExpatWrapper.h */ -void ExpatWrapper::dataHandler(const XML_Char *s, int len) -{ -} diff --git a/media/libdrm/mobile2/src/util/xml/XMLDocumentImpl.cpp b/media/libdrm/mobile2/src/util/xml/XMLDocumentImpl.cpp deleted file mode 100644 index c1fbc79d3036bf748f72a519e532f7b77511d073..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/xml/XMLDocumentImpl.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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. - */ -#include -#include - -/** see XMLDocumentImpl.h */ -XMLDocumentImpl::XMLDocumentImpl() -{} - -/** see XMLDocumentImpl.h */ -XMLDocumentImpl::~XMLDocumentImpl() -{} - -/** see XMLDocumentImpl.h */ -ElementImpl* XMLDocumentImpl::getDocumentElement() const -{ - XMLElementImpl *element = (XMLElementImpl *)(this->getFirstChild()); - return element; -} - -/** see XMLDocumentImpl.h */ -ElementImpl* XMLDocumentImpl::createElement(const DOMString* tagName) const throw (DOMException) -{ - if (tagName) - { - XMLElementImpl *element = new XMLElementImpl(tagName); - return element; - } - return NULL; -} - -/** see XMLDocumentImpl.h */ -TextImpl* XMLDocumentImpl::createTextNode(const DOMString* data) const -{ - if (data) - { - TextImpl *text = new TextImpl(data); - return text; - } - return NULL; -} - diff --git a/media/libdrm/mobile2/src/util/xml/XMLElementImpl.cpp b/media/libdrm/mobile2/src/util/xml/XMLElementImpl.cpp deleted file mode 100644 index 5453902eba64132778745be492c69bff8f2b9055..0000000000000000000000000000000000000000 --- a/media/libdrm/mobile2/src/util/xml/XMLElementImpl.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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. - */ -#include -#include - -/** see XMLElementImpl.h */ -XMLElementImpl::XMLElementImpl(const DOMString *tag) -{ - if (tag) - { - mTagName = *tag; - } -} - -/** see XMLElementImpl.h */ -XMLElementImpl::~XMLElementImpl() -{ -} - -/** see XMLElementImpl.h */ -const DOMString* XMLElementImpl::getTagName() const -{ - return &mTagName; -} - -/** see XMLElementImpl.h */ -void XMLElementImpl::setAttribute(const DOMString* name, const DOMString* value) - throw (DOMException) -{ - if (name && value) - { - mAttributeMap[*name] = *value; - } -} - -/** see XMLElementImpl.h */ -void XMLElementImpl::removeAttribute(const DOMString* name) throw (DOMException) -{ - if (name) - { - mAttributeMap.erase(*name); - } -} - -/** see XMLElementImpl.h */ -const DOMString* XMLElementImpl::getAttribute(const DOMString* name) const -{ - if (name) - { - DOMStringMap::const_iterator pos = mAttributeMap.find(*name); - - if (pos != mAttributeMap.end()) - { - return &(pos->second); - } - - } - return NULL; -} - -/** see XMLElementImpl.h */ -bool XMLElementImpl::hasAttributes() const -{ - return !mAttributeMap.empty(); -} - -/** see XMLElementImpl.h */ -const DOMStringMap* XMLElementImpl::getAttributeMap() const -{ - return &mAttributeMap; -} - -/** see XMLElementImpl.h */ -const NodeImpl* XMLElementImpl::findSoloChildNode(const char* tag) const -{ - if (NULL == tag) - { - return NULL; - } - - string token; - NodeListImpl *nodeList = NULL; - const NodeImpl *childNode = NULL; - - token.assign(tag); - nodeList = getElementsByTagName(&token); - - if (nodeList->getLength() > 0) - { - childNode = nodeList->item(0); - } - - return childNode; -} - -/** see XMLElementImpl.h */ -const string* XMLElementImpl::getSoloText(const char* tag) const -{ - const NodeImpl *textNode = this->findSoloChildNode(tag); - - if (textNode) - { - textNode = textNode->getFirstChild(); - if (textNode) - { - return static_cast(textNode)->getData(); - } - } - - return NULL; -} - -/** see XMLElementImpl.h */ -const XMLElementImpl* XMLElementImpl::getSoloElement(const char* tag) const -{ - const NodeImpl *node = findSoloChildNode(tag); - if (node) - { - return static_cast(node); - } - - return NULL; -} diff --git a/media/libeffects/Android.mk b/media/libeffects/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..ff2145461f7e37ea598da0dd232be40edb4943c1 --- /dev/null +++ b/media/libeffects/Android.mk @@ -0,0 +1,90 @@ +LOCAL_PATH:= $(call my-dir) + +# Effect factory library +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + EffectsFactory.c + +LOCAL_SHARED_LIBRARIES := \ + libcutils + +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) +LOCAL_MODULE:= libeffects + +ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) +LOCAL_LDLIBS += -ldl +endif + +ifneq ($(TARGET_SIMULATOR),true) +LOCAL_SHARED_LIBRARIES += libdl +endif + +LOCAL_C_INCLUDES := \ + +include $(BUILD_SHARED_LIBRARY) + + +# Default Reverb library +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + EffectReverb.c.arm \ + EffectsMath.c.arm +LOCAL_CFLAGS+= -O2 + +LOCAL_SHARED_LIBRARIES := \ + libcutils + +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE:= libreverb + +ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) +LOCAL_LDLIBS += -ldl +endif + +ifneq ($(TARGET_SIMULATOR),true) +LOCAL_SHARED_LIBRARIES += libdl +endif + +LOCAL_C_INCLUDES := \ + $(call include-path-for, graphics corecg) + +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) + +# Default Equalizer library +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + EffectsMath.c.arm \ + EffectEqualizer.cpp \ + AudioBiquadFilter.cpp.arm \ + AudioCoefInterpolator.cpp.arm \ + AudioPeakingFilter.cpp.arm \ + AudioShelvingFilter.cpp.arm \ + AudioEqualizer.cpp.arm + +LOCAL_CFLAGS+= -O2 + +LOCAL_SHARED_LIBRARIES := \ + libcutils + +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE:= libequalizer + +ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) +LOCAL_LDLIBS += -ldl +endif + +ifneq ($(TARGET_SIMULATOR),true) +LOCAL_SHARED_LIBRARIES += libdl +endif + +LOCAL_C_INCLUDES := \ + $(call include-path-for, graphics corecg) + +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/media/libeffects/AudioBiquadFilter.cpp b/media/libeffects/AudioBiquadFilter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72917a3628cf8157217e3bddb8fe6da5fab3391e --- /dev/null +++ b/media/libeffects/AudioBiquadFilter.cpp @@ -0,0 +1,260 @@ +/* //device/servers/AudioFlinger/AudioBiquadFilter.cpp +** +** Copyright 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 +#include + +#include "AudioBiquadFilter.h" + +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) + +namespace android { + +const audio_coef_t AudioBiquadFilter::IDENTITY_COEFS[AudioBiquadFilter::NUM_COEFS] = { AUDIO_COEF_ONE, 0, 0, 0, 0 }; + +AudioBiquadFilter::AudioBiquadFilter(int nChannels, int sampleRate) { + configure(nChannels, sampleRate); + reset(); +} + +void AudioBiquadFilter::configure(int nChannels, int sampleRate) { + assert(nChannels > 0 && nChannels <= MAX_CHANNELS); + assert(sampleRate > 0); + mNumChannels = nChannels; + mMaxDelta = static_cast(MAX_DELTA_PER_SEC) + * AUDIO_COEF_ONE + / sampleRate; + clear(); +} + +void AudioBiquadFilter::reset() { + memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs)); + mCoefDirtyBits = 0; + setState(STATE_BYPASS); +} + +void AudioBiquadFilter::clear() { + memset(mDelays, 0, sizeof(mDelays)); +} + +void AudioBiquadFilter::setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate) { + memcpy(mTargetCoefs, coefs, sizeof(mTargetCoefs)); + if (mState & STATE_ENABLED_MASK) { + if (UNLIKELY(immediate)) { + memcpy(mCoefs, coefs, sizeof(mCoefs)); + setState(STATE_NORMAL); + } else { + setState(STATE_TRANSITION_TO_NORMAL); + } + } +} + +void AudioBiquadFilter::process(const audio_sample_t in[], audio_sample_t out[], + int frameCount) { + (this->*mCurProcessFunc)(in, out, frameCount); +} + +void AudioBiquadFilter::enable(bool immediate) { + if (UNLIKELY(immediate)) { + memcpy(mCoefs, mTargetCoefs, sizeof(mCoefs)); + setState(STATE_NORMAL); + } else { + setState(STATE_TRANSITION_TO_NORMAL); + } +} + +void AudioBiquadFilter::disable(bool immediate) { + if (UNLIKELY(immediate)) { + memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs)); + setState(STATE_BYPASS); + } else { + setState(STATE_TRANSITION_TO_BYPASS); + } +} + +void AudioBiquadFilter::setState(state_t state) { + switch (state) { + case STATE_BYPASS: + mCurProcessFunc = &AudioBiquadFilter::process_bypass; + break; + case STATE_TRANSITION_TO_BYPASS: + if (mNumChannels == 1) { + mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_mono; + } else { + mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_multi; + } + mCoefDirtyBits = (1 << NUM_COEFS) - 1; + break; + case STATE_TRANSITION_TO_NORMAL: + if (mNumChannels == 1) { + mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_mono; + } else { + mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_multi; + } + mCoefDirtyBits = (1 << NUM_COEFS) - 1; + break; + case STATE_NORMAL: + if (mNumChannels == 1) { + mCurProcessFunc = &AudioBiquadFilter::process_normal_mono; + } else { + mCurProcessFunc = &AudioBiquadFilter::process_normal_multi; + } + break; + } + mState = state; +} + +bool AudioBiquadFilter::updateCoefs(const audio_coef_t coefs[NUM_COEFS], + int frameCount) { + int64_t maxDelta = mMaxDelta * frameCount; + for (int i = 0; i < NUM_COEFS; ++i) { + if (mCoefDirtyBits & (1< maxDelta) { + mCoefs[i] += maxDelta; + } else if (diff < -maxDelta) { + mCoefs[i] -= maxDelta; + } else { + mCoefs[i] = coefs[i]; + mCoefDirtyBits ^= (1< 0) { + audio_sample_t x0 = *(in++); + audio_coef_sample_acc_t acc; + acc = mul_coef_sample(b0, x0); + acc = mac_coef_sample(b1, x1, acc); + acc = mac_coef_sample(b2, x2, acc); + acc = mac_coef_sample(a1, y1, acc); + acc = mac_coef_sample(a2, y2, acc); + audio_sample_t y0 = coef_sample_acc_to_sample(acc); + y2 = y1; + y1 = y0; + x2 = x1; + x1 = x0; + (*out++) = y0; + } + mDelays[0][0] = x1; + mDelays[0][1] = x2; + mDelays[0][2] = y1; + mDelays[0][3] = y2; +} + +void AudioBiquadFilter::process_transition_normal_mono(const audio_sample_t * in, + audio_sample_t * out, + int frameCount) { + if (updateCoefs(mTargetCoefs, frameCount)) { + setState(STATE_NORMAL); + } + process_normal_mono(in, out, frameCount); +} + +void AudioBiquadFilter::process_transition_bypass_mono(const audio_sample_t * in, + audio_sample_t * out, + int frameCount) { + if (updateCoefs(IDENTITY_COEFS, frameCount)) { + setState(STATE_NORMAL); + } + process_normal_mono(in, out, frameCount); +} + +void AudioBiquadFilter::process_normal_multi(const audio_sample_t * in, + audio_sample_t * out, + int frameCount) { + const audio_coef_t b0 = mCoefs[0]; + const audio_coef_t b1 = mCoefs[1]; + const audio_coef_t b2 = mCoefs[2]; + const audio_coef_t a1 = mCoefs[3]; + const audio_coef_t a2 = mCoefs[4]; + for (int ch = 0; ch < mNumChannels; ++ch) { + size_t nFrames = frameCount; + audio_sample_t x1 = mDelays[ch][0]; + audio_sample_t x2 = mDelays[ch][1]; + audio_sample_t y1 = mDelays[ch][2]; + audio_sample_t y2 = mDelays[ch][3]; + while (nFrames-- > 0) { + audio_sample_t x0 = *in; + audio_coef_sample_acc_t acc; + acc = mul_coef_sample(b0, x0); + acc = mac_coef_sample(b1, x1, acc); + acc = mac_coef_sample(b2, x2, acc); + acc = mac_coef_sample(a1, y1, acc); + acc = mac_coef_sample(a2, y2, acc); + audio_sample_t y0 = coef_sample_acc_to_sample(acc); + y2 = y1; + y1 = y0; + x2 = x1; + x1 = x0; + *out = y0; + in += mNumChannels; + out += mNumChannels; + } + mDelays[ch][0] = x1; + mDelays[ch][1] = x2; + mDelays[ch][2] = y1; + mDelays[ch][3] = y2; + in -= frameCount * mNumChannels - 1; + out -= frameCount * mNumChannels - 1; + } +} + +void AudioBiquadFilter::process_transition_normal_multi(const audio_sample_t * in, + audio_sample_t * out, + int frameCount) { + if (updateCoefs(mTargetCoefs, frameCount)) { + setState(STATE_NORMAL); + } + process_normal_multi(in, out, frameCount); +} + +void AudioBiquadFilter::process_transition_bypass_multi(const audio_sample_t * in, + audio_sample_t * out, + int frameCount) { + if (updateCoefs(IDENTITY_COEFS, frameCount)) { + setState(STATE_NORMAL); + } + process_normal_multi(in, out, frameCount); +} + +} diff --git a/media/libeffects/AudioBiquadFilter.h b/media/libeffects/AudioBiquadFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..2b0e2d64aa420606c12b716836cbd9c0c05d809b --- /dev/null +++ b/media/libeffects/AudioBiquadFilter.h @@ -0,0 +1,180 @@ +/* //device/include/server/AudioFlinger/AudioBiquadFilter.h +** +** Copyright 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. +*/ + +#ifndef ANDROID_AUDIO_BIQUAD_FILTER_H +#define ANDROID_AUDIO_BIQUAD_FILTER_H + +#include "AudioCommon.h" + +namespace android { +// A biquad filter. +// Implements the recursion y[n]=a0*y[n-1]+a1*y[n-2]+b0*x[n]+b1*x[n-1]+b2*x[n-2] +// (the a0 and a1 coefficients have an opposite sign to the common convention) +// The filter works on fixed sized blocks of data (frameCount multi-channel +// samples, as defined during construction). An arbitrary number of interlaced +// channels is supported. +// Filter can operate in an enabled (active) or disabled (bypassed) states. +// A mechanism for suppression of artifacts caused by abrupt coefficient changes +// is implemented: normally, when the enable(), disable() and setCoefs() methods +// are called without the immediate flag set, the filter smoothly transitions +// from its current state to the desired state. +class AudioBiquadFilter { +public: + // Max number of channels (can be changed here, and everything should work). + static const int MAX_CHANNELS = 2; + // Number of coefficients. + static const int NUM_COEFS = 5; + + // Constructor. + // nChannels Number of input/output channels. + // sampleRate Sample rate, in Hz. + AudioBiquadFilter(int nChannels, int sampleRate); + + // Reconfiguration of the filter. Implies clear(). + // nChannels Number of input/output channels. + // sampleRate Sample rate, in Hz. + void configure(int nChannels, int sampleRate); + + // Resets the internal state of the filter. + // Coefficients are reset to identity, state becomes disabled. This change + // happens immediately and might cause discontinuities in the output. + // Delay lines are not cleared. + void reset(); + + // Clears the delay lines. + // This change happens immediately and might cause discontinuities in the + // output. + void clear(); + + // Sets the coefficients. + // If called when filter is disabled, will have no immediate effect, but the + // new coefficients will be set and used next time the filter is enabled. + // coefs The new coefficients. + // immediate If true, transitions to new coefficients smoothly, without + // introducing discontinuities in the output. Otherwise, + // transitions immediately. + void setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate = false); + + // Process a buffer of data. Always processes frameCount multi-channel + // samples. Processing can be done in-place, by passing the same buffer as + // both arguments. + // in The input buffer. Should be of size frameCount * nChannels. + // out The output buffer. Should be of size frameCount * nChannels. + // frameCount Number of multi-channel samples to process. + void process(const audio_sample_t in[], audio_sample_t out[], + int frameCount); + + // Enables (activates) the filter. + // immediate If true, transitions to new state smoothly, without + // introducing discontinuities in the output. Otherwise, + // transitions immediately. + void enable(bool immediate = false); + + // Disables (bypasses) the filter. + // immediate If true, transitions to new state smoothly, without + // introducing discontinuities in the output. Otherwise, + // transitions immediately. + void disable(bool immediate = false); + +private: + // A prototype of the actual processing function. Has the same semantics as + // the process() method. + typedef void (AudioBiquadFilter::*process_func)(const audio_sample_t[], + audio_sample_t[], + int frameCount); + + // The maximum rate of coefficient change, measured in coefficient units per + // second. + static const audio_coef_t MAX_DELTA_PER_SEC = 2000; + + // Coefficients of identity transformation. + static const audio_coef_t IDENTITY_COEFS[NUM_COEFS]; + + // Filter state. + enum state_t { + // Bypass. + STATE_BYPASS = 0x01, + // In the process of smooth transition to bypass state. + STATE_TRANSITION_TO_BYPASS = 0x02, + // In the process of smooth transition to normal (enabled) state. + STATE_TRANSITION_TO_NORMAL = 0x04, + // In normal (enabled) state. + STATE_NORMAL = 0x05, + // A bit-mask for determining whether the filter is enabled or disabled + // in the eyes of the client. + STATE_ENABLED_MASK = 0x04 + }; + + // Number of channels. + int mNumChannels; + // Current state. + state_t mState; + // Maximum coefficient delta per sample. + audio_coef_t mMaxDelta; + + // A bit-mask designating for which coefficients the current value is not + // necessarily identical to the target value (since we're in transition + // state). + uint32_t mCoefDirtyBits; + // The current coefficients. + audio_coef_t mCoefs[NUM_COEFS]; + // The target coefficients. Will not be identical to mCoefs if we are in a + // transition state. + audio_coef_t mTargetCoefs[NUM_COEFS]; + + // The delay lines. + audio_sample_t mDelays[MAX_CHANNELS][4]; + + // Current processing function (determines according to current state and + // number of channels). + process_func mCurProcessFunc; + + // Sets a new state. Updates the processing function accordingly, and sets + // the dirty bits if changing to a transition state. + void setState(state_t state); + + // In a transition state, modifies the current coefs towards the passed + // coefs, while keeping a smooth change rate. Whenever a coef reaches its + // target value, the dirty bit is cleared. If all are clear, the function + // returns true, and we can then change to our target state. + bool updateCoefs(const audio_coef_t coefs[NUM_COEFS], int frameCount); + + // Processing function when in disabled state. + void process_bypass(const audio_sample_t * in, audio_sample_t * out, + int frameCount); + // Processing function when in normal state, mono. + void process_normal_mono(const audio_sample_t * in, audio_sample_t * out, + int frameCount); + // Processing function when transitioning to normal state, mono. + void process_transition_normal_mono(const audio_sample_t * in, + audio_sample_t * out, int frameCount); + // Processing function when transitioning to bypass state, mono. + void process_transition_bypass_mono(const audio_sample_t * in, + audio_sample_t * out, int frameCount); + // Processing function when in normal state, multi-channel. + void process_normal_multi(const audio_sample_t * in, audio_sample_t * out, + int frameCount); + // Processing function when transitioning to normal state, multi-channel. + void process_transition_normal_multi(const audio_sample_t * in, + audio_sample_t * out, int frameCount); + // Processing function when transitioning to bypass state, multi-channel. + void process_transition_bypass_multi(const audio_sample_t * in, + audio_sample_t * out, int frameCount); +}; +} + +#endif // ANDROID_AUDIO_BIQUAD_FILTER_H diff --git a/media/libeffects/AudioCoefInterpolator.cpp b/media/libeffects/AudioCoefInterpolator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..05898c9952256dd139784164f7275c72810194bc --- /dev/null +++ b/media/libeffects/AudioCoefInterpolator.cpp @@ -0,0 +1,84 @@ +/* //device/servers/AudioFlinger/AudioCoefInterpolator.cpp + ** + ** Copyright 2008, 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 "AudioCoefInterpolator.h" + +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) + +namespace android { + +AudioCoefInterpolator::AudioCoefInterpolator(size_t nInDims, + const size_t inDims[], + size_t nOutDims, + const audio_coef_t * table) { + mNumInDims = nInDims; + memcpy(mInDims, inDims, nInDims * sizeof(size_t)); + mNumOutDims = nOutDims; + mTable = table; + // Initialize offsets array + size_t dim = nInDims - 1; + mInDimOffsets[nInDims - 1] = nOutDims; + while (dim-- > 0) { + mInDimOffsets[dim] = mInDimOffsets[dim + 1] * mInDims[dim + 1]; + } +} + +void AudioCoefInterpolator::getCoef(const int intCoord[], uint32_t fracCoord[], + audio_coef_t out[]) { + size_t index = 0; + size_t dim = mNumInDims; + while (dim-- > 0) { + if (UNLIKELY(intCoord[dim] < 0)) { + fracCoord[dim] = 0; + } else if (UNLIKELY(intCoord[dim] >= mInDims[dim] - 1)) { + fracCoord[dim] = 0; + index += mInDimOffsets[dim] * (mInDims[dim] - 1); + } else { + index += mInDimOffsets[dim] * intCoord[dim]; + } + } + getCoefRecurse(index, fracCoord, out, 0); +} + +void AudioCoefInterpolator::getCoefRecurse(size_t index, + const uint32_t fracCoord[], + audio_coef_t out[], size_t dim) { + if (dim == mNumInDims) { + memcpy(out, mTable + index, mNumOutDims * sizeof(audio_coef_t)); + } else { + getCoefRecurse(index, fracCoord, out, dim + 1); + if (LIKELY(fracCoord != 0)) { + audio_coef_t tempCoef[MAX_OUT_DIMS]; + getCoefRecurse(index + mInDimOffsets[dim], fracCoord, tempCoef, + dim + 1); + size_t d = mNumOutDims; + while (d-- > 0) { + out[d] = interp(out[d], tempCoef[d], fracCoord[dim]); + } + } + } +} + +audio_coef_t AudioCoefInterpolator::interp(audio_coef_t lo, audio_coef_t hi, + uint32_t frac) { + int64_t delta = static_cast(hi-lo) * frac; + return lo + static_cast (delta >> 32); +} + +} diff --git a/media/libeffects/AudioCoefInterpolator.h b/media/libeffects/AudioCoefInterpolator.h new file mode 100644 index 0000000000000000000000000000000000000000..13e569714758e4193171d09d00c4434d4bf863eb --- /dev/null +++ b/media/libeffects/AudioCoefInterpolator.h @@ -0,0 +1,98 @@ +/* //device/include/server/AudioFlinger/AudioCoefInterpolator.h + ** + ** Copyright 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. + */ + +#ifndef ANDROID_AUDIO_COEF_INTERPOLATOR_H +#define ANDROID_AUDIO_COEF_INTERPOLATOR_H + +#include "AudioCommon.h" + +namespace android { + +// A helper class for linear interpolation of N-D -> M-D coefficient tables. +// This class provides support for out-of-range indexes. +// Details: +// The purpose is efficient approximation of a N-dimensional vector to +// M-dimensional function. The approximation is based on a table of output +// values on a uniform grid of the input values. Values not on the grid are +// linearly interpolated. +// Access to values are done by specifying input values in table index units, +// having an integer and a fractional part, e.g. retrieving a value from index +// 1.4 will result in linear interpolation between index 1 and index 2. +class AudioCoefInterpolator { +public: + // Constructor. + // nInDims Number of input dimensions (limited to MAX_IN_DIMS). + // inDims An array of size nInDims with the size of the table on each + // respective dimension. + // nOutDims Number of output dimensions (limited to MAX_OUT_DIMS). + // table The coefficient table. Should be of size: + // inDims[0]*inDims[1]*...*inDims[nInDims-1]*nOutDims, where + // func([i,j,k]) = table(i,j,k,:) + AudioCoefInterpolator(size_t nInDims, const size_t inDims[], + size_t nOutDims, const audio_coef_t * table); + + // Get the value of the approximated function at a given point. + // intCoord The integer part of the input value. Should be an array of + // size nInDims. + // fracCoord The fractional part of the input value. Should be an array + // of size nInDims. This value is in 32-bit precision. + // out An array for the output value. Should be of size nOutDims. + void getCoef(const int intCoord[], uint32_t fracCoord[], audio_coef_t out[]); + +private: + // Maximum allowed number of input dimensions. + static const size_t MAX_IN_DIMS = 8; + // Maximum allowed number of output dimensions. + static const size_t MAX_OUT_DIMS = 8; + + // Number of input dimensions. + size_t mNumInDims; + // Number of input dimensions. + size_t mInDims[MAX_IN_DIMS]; + // The offset between two consecutive indexes of each dimension. This is in + // fact a cumulative product of mInDims (done in reverse). + size_t mInDimOffsets[MAX_IN_DIMS]; + // Number of output dimensions. + size_t mNumOutDims; + // The coefficient table. + const audio_coef_t * mTable; + + // A recursive function for getting an interpolated coefficient value. + // The recursion depth is the number of input dimensions. + // At each step, we fetch two interpolated values of the current dimension, + // by two recursive calls to this method for the next dimensions. We then + // linearly interpolate these values over the current dimension. + // index The linear integer index of the value we need to interpolate. + // fracCoord A vector of fractional coordinates for each of the input + // dimensions. + // out Where the output should be written. Needs to be of size + // mNumOutDims. + // dim The input dimensions we are currently interpolating. This + // value will be increased on recursive calls. + void getCoefRecurse(size_t index, const uint32_t fracCoord[], + audio_coef_t out[], size_t dim); + + // Scalar interpolation of two data points. + // lo The first data point. + // hi The second data point. + // frac A 32-bit fraction designating the weight of the second point. + static audio_coef_t interp(audio_coef_t lo, audio_coef_t hi, uint32_t frac); +}; + +} + +#endif // ANDROID_AUDIO_COEF_INTERPOLATOR_H diff --git a/media/libeffects/AudioCommon.h b/media/libeffects/AudioCommon.h new file mode 100644 index 0000000000000000000000000000000000000000..12d2193e6a10d943862e7221f5c2f3ba179a3a2c --- /dev/null +++ b/media/libeffects/AudioCommon.h @@ -0,0 +1,92 @@ +/* //device/include/server/AudioFlinger/AudioCommon.h +** +** Copyright 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 ANDROID_AUDIO_COMMON_H +#define ANDROID_AUDIO_COMMON_H + +#include +#include + +namespace android { + +// Audio coefficient type. +typedef int32_t audio_coef_t; +// Audio sample type. +typedef int32_t audio_sample_t; +// Accumulator type for coef x sample. +typedef int64_t audio_coef_sample_acc_t; + +// Number of fraction bits for audio coefficient. +static const int AUDIO_COEF_PRECISION = 24; +// Audio coefficient with the value of 1.0 +static const audio_coef_t AUDIO_COEF_ONE = 1 << AUDIO_COEF_PRECISION; +// Audio coefficient with the value of 0.5 +static const audio_coef_t AUDIO_COEF_HALF = 1 << (AUDIO_COEF_PRECISION - 1); +// Number of fraction bits for audio sample. +static const int AUDIO_SAMPLE_PRECISION = 24; +// Audio sample with the value of 1.0 +static const audio_sample_t AUDIO_SAMPLE_ONE = 1 << AUDIO_SAMPLE_PRECISION; + +// TODO: These are just temporary naive implementations of the necessary +// arithmetic operations needed for the filter. They should be moved to a more +// generic location and implemented more efficiently. + +// Multiply a sample by a coefficient to return an accumulator. +inline audio_coef_sample_acc_t mul_coef_sample(audio_coef_t x, audio_sample_t y) { + return ((audio_coef_sample_acc_t) (x)) * y; +} + +// Multiply and accumulate sample by a coefficient to return an accumulator. +inline audio_coef_sample_acc_t mac_coef_sample(audio_coef_t x, audio_sample_t y, audio_coef_sample_acc_t acc) { + return acc + ((audio_coef_sample_acc_t) (x)) * y; +} + +// Convert a sample-coefficient accumulator to a sample. +inline audio_sample_t coef_sample_acc_to_sample(audio_coef_sample_acc_t acc) { + if (acc < 0) { + acc += AUDIO_COEF_ONE - 1; + } + return (audio_sample_t) (acc >> AUDIO_COEF_PRECISION); +} + +// Convert a S15 sample to audio_sample_t +inline audio_sample_t s15_to_audio_sample_t(int16_t s15) { + return audio_sample_t(s15) << 9; +} + +// Convert a audio_sample_t sample to S15 (no clipping) +inline int16_t audio_sample_t_to_s15(audio_sample_t sample) { + return int16_t((sample + (1 << 8)) >> 9); +} + +// Convert a audio_sample_t sample to S15 (with clipping) +inline int16_t audio_sample_t_to_s15_clip(audio_sample_t sample) { + // TODO: optimize for targets supporting this as an atomic operation. + if (__builtin_expect(sample >= (0x7FFF << 9), 0)) { + return 0x7FFF; + } else if (__builtin_expect(sample <= -(0x8000 << 9), 0)) { + return 0x8000; + } else { + return audio_sample_t_to_s15(sample); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +} + +#endif // ANDROID_AUDIO_COMMON_H diff --git a/media/libeffects/AudioEqualizer.cpp b/media/libeffects/AudioEqualizer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44c9476a71d860e46e994081e316a0076e7fc730 --- /dev/null +++ b/media/libeffects/AudioEqualizer.cpp @@ -0,0 +1,315 @@ +/* + * Copyright 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. + */ + +#define LOG_TAG "AudioEqualizer" + +#include +#include +#include +#include + +#include "AudioEqualizer.h" +#include "AudioPeakingFilter.h" +#include "AudioShelvingFilter.h" +#include "EffectsMath.h" + +namespace android { + +size_t AudioEqualizer::GetInstanceSize(int nBands) { + assert(nBands >= 2); + return sizeof(AudioEqualizer) + + sizeof(AudioShelvingFilter) * 2 + + sizeof(AudioPeakingFilter) * (nBands - 2); +} + +AudioEqualizer * AudioEqualizer::CreateInstance(void * pMem, int nBands, + int nChannels, int sampleRate, + const PresetConfig * presets, + int nPresets) { + LOGV("AudioEqualizer::CreateInstance(pMem=%p, nBands=%d, nChannels=%d, " + "sampleRate=%d, nPresets=%d)", + pMem, nBands, nChannels, sampleRate, nPresets); + assert(nBands >= 2); + bool ownMem = false; + if (pMem == NULL) { + pMem = malloc(GetInstanceSize(nBands)); + if (pMem == NULL) { + return NULL; + } + ownMem = true; + } + return new (pMem) AudioEqualizer(pMem, nBands, nChannels, sampleRate, + ownMem, presets, nPresets); +} + +void AudioEqualizer::configure(int nChannels, int sampleRate) { + LOGV("AudioEqualizer::configure(nChannels=%d, sampleRate=%d)", nChannels, + sampleRate); + mpLowShelf->configure(nChannels, sampleRate); + for (int i = 0; i < mNumPeaking; ++i) { + mpPeakingFilters[i].configure(nChannels, sampleRate); + } + mpHighShelf->configure(nChannels, sampleRate); +} + +void AudioEqualizer::clear() { + LOGV("AudioEqualizer::clear()"); + mpLowShelf->clear(); + for (int i = 0; i < mNumPeaking; ++i) { + mpPeakingFilters[i].clear(); + } + mpHighShelf->clear(); +} + +void AudioEqualizer::free() { + LOGV("AudioEqualizer::free()"); + if (mpMem != NULL) { + ::free(mpMem); + } +} + +void AudioEqualizer::reset() { + LOGV("AudioEqualizer::reset()"); + const int32_t bottom = Effects_log2(kMinFreq); + const int32_t top = Effects_log2(mSampleRate * 500); + const int32_t jump = (top - bottom) / (mNumPeaking + 2); + int32_t centerFreq = bottom + jump/2; + + mpLowShelf->reset(); + mpLowShelf->setFrequency(Effects_exp2(centerFreq)); + centerFreq += jump; + for (int i = 0; i < mNumPeaking; ++i) { + mpPeakingFilters[i].reset(); + mpPeakingFilters[i].setFrequency(Effects_exp2(centerFreq)); + centerFreq += jump; + } + mpHighShelf->reset(); + mpHighShelf->setFrequency(Effects_exp2(centerFreq)); + commit(true); + mCurPreset = PRESET_CUSTOM; +} + +void AudioEqualizer::setGain(int band, int32_t millibel) { + LOGV("AudioEqualizer::setGain(band=%d, millibel=%d)", band, millibel); + assert(band >= 0 && band < mNumPeaking + 2); + if (band == 0) { + mpLowShelf->setGain(millibel); + } else if (band == mNumPeaking + 1) { + mpHighShelf->setGain(millibel); + } else { + mpPeakingFilters[band - 1].setGain(millibel); + } + mCurPreset = PRESET_CUSTOM; +} + +void AudioEqualizer::setFrequency(int band, uint32_t millihertz) { + LOGV("AudioEqualizer::setFrequency(band=%d, millihertz=%d)", band, + millihertz); + assert(band >= 0 && band < mNumPeaking + 2); + if (band == 0) { + mpLowShelf->setFrequency(millihertz); + } else if (band == mNumPeaking + 1) { + mpHighShelf->setFrequency(millihertz); + } else { + mpPeakingFilters[band - 1].setFrequency(millihertz); + } + mCurPreset = PRESET_CUSTOM; +} + +void AudioEqualizer::setBandwidth(int band, uint32_t cents) { + LOGV("AudioEqualizer::setBandwidth(band=%d, cents=%d)", band, cents); + assert(band >= 0 && band < mNumPeaking + 2); + if (band > 0 && band < mNumPeaking + 1) { + mpPeakingFilters[band - 1].setBandwidth(cents); + mCurPreset = PRESET_CUSTOM; + } +} + +int32_t AudioEqualizer::getGain(int band) const { + assert(band >= 0 && band < mNumPeaking + 2); + if (band == 0) { + return mpLowShelf->getGain(); + } else if (band == mNumPeaking + 1) { + return mpHighShelf->getGain(); + } else { + return mpPeakingFilters[band - 1].getGain(); + } +} + +uint32_t AudioEqualizer::getFrequency(int band) const { + assert(band >= 0 && band < mNumPeaking + 2); + if (band == 0) { + return mpLowShelf->getFrequency(); + } else if (band == mNumPeaking + 1) { + return mpHighShelf->getFrequency(); + } else { + return mpPeakingFilters[band - 1].getFrequency(); + } +} + +uint32_t AudioEqualizer::getBandwidth(int band) const { + assert(band >= 0 && band < mNumPeaking + 2); + if (band == 0 || band == mNumPeaking + 1) { + return 0; + } else { + return mpPeakingFilters[band - 1].getBandwidth(); + } +} + +void AudioEqualizer::getBandRange(int band, uint32_t & low, + uint32_t & high) const { + assert(band >= 0 && band < mNumPeaking + 2); + if (band == 0) { + low = 0; + high = mpLowShelf->getFrequency(); + } else if (band == mNumPeaking + 1) { + low = mpHighShelf->getFrequency(); + high = mSampleRate * 500; + } else { + mpPeakingFilters[band - 1].getBandRange(low, high); + } +} + +const char * AudioEqualizer::getPresetName(int preset) const { + assert(preset < mNumPresets && preset >= PRESET_CUSTOM); + if (preset == PRESET_CUSTOM) { + return "Custom"; + } else { + return mpPresets[preset].name; + } +} + +int AudioEqualizer::getNumPresets() const { + return mNumPresets; +} + +int AudioEqualizer::getPreset() const { + return mCurPreset; +} + +void AudioEqualizer::setPreset(int preset) { + LOGV("AudioEqualizer::setPreset(preset=%d)", preset); + assert(preset < mNumPresets && preset >= 0); + const PresetConfig &presetCfg = mpPresets[preset]; + for (int band = 0; band < (mNumPeaking + 2); ++band) { + const BandConfig & bandCfg = presetCfg.bandConfigs[band]; + setGain(band, bandCfg.gain); + setFrequency(band, bandCfg.freq); + setBandwidth(band, bandCfg.bandwidth); + } + mCurPreset = preset; +} + +void AudioEqualizer::commit(bool immediate) { + LOGV("AudioEqualizer::commit(immediate=%d)", immediate); + mpLowShelf->commit(immediate); + for (int i = 0; i < mNumPeaking; ++i) { + mpPeakingFilters[i].commit(immediate); + } + mpHighShelf->commit(immediate); +} + +void AudioEqualizer::process(const audio_sample_t * pIn, + audio_sample_t * pOut, + int frameCount) { +// LOGV("AudioEqualizer::process(frameCount=%d)", frameCount); + mpLowShelf->process(pIn, pOut, frameCount); + for (int i = 0; i < mNumPeaking; ++i) { + mpPeakingFilters[i].process(pIn, pOut, frameCount); + } + mpHighShelf->process(pIn, pOut, frameCount); +} + +void AudioEqualizer::enable(bool immediate) { + LOGV("AudioEqualizer::enable(immediate=%d)", immediate); + mpLowShelf->enable(immediate); + for (int i = 0; i < mNumPeaking; ++i) { + mpPeakingFilters[i].enable(immediate); + } + mpHighShelf->enable(immediate); +} + +void AudioEqualizer::disable(bool immediate) { + LOGV("AudioEqualizer::disable(immediate=%d)", immediate); + mpLowShelf->disable(immediate); + for (int i = 0; i < mNumPeaking; ++i) { + mpPeakingFilters[i].disable(immediate); + } + mpHighShelf->disable(immediate); +} + +int AudioEqualizer::getMostRelevantBand(uint32_t targetFreq) const { + // First, find the two bands that the target frequency is between. + uint32_t low = mpLowShelf->getFrequency(); + if (targetFreq <= low) { + return 0; + } + uint32_t high = mpHighShelf->getFrequency(); + if (targetFreq >= high) { + return mNumPeaking + 1; + } + int band = mNumPeaking; + for (int i = 0; i < mNumPeaking; ++i) { + uint32_t freq = mpPeakingFilters[i].getFrequency(); + if (freq >= targetFreq) { + high = freq; + band = i; + break; + } + low = freq; + } + // Now, low is right below the target and high is right above. See which one + // is closer on a log scale. + low = Effects_log2(low); + high = Effects_log2(high); + targetFreq = Effects_log2(targetFreq); + if (high - targetFreq < targetFreq - low) { + return band + 1; + } else { + return band; + } +} + + +AudioEqualizer::AudioEqualizer(void * pMem, int nBands, int nChannels, + int sampleRate, bool ownMem, + const PresetConfig * presets, int nPresets) + : mSampleRate(sampleRate) + , mpPresets(presets) + , mNumPresets(nPresets) { + assert(pMem != NULL); + assert(nPresets == 0 || nPresets > 0 && presets != NULL); + mpMem = ownMem ? pMem : NULL; + + pMem = (char *) pMem + sizeof(AudioEqualizer); + mpLowShelf = new (pMem) AudioShelvingFilter(AudioShelvingFilter::kLowShelf, + nChannels, sampleRate); + pMem = (char *) pMem + sizeof(AudioShelvingFilter); + mpHighShelf = new (pMem) AudioShelvingFilter(AudioShelvingFilter::kHighShelf, + nChannels, sampleRate); + pMem = (char *) pMem + sizeof(AudioShelvingFilter); + mNumPeaking = nBands - 2; + if (mNumPeaking > 0) { + mpPeakingFilters = reinterpret_cast(pMem); + for (int i = 0; i < mNumPeaking; ++i) { + new (&mpPeakingFilters[i]) AudioPeakingFilter(nChannels, + sampleRate); + } + } + reset(); +} + +} diff --git a/media/libeffects/AudioEqualizer.h b/media/libeffects/AudioEqualizer.h new file mode 100644 index 0000000000000000000000000000000000000000..40284627f53627b457e3484cde065da1a460b817 --- /dev/null +++ b/media/libeffects/AudioEqualizer.h @@ -0,0 +1,246 @@ +/* + * Copyright 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 AUDIOEQUALIZER_H_ +#define AUDIOEQUALIZER_H_ + +#include "AudioCommon.h" + +namespace android { + +class AudioShelvingFilter; +class AudioPeakingFilter; + +// A parametric audio equalizer. Supports an arbitrary number of bands and +// presets. +// The EQ is composed of a low-shelf, zero or more peaking filters and a high +// shelf, where each band has frequency and gain controls, and the peaking +// filters have an additional bandwidth control. +class AudioEqualizer { +public: + // Configuration of a single band. + struct BandConfig { + // Gain in millibel. + int32_t gain; + // Frequency in millihertz. + uint32_t freq; + // Bandwidth in cents (ignored on shelving filters). + uint32_t bandwidth; + }; + + // Preset configuration. + struct PresetConfig { + // Human-readable name. + const char * name; + // An array of size nBands where each element is a configuration for the + // corresponding band. + const BandConfig * bandConfigs; + }; + + // This value is used when requesting current preset, and EQ is not using a + // preset. + static const int PRESET_CUSTOM = -1; + + // Get the required memory size for an instance of this class. + // nBands Number of bands required in the instance. + static size_t GetInstanceSize(int nBands); + + // Create an instance of this class. + // If succeeds, a respective call is expected to freeInstance(), regardless + // of who owns the context memory. + // pMem A memory buffer of at least the size returned by + // GetInstanceSize(), where the instance context is to be + // stored. If NULL, it will be automatically allocated (using + // malloc). + // nBands Number of bands. Must be >= 2. + // nChannels Number of input/output channels (interlaced). + // sampleRate The input/output sample rate, in Hz. + // presets The presets configuration. May be NULL, but in that case the + // client is required not to call preset-related functions. + // This array is owned by the client and is not copied. It + // must be kept valid by the client as long as the instance is + // alive. + // nPresets Number of elements in the presets array. + // returns The instance if success. NULL if pMem is NULL and allocation + // failed. + static AudioEqualizer * CreateInstance(void * pMem, int nBands, + int nChannels, + int sampleRate, + const PresetConfig * presets, + int nPresets); + + // Reconfiguration of the filter. Changes input/output format, but does not + // alter current parameter values. Causes reset of the delay lines. + // nChannels Number of input/output channels (interlaced). + // sampleRate The input/output sample rate, in Hz. + void configure(int nChannels, int sampleRate); + + // Resets the filter parameters to the following values: + // frequency: 0 + // gain: 0 + // bandwidth: 1200 cents. + // It also disables the filter. Does not clear the delay lines. + void reset(); + + // Clears delay lines. Does not alter parameter values. + void clear(); + + // Frees the object. Will free the memory if the object owned it, i.e. if + // a NULL pointer was passed to CreateInstance as pMem. + void free(); + + // Sets gain value. Actual change will only take place upon commit(). + // This value will be remembered even if the filter is in disabled() state. + // band The band to set the gain for. + // millibel Gain value in millibel (1/100 of decibel). + void setGain(int band, int32_t millibel); + + // Gets gain of a certain band. This is always the last value set (or + // default value after reset). + // band The band to get the gain for. + // returns Gain value in millibel (1/100 of decibel). + int32_t getGain(int band) const; + + // Sets cutoff frequency value. Actual change will only take place upon + // commit(). + // This value will be remembered even if the filter is in disabled() state. + // band The band to set the frequency for. + // millihertz Frequency value in mHz. + void setFrequency(int band, uint32_t millihertz); + + // Gets frequency of a certain band. This is always the last value set (or + // default value after reset). + // band The band to get the frequency for. + // returns Frequency value in mHz. + uint32_t getFrequency(int band) const; + + // Sets bandwidth value. Actual change will only take place upon commit(). + // This value will be remembered even if the filter is in disabled() state. + // If called on the first or last band, this call is ignored. + // band The band to set the frequency for. + // cents Bandwidth value in cents (1/1200 octave). + void setBandwidth(int band, uint32_t cents); + + // Gets bandwidth of a certain band. This is always the last value set (or + // default value after reset). For the first and last bands, 0 is always + // returned. + // band The band to get the bandwidth for. + // returns Bandwidth value in cents (1/1200 octave). + uint32_t getBandwidth(int band) const; + + // Gets lower and upper boundaries of a band. + // For the low shelf, the low bound is 0 and the high bound is the band + // frequency. + // For the high shelf, the low bound is the band frequency and the high + // bound is Nyquist. + // For the peaking filters, they are the gain[dB]/2 points. + void getBandRange(int band, uint32_t & low, uint32_t & high) const; + + // Gets a human-readable name for a preset ID. Will return "Custom" if + // PRESET_CUSTOM is passed. + // preset The preset ID. Must be less than number of presets. + const char * getPresetName(int preset) const; + + // Gets the number of presets. + int getNumPresets() const; + + // Gets the currently set preset ID. + // Will return PRESET_CUSTOM in case the EQ parameters have been modified + // manually since a preset was set. + int getPreset() const; + + // Sets the current preset by ID. + // All the band parameters will be overridden. + // Change will not be applied until commit() is called. + // preset The preset ID. Must be less than number of presets. + // PRESET_CUSTOM is NOT a valid value here. + void setPreset(int preset); + + // Applies all parameter changes done to this point in time. + // If the filter is disabled, the new parameters will take place when it is + // enabled again. Does not introduce artifacts, unless immediate is set. + // immediate Whether to apply change abruptly (ignored if filter is + // disabled). + void commit(bool immediate = false); + + // Process a buffer of input data. The input and output should contain + // frameCount * nChannels interlaced samples. Processing can be done + // in-place, by passing the same buffer as both arguments. + // pIn Input buffer. + // pOut Output buffer. + // frameCount Number of frames to produce on each call to process(). + void process(const audio_sample_t * pIn, audio_sample_t * pOut, + int frameCount); + + // Enables the filter, so it would start processing input. Does not + // introduce artifacts, unless immediate is set. + // immediate Whether to apply change abruptly. + void enable(bool immediate = false); + + // Disabled (bypasses) the filter. Does not introduce artifacts, unless + // immediate is set. + // immediate Whether to apply change abruptly. + void disable(bool immediate = false); + + // Returns the band with the maximum influence on a given frequency. + // Result is unaffected by whether EQ is enabled or not, or by whether + // changes have been committed or not. + // targetFreq The target frequency, in millihertz. + int getMostRelevantBand(uint32_t targetFreq) const; + +private: + // Bottom frequency, in mHz. + static const int kMinFreq = 20000; + // Sample rate, in Hz. + int mSampleRate; + // Number of peaking filters. Total number of bands is +2. + int mNumPeaking; + // Preset configurations. + const PresetConfig * mpPresets; + // Number of elements in mpPresets; + int mNumPresets; + // Current preset. + int mCurPreset; + + // Memory space to free when instance is deleted, or NULL if no memory is + // owned. + void * mpMem; + // The low-shelving filter. + AudioShelvingFilter * mpLowShelf; + // The high-shelving filter. + AudioShelvingFilter * mpHighShelf; + // An array of size mNumPeaking of peaking filters. + AudioPeakingFilter * mpPeakingFilters; + + // Constructor. Resets the filter (see reset()). Must call init() doing + // anything else. + // pMem Memory buffer for bands. + // nChannels Number of input/output channels (interlaced). + // sampleRate The input/output sample rate, in Hz. + // ownMem Whether pMem is owned by me. + // presets The presets configuration. May be NULL, but in that case the + // client is required not to call preset-related functions. + // This array is owned by the client and is not copied. It + // must be kept valid by the client as long as the instance is + // alive. + // nPresets Number of elements in the presets array. + AudioEqualizer(void * pMem, int nBands, int nChannels, int sampleRate, + bool ownMem, const PresetConfig * presets, int nPresets); +}; + +} + +#endif // AUDIOEQUALIZER_H_ diff --git a/media/libeffects/AudioFormatAdapter.h b/media/libeffects/AudioFormatAdapter.h new file mode 100644 index 0000000000000000000000000000000000000000..8aa5e65119b6c6271a5b4a5a6b36660c905332c4 --- /dev/null +++ b/media/libeffects/AudioFormatAdapter.h @@ -0,0 +1,184 @@ +/* /android/src/frameworks/base/media/libeffects/AudioFormatAdapter.h +** +** Copyright 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 AUDIOFORMATADAPTER_H_ +#define AUDIOFORMATADAPTER_H_ + +#include + + +#define min(x,y) (((x) < (y)) ? (x) : (y)) + +namespace android { + +// An adapter for an audio processor working on audio_sample_t samples with a +// buffer override behavior to arbitrary sample formats and buffer behaviors. +// The adapter may work on any processing class which has a processing function +// with the following signature: +// void process(const audio_sample_t * pIn, +// audio_sample_t * pOut, +// int frameCount); +// It is assumed that the underlying processor works in S7.24 format and an +// overwrite behavior. +// +// Usage is simple: just work with the processor normally, but instead of +// calling its process() function directly, work with the process() function of +// the adapter. +// The adapter supports re-configuration to a different format on the fly. +// +// T The processor class. +// bufSize The maximum number of samples (single channel) to process on a +// single call to the underlying processor. Setting this to a small +// number will save a little memory, but will cost function call +// overhead, resulting from multiple calls to the underlying process() +// per a single call to this class's process(). +template +class AudioFormatAdapter { +public: + // Configure the adapter. + // processor The underlying audio processor. + // nChannels Number of input and output channels. The adapter does not do + // channel conversion - this parameter must be in sync with the + // actual processor. + // pcmFormat The desired input/output sample format. + // behavior The desired behavior (overwrite or accumulate). + void configure(T & processor, int nChannels, uint8_t pcmFormat, + uint32_t behavior) { + mpProcessor = &processor; + mNumChannels = nChannels; + mPcmFormat = pcmFormat; + mBehavior = behavior; + mMaxSamplesPerCall = bufSize / nChannels; + } + + // Process a block of samples. + // pIn A buffer of samples with the format specified on + // configure(). + // pOut A buffer of samples with the format specified on + // configure(). May be the same as pIn. + // numSamples The number of multi-channel samples to process. + void process(const void * pIn, void * pOut, uint32_t numSamples) { + while (numSamples > 0) { + uint32_t numSamplesIter = min(numSamples, mMaxSamplesPerCall); + uint32_t nSamplesChannels = numSamplesIter * mNumChannels; + if (mPcmFormat == PCM_FORMAT_S7_24) { + if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) { + mpProcessor->process( + reinterpret_cast (pIn), + reinterpret_cast (pOut), + numSamplesIter); + } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) { + mpProcessor->process( + reinterpret_cast (pIn), + mBuffer, numSamplesIter); + MixOutput(pOut, numSamplesIter); + } else { + assert(false); + } + pIn = reinterpret_cast (pIn) + + nSamplesChannels; + pOut = reinterpret_cast (pOut) + + nSamplesChannels; + } else { + ConvertInput(pIn, nSamplesChannels); + mpProcessor->process(mBuffer, mBuffer, numSamplesIter); + ConvertOutput(pOut, nSamplesChannels); + } + numSamples -= numSamplesIter; + } + } + +private: + // The underlying processor. + T * mpProcessor; + // The number of input/output channels. + int mNumChannels; + // The desired PCM format. + uint8_t mPcmFormat; + // The desired buffer behavior. + uint32_t mBehavior; + // An intermediate buffer for processing. + audio_sample_t mBuffer[bufSize]; + // The buffer size, divided by the number of channels - represents the + // maximum number of multi-channel samples that can be stored in the + // intermediate buffer. + size_t mMaxSamplesPerCall; + + // Converts a buffer of input samples to audio_sample_t format. + // Output is written to the intermediate buffer. + // pIn The input buffer with the format designated in configure(). + // When function exist will point to the next unread input + // sample. + // numSamples The number of single-channel samples to process. + void ConvertInput(const void *& pIn, uint32_t numSamples) { + if (mPcmFormat == PCM_FORMAT_S15) { + const int16_t * pIn16 = reinterpret_cast(pIn); + audio_sample_t * pOut = mBuffer; + while (numSamples-- > 0) { + *(pOut++) = s15_to_audio_sample_t(*(pIn16++)); + } + pIn = pIn16; + } else { + assert(false); + } + } + + // Converts audio_sample_t samples from the intermediate buffer to the + // output buffer, converting to the desired format and buffer behavior. + // pOut The buffer to write the output to. + // When function exist will point to the next output sample. + // numSamples The number of single-channel samples to process. + void ConvertOutput(void *& pOut, uint32_t numSamples) { + if (mPcmFormat == PCM_FORMAT_S15) { + const audio_sample_t * pIn = mBuffer; + int16_t * pOut16 = reinterpret_cast(pOut); + if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) { + while (numSamples-- > 0) { + *(pOut16++) = audio_sample_t_to_s15_clip(*(pIn++)); + } + } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) { + while (numSamples-- > 0) { + *(pOut16++) += audio_sample_t_to_s15_clip(*(pIn++)); + } + } else { + assert(false); + } + pOut = pOut16; + } else { + assert(false); + } + } + + // Accumulate data from the intermediate buffer to the output. Output is + // assumed to be of audio_sample_t type. + // pOut The buffer to mix the output to. + // When function exist will point to the next output sample. + // numSamples The number of single-channel samples to process. + void MixOutput(void *& pOut, uint32_t numSamples) { + const audio_sample_t * pIn = mBuffer; + audio_sample_t * pOut24 = reinterpret_cast(pOut); + numSamples *= mNumChannels; + while (numSamples-- > 0) { + *(pOut24++) += *(pIn++); + } + pOut = pOut24; + } +}; + +} + +#endif // AUDIOFORMATADAPTER_H_ diff --git a/media/libeffects/AudioHighShelfFilterCoef.inl b/media/libeffects/AudioHighShelfFilterCoef.inl new file mode 100644 index 0000000000000000000000000000000000000000..ebba139c341cdb2561421721f7def4e7d3fe5502 --- /dev/null +++ b/media/libeffects/AudioHighShelfFilterCoef.inl @@ -0,0 +1,225 @@ +13679, +21575, +8921, +32315056, +-15582015, +26172, +37678, +14797, +31891096, +-15192527, +51020, +64449, +23945, +31322988, +-14685186, +101817, +106144, +37744, +30562882, +-14031372, +208996, +162163, +58536, +29548538, +-13201017, +442996, +207459, +93300, +28200792, +-12167331, +971423, +128786, +169690, +26422744, +-10915428, +2200461, +-465686, +394986, +24103317, +-9455862, +5119991, +-2777199, +1147245, +21129473, +-7842294, +12120379, +-10198160, +3631544, +17411837, +-6188384, +28834234, +-31647135, +11337795, +12924960, +-4672638, +68037766, +-88974388, +33477255, +7752680, +-3516098, +157369944, +-232063160, +92282129, +2113926, +-2925624, +353720112, +-567427144, +237164112, +-3659993, +-3019871, +769091151, +-1309871949, +570539430, +-9202114, +-3779302, +66791, +121706, +55888, +30571245, +-14038415, +120426, +212178, +94820, +29559679, +-13209886, +217130, +365165, +157610, +28215554, +-12178243, +391489, +617016, +255010, +26442131, +-10928431, +705862, +1015147, +398457, +24128430, +-9470680, +1272682, +1605251, +596102, +21161334, +-7858153, +2294668, +2386833, +848523, +17451072, +-6203880, +4137327, +3198789, +1155536, +12971362, +-4685798, +7459675, +3470266, +1567219, +7804818, +-3524761, +13449926, +1738911, +2347406, +2169089, +-2928116, +24250455, +-5211241, +4358971, +-3605298, +-3015671, +43724001, +-23849570, +9823315, +-9151253, +-3769277, +78835150, +-66542375, +23686373, +-14161143, +-5040790, +142141173, +-156324261, +56024234, +-18451275, +-6612656, +256283057, +-335606326, +126341244, +-21970004, +-8270755, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, +16777216, +33554432, +16777216, +-33554432, +-16777216, diff --git a/media/libeffects/AudioLowShelfFilterCoef.inl b/media/libeffects/AudioLowShelfFilterCoef.inl new file mode 100644 index 0000000000000000000000000000000000000000..b57deb46dea12cc1ef27bfb6db4172977c84ea7c --- /dev/null +++ b/media/libeffects/AudioLowShelfFilterCoef.inl @@ -0,0 +1,375 @@ +16212506, +-32420574, +16208068, +32401411, +-15662521, +16356129, +-32706246, +16350118, +32695525, +-15939752, +16464399, +-32920670, +16456274, +32914686, +-16149441, +16546128, +-33081289, +16535165, +33077955, +-16307411, +16608101, +-33201422, +16593328, +33199569, +-16426067, +16655539, +-33291174, +16635647, +33290147, +-16514997, +16692478, +-33358171, +16665715, +33357608, +-16581540, +16722089, +-33408149, +16686099, +33407850, +-16631271, +16746930, +-33445409, +16698549, +33445267, +-16668405, +16769156, +-33473168, +16704138, +33473133, +-16696114, +16790706, +-33493827, +16703348, +33493886, +-16716779, +16813466, +-33509166, +16696111, +33509342, +-16732186, +16839437, +-33520498, +16681802, +33520852, +-16743669, +16870911, +-33528765, +16659191, +33529424, +-16752226, +16910681, +-33534607, +16626337, +33535807, +-16758602, +15667401, +-31326224, +15658825, +31252161, +-14623074, +15945865, +-31880007, +15934146, +31838205, +-15144597, +16157521, +-32299091, +16141578, +32275604, +-15545369, +16318267, +-32614903, +16296651, +32601755, +-15850850, +16440710, +-32852157, +16411473, +32844820, +-16082303, +16534751, +-33029985, +16495281, +33025910, +-16256891, +16608171, +-33163043, +16554957, +33160803, +-16388152, +16667145, +-33262468, +16595477, +33261275, +-16486599, +16716699, +-33336671, +16620252, +33336105, +-16560301, +16761100, +-33391976, +16631379, +33391836, +-16615404, +16804207, +-33433103, +16629806, +33433341, +-16656560, +16849794, +-33463551, +16615399, +33464251, +-16687277, +16901887, +-33485857, +16586933, +33487271, +-16710189, +16965125, +-33501781, +16542000, +33504415, +-16727274, +17045198, +-33512384, +16476824, +33517183, +-16740008, +14635201, +-29254376, +14619184, +28977711, +-12753834, +15157556, +-30292825, +15135285, +30133938, +-13674513, +15561511, +-31092298, +15530817, +31001860, +-14405551, +15872211, +-31702342, +15830187, +31651218, +-14976306, +16111094, +-32164834, +16053843, +32136101, +-15416453, +16295848, +-32513802, +16218140, +32497757, +-15752817, +16440852, +-32776179, +16335665, +32767326, +-16008155, +16557804, +-32972907, +16415715, +32968179, +-16201031, +16656403, +-33120052, +16464758, +33117802, +-16346195, +16745001, +-33229805, +16486810, +33229247, +-16455153, +16831240, +-33311306, +16483692, +33312252, +-16536771, +16922682, +-33371278, +16455145, +33374070, +-16597819, +17027472, +-33414465, +16398818, +33420110, +-16643430, +17155108, +-33443875, +16310110, +33454398, +-16677479, +17317384, +-33460760, +16181887, +33479933, +-16702882, +12792703, +-25557388, +12764716, +24590507, +-9747085, +13706465, +-27372621, +13666215, +26798296, +-11169790, +14439425, +-28821830, +14382518, +28486469, +-12380088, +15018453, +-29957273, +14939030, +29764018, +-13373522, +15472460, +-30834757, +15362688, +30724568, +-14168120, +15828725, +-31506123, +15678118, +31443928, +-14791822, +16111406, +-32015988, +15905901, +31981391, +-15274688, +16341329, +-32400984, +16062061, +32382398, +-15644761, +16536484, +-32690238, +16158133, +32681354, +-15926286, +16712853, +-32906337, +16201432, +32904128, +-16139278, +16885430, +-33066336, +16195306, +33070090, +-16299767, +17069377, +-33182599, +16139282, +33193711, +-16420332, +17281371, +-33263294, +16029039, +33285785, +-16510702, +17541271, +-33312390, +15856243, +33354359, +-16578329, +17874330, +-33328902, +15608287, +33405430, +-16628873, +9881279, +-19719268, +9838084, +16734303, +-5927111, +11264857, +-22463447, +11198784, +20577584, +-7572288, +12460736, +-24823046, +12362697, +23667359, +-9201903, +13459805, +-26776851, +13317799, +26085683, +-10691555, +14276287, +-28349256, +14074406, +27943899, +-11978834, +14936943, +-29588248, +14654011, +29354533, +-13047453, +15473300, +-30549299, +15081036, +30417203, +-13909216, +15917271, +-31285788, +15377817, +31213972, +-14589687, +16299384, +-31844320, +15562006, +31809683, +-15118811, +16648774, +-32262999, +15645414, +32254329, +-15525641, +16994277, +-32571090, +15633607, +32585895, +-15835862, +17366374, +-32789019, +15525801, +32833003, +-16070975, +17799955, +-32927834, +15314895, +33017107, +-16248361, +18338206, +-32987318, +14987686, +33154246, +-16381747, +19038270, +-32951545, +14525592, +33256392, +-16481800, diff --git a/media/libeffects/AudioPeakingFilter.cpp b/media/libeffects/AudioPeakingFilter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..60fefe60bb2c7f2d810d38d0fab6bf48712821cf --- /dev/null +++ b/media/libeffects/AudioPeakingFilter.cpp @@ -0,0 +1,121 @@ +/* //device/include/server/AudioFlinger/AudioPeakingFilter.cpp + ** + ** Copyright 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. + */ + +#include "AudioPeakingFilter.h" +#include "AudioCommon.h" +#include "EffectsMath.h" + +#include +#include + +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) + +namespace android { +// Format of the coefficient table: +// kCoefTable[freq][gain][bw][coef] +// freq - peak frequency, in octaves below Nyquist,from -9 to -1. +// gain - gain, in millibel, starting at -9600, jumps of 1024, to 4736 millibel. +// bw - bandwidth, starting at 1 cent, jumps of 1024, to 3073 cents. +// coef - 0: b0 +// 1: b1 +// 2: b2 +// 3: -a1 +// 4: -a2 +static const size_t kInDims[3] = {9, 15, 4}; +static const audio_coef_t kCoefTable[9*15*4*5] = { +#include "AudioPeakingFilterCoef.inl" +}; + +AudioCoefInterpolator AudioPeakingFilter::mCoefInterp(3, kInDims, 5, (const audio_coef_t*) kCoefTable); + +AudioPeakingFilter::AudioPeakingFilter(int nChannels, int sampleRate) + : mBiquad(nChannels, sampleRate) { + configure(nChannels, sampleRate); + reset(); +} + +void AudioPeakingFilter::configure(int nChannels, int sampleRate) { + mNiquistFreq = sampleRate * 500; + mFrequencyFactor = ((1ull) << 42) / mNiquistFreq; + mBiquad.configure(nChannels, sampleRate); + setFrequency(mNominalFrequency); + commit(true); +} + +void AudioPeakingFilter::reset() { + setGain(0); + setFrequency(0); + setBandwidth(2400); + commit(true); +} + +void AudioPeakingFilter::setFrequency(uint32_t millihertz) { + mNominalFrequency = millihertz; + if (UNLIKELY(millihertz > mNiquistFreq / 2)) { + millihertz = mNiquistFreq / 2; + } + uint32_t normFreq = static_cast( + (static_cast(millihertz) * mFrequencyFactor) >> 10); + if (LIKELY(normFreq > (1 << 23))) { + mFrequency = (Effects_log2(normFreq) - ((32-9) << 15)) << (FREQ_PRECISION_BITS - 15); + } else { + mFrequency = 0; + } +} + +void AudioPeakingFilter::setGain(int32_t millibel) { + mGain = millibel + 9600; +} + +void AudioPeakingFilter::setBandwidth(uint32_t cents) { + mBandwidth = cents - 1; +} + +void AudioPeakingFilter::commit(bool immediate) { + audio_coef_t coefs[5]; + int intCoord[3] = { + mFrequency >> FREQ_PRECISION_BITS, + mGain >> GAIN_PRECISION_BITS, + mBandwidth >> BANDWIDTH_PRECISION_BITS + }; + uint32_t fracCoord[3] = { + mFrequency << (32 - FREQ_PRECISION_BITS), + static_cast(mGain) << (32 - GAIN_PRECISION_BITS), + mBandwidth << (32 - BANDWIDTH_PRECISION_BITS) + }; + mCoefInterp.getCoef(intCoord, fracCoord, coefs); + mBiquad.setCoefs(coefs, immediate); +} + +void AudioPeakingFilter::getBandRange(uint32_t & low, uint32_t & high) const { + // Half bandwidth, in octaves, 15-bit precision + int32_t halfBW = (((mBandwidth + 1) / 2) << 15) / 1200; + + low = static_cast((static_cast(mNominalFrequency) * Effects_exp2(-halfBW + (16 << 15))) >> 16); + if (UNLIKELY(halfBW >= (16 << 15))) { + high = mNiquistFreq; + } else { + high = static_cast((static_cast(mNominalFrequency) * Effects_exp2(halfBW + (16 << 15))) >> 16); + if (UNLIKELY(high > mNiquistFreq)) { + high = mNiquistFreq; + } + } +} + +} + diff --git a/media/libeffects/AudioPeakingFilter.h b/media/libeffects/AudioPeakingFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..d0f49c9e1ba905dd681b5c4b58ea3d09f1336936 --- /dev/null +++ b/media/libeffects/AudioPeakingFilter.h @@ -0,0 +1,151 @@ +/* //device/include/server/AudioFlinger/AudioPeakingFilter.h +** +** Copyright 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 ANDROID_AUDIO_PEAKING_FILTER_H +#define ANDROID_AUDIO_PEAKING_FILTER_H + +#include "AudioBiquadFilter.h" +#include "AudioCoefInterpolator.h" + +namespace android { + +// A peaking audio filter, with unity skirt gain, and controllable peak +// frequency, gain and bandwidth. +// This filter is able to suppress introduce discontinuities and other artifacts +// in the output, even when changing parameters abruptly. +// Parameters can be set to any value - this class will make sure to clip them +// when they are out of supported range. +// +// Implementation notes: +// This class uses an underlying biquad filter whose parameters are determined +// using a linear interpolation from a coefficient table, using a +// AudioCoefInterpolator. +// All is left for this class to do is mapping between high-level parameters to +// fractional indices into the coefficient table. +class AudioPeakingFilter { +public: + // Constructor. Resets the filter (see reset()). + // nChannels Number of input/output channels (interlaced). + // sampleRate The input/output sample rate, in Hz. + AudioPeakingFilter(int nChannels, int sampleRate); + + // Reconfiguration of the filter. Changes input/output format, but does not + // alter current parameter values. Clears delay lines. + // nChannels Number of input/output channels (interlaced). + // sampleRate The input/output sample rate, in Hz. + void configure(int nChannels, int sampleRate); + + // Resets the filter parameters to the following values: + // frequency: 0 + // gain: 0 + // bandwidth: 1200 cents. + // It also disables the filter. Does not clear the delay lines. + void reset(); + + // Clears delay lines. Does not alter parameter values. + void clear() { mBiquad.clear(); } + + // Sets gain value. Actual change will only take place upon commit(). + // This value will be remembered even if the filter is in disabled() state. + // millibel Gain value in millibel (1/100 of decibel). + void setGain(int32_t millibel); + + // Gets the gain, in millibel, as set. + int32_t getGain() const { return mGain - 9600; } + + // Sets bandwidth value. Actual change will only take place upon commit(). + // This value will be remembered even if the filter is in disabled() state. + // cents Bandwidth value in cents (1/1200 octave). + void setBandwidth(uint32_t cents); + + // Gets the gain, in cents, as set. + uint32_t getBandwidth() const { return mBandwidth + 1; } + + // Sets frequency value. Actual change will only take place upon commit(). + // This value will be remembered even if the filter is in disabled() state. + // millihertz Frequency value in mHz. + void setFrequency(uint32_t millihertz); + + // Gets the frequency, in mHz, as set. + uint32_t getFrequency() const { return mNominalFrequency; } + + // Gets gain[dB]/2 points. + // Results in mHz, and are computed based on the nominal values set, not on + // possibly rounded or truncated actual values. + void getBandRange(uint32_t & low, uint32_t & high) const; + + // Applies all parameter changes done to this point in time. + // If the filter is disabled, the new parameters will take place when it is + // enabled again. Does not introduce artifacts, unless immediate is set. + // immediate Whether to apply change abruptly (ignored if filter is + // disabled). + void commit(bool immediate = false); + + // Process a buffer of input data. The input and output should contain + // frameCount * nChannels interlaced samples. Processing can be done + // in-place, by passing the same buffer as both arguments. + // in Input buffer. + // out Output buffer. + // frameCount Number of frames to produce. + void process(const audio_sample_t in[], audio_sample_t out[], + int frameCount) { mBiquad.process(in, out, frameCount); } + + // Enables the filter, so it would start processing input. Does not + // introduce artifacts, unless immediate is set. + // immediate Whether to apply change abruptly. + void enable(bool immediate = false) { mBiquad.enable(immediate); } + + // Disabled (bypasses) the filter. Does not introduce artifacts, unless + // immediate is set. + // immediate Whether to apply change abruptly. + void disable(bool immediate = false) { mBiquad.disable(immediate); } + +private: + // Precision for the mFrequency member. + static const int FREQ_PRECISION_BITS = 26; + // Precision for the mGain member. + static const int GAIN_PRECISION_BITS = 10; + // Precision for the mBandwidth member. + static const int BANDWIDTH_PRECISION_BITS = 10; + + // Nyquist, in mHz. + uint32_t mNiquistFreq; + // Fractional index into the gain dimension of the coef table in + // GAIN_PRECISION_BITS precision. + int32_t mGain; + // Fractional index into the bandwidth dimension of the coef table in + // BANDWIDTH_PRECISION_BITS precision. + uint32_t mBandwidth; + // Fractional index into the frequency dimension of the coef table in + // FREQ_PRECISION_BITS precision. + uint32_t mFrequency; + // Nominal value of frequency, as set. + uint32_t mNominalFrequency; + // 1/Nyquist[mHz], in 42-bit precision (very small). + // Used for scaling the frequency. + uint32_t mFrequencyFactor; + + // A biquad filter, used for the actual processing. + AudioBiquadFilter mBiquad; + // A coefficient interpolator, used for mapping the high level parameters to + // the low-level biquad coefficients. + static AudioCoefInterpolator mCoefInterp; +}; + +} + +#endif // ANDROID_AUDIO_PEAKING_FILTER_H diff --git a/media/libeffects/AudioPeakingFilterCoef.inl b/media/libeffects/AudioPeakingFilterCoef.inl new file mode 100644 index 0000000000000000000000000000000000000000..374c6e11d0436a6034b73bfb5d72f6d63c7e0003 --- /dev/null +++ b/media/libeffects/AudioPeakingFilterCoef.inl @@ -0,0 +1,2700 @@ +16769751, +-33538871, +16769751, +33538871, +-16762286, +11468083, +-22935566, +11467915, +22935566, +-6158781, +8532673, +-17064763, +8532412, +17064763, +-287869, +6567366, +-13134160, +6567042, +13134160, +3642808, +16773075, +-33545518, +16773075, +33545518, +-16768934, +13349658, +-26698459, +13349304, +26698459, +-9921746, +10923581, +-21846147, +10922977, +21846147, +-5069342, +9009390, +-18017641, +9008590, +18017641, +-1240764, +16774919, +-33549207, +16774919, +33549207, +-16772622, +14686150, +-29371047, +14685450, +29371047, +-12594384, +12933736, +-25865697, +12932448, +25865697, +-9088968, +11350364, +-22698482, +11348545, +22698482, +-5921693, +16775943, +-33551252, +16775941, +33551252, +-16774668, +15549746, +-31097569, +15548408, +31097569, +-14320938, +14404163, +-28805197, +14401577, +28805197, +-12028524, +13261978, +-26519626, +13258147, +26519626, +-9742909, +16776511, +-33552387, +16776508, +33552387, +-16775803, +16074349, +-32145600, +16071856, +32145600, +-15368989, +15374244, +-30742933, +15369268, +30742933, +-13966296, +14629431, +-29250695, +14621814, +29250695, +-12474030, +16776826, +-33553017, +16776822, +33553017, +-16776432, +16381548, +-32757900, +16376968, +32757900, +-15981300, +15972161, +-31934402, +15962842, +31934402, +-15157787, +15518882, +-31022614, +15504316, +31022614, +-14245982, +16777003, +-33553366, +16776995, +33553366, +-16776781, +16558315, +-33107660, +16549969, +33107660, +-16331067, +16326848, +-32635910, +16309677, +32635910, +-15859308, +16064456, +-32101133, +16037281, +32101133, +-15324521, +16777103, +-33553559, +16777088, +33553559, +-16776975, +16660325, +-33304885, +16645187, +33304885, +-16528296, +16535200, +-33038436, +16503858, +33038436, +-16261842, +16391425, +-32732273, +16341464, +32732273, +-15955673, +16777162, +-33553667, +16777136, +33553667, +-16777082, +16721651, +-33415288, +16694267, +33415288, +-16638701, +16661761, +-33265997, +16604862, +33265997, +-16489407, +16592417, +-33093137, +16501343, +33093137, +-16316544, +16777203, +-33553726, +16777155, +33553726, +-16777142, +16763466, +-33476836, +16714001, +33476836, +-16700251, +16748588, +-33393565, +16645605, +33393565, +-16616978, +16731288, +-33296733, +16566071, +33296733, +-16520144, +16777238, +-33553759, +16777152, +33553759, +-16777175, +16800489, +-33511071, +16711212, +33511071, +-16734485, +16825723, +-33464740, +16639647, +33464740, +-16688154, +16855137, +-33410736, +16556228, +33410736, +-16634149, +16777282, +-33553778, +16777127, +33553778, +-16777193, +16845889, +-33530088, +16684830, +33530088, +-16753503, +16920437, +-33504347, +16584541, +33504347, +-16727762, +17007449, +-33474302, +16467484, +33474302, +-16697716, +16777349, +-33553788, +16777070, +33553788, +-16777203, +16915880, +-33540645, +16625396, +33540645, +-16764060, +17066504, +-33526354, +16460481, +33526354, +-16749769, +17242444, +-33509662, +16267849, +33509662, +-16733077, +16777464, +-33553793, +16776961, +33553793, +-16777209, +17035487, +-33546503, +16511647, +33546503, +-16769918, +17316137, +-33538572, +16223067, +33538572, +-16761988, +17644089, +-33529306, +15885848, +33529306, +-16752721, +16777668, +-33553796, +16776760, +33553796, +-16777212, +17247484, +-33549752, +16302900, +33549752, +-16773168, +17758603, +-33545353, +15787381, +33545353, +-16768768, +18356007, +-33540211, +15184835, +33540211, +-16763626, +16762293, +-33522062, +16762293, +33522062, +-16747370, +8711405, +-17421242, +8711149, +17421242, +-645338, +5721250, +-11441288, +5720900, +11441288, +5335066, +4082836, +-8164655, +4082434, +8164655, +8611946, +16768936, +-33535347, +16768936, +33535347, +-16760656, +11085056, +-22167856, +11084469, +22167856, +-5392309, +8098223, +-16194333, +8097329, +16194333, +581664, +6158323, +-12314623, +6157228, +12314623, +4461665, +16772623, +-33542719, +16772622, +33542719, +-16768029, +13058634, +-26114055, +13057388, +26114055, +-9338806, +10523211, +-21042742, +10521116, +21042742, +-4267110, +8576560, +-17149081, +8573812, +17149081, +-373156, +16774670, +-33546810, +16774667, +33546810, +-16772120, +14489725, +-28974776, +14487233, +28974776, +-12199742, +12619509, +-25232587, +12614979, +25232587, +-8457271, +10965151, +-21922319, +10958818, +21922319, +-5146753, +16775805, +-33549079, +16775800, +33549079, +-16774390, +15428102, +-30849095, +15423317, +30849095, +-14074202, +14188157, +-28364996, +14178975, +28364996, +-11589916, +12969900, +-25924346, +12956398, +25924346, +-9149082, +16776437, +-33550338, +16776428, +33550338, +-16775648, +16004216, +-31997074, +15995268, +31997074, +-15222267, +15241233, +-30462393, +15223454, +30462393, +-13687471, +14437070, +-28844880, +14409982, +28844880, +-12069836, +16776789, +-33551036, +16776773, +33551036, +-16776347, +16345158, +-32671383, +16328685, +32671383, +-15896627, +15900462, +-31765104, +15867034, +31765104, +-14990280, +15410846, +-30767279, +15358750, +30767279, +-13992380, +16776990, +-33551423, +16776960, +33551423, +-16776734, +16545156, +-33057769, +16515103, +33057769, +-16283043, +16300504, +-32536823, +16238769, +32536823, +-15762058, +16024071, +-31948201, +15926537, +31948201, +-15173391, +16777109, +-33551638, +16777056, +33551638, +-16776949, +16666542, +-33276035, +16611999, +33276035, +-16501325, +16548270, +-32981225, +16435439, +32981225, +-16206493, +16412621, +-32643103, +16232940, +32643103, +-15868346, +16777189, +-33551757, +16777094, +33551757, +-16777068, +16749778, +-33398338, +16651075, +33398338, +-16623637, +16720233, +-33232976, +16515245, +33232976, +-16458262, +16686059, +-33041706, +16358135, +33041706, +-16266978, +16777261, +-33551823, +16777089, +33551823, +-16777134, +16823703, +-33466559, +16645376, +33466559, +-16691863, +16873974, +-33374267, +16502806, +33374267, +-16599564, +16932398, +-33267006, +16337114, +33267006, +-16492295, +16777348, +-33551860, +16777038, +33551860, +-16777170, +16914465, +-33504517, +16592574, +33504517, +-16729824, +17063236, +-33453150, +16392432, +33453150, +-16678453, +17236595, +-33393293, +16159213, +33393293, +-16618592, +16777483, +-33551880, +16776924, +33551880, +-16777191, +17054436, +-33525606, +16473695, +33525606, +-16750914, +17355321, +-33497061, +16144262, +33497061, +-16722367, +17706453, +-33463749, +15759816, +33463749, +-16689053, +16777713, +-33551891, +16776705, +33551891, +-16777202, +17293646, +-33537314, +16246194, +33537314, +-16762623, +17854571, +-33521465, +15669419, +33521465, +-16746773, +18509706, +-33502954, +14995772, +33502954, +-16728261, +16778120, +-33551898, +16776304, +33551898, +-16777208, +17717639, +-33543811, +15828698, +33543811, +-16769121, +18739501, +-33535016, +14798040, +33535016, +-16760325, +19933534, +-33524738, +13593729, +33524738, +-16750047, +16747397, +-33484705, +16747396, +33484705, +-16717577, +5883112, +-11762335, +5882767, +11762335, +5011337, +3448701, +-6894903, +3448279, +6894903, +9880236, +2324286, +-4646714, +2323828, +4646714, +12129102, +16760665, +-33511232, +16760663, +33511232, +-16744112, +8276984, +-16548106, +8276108, +16548106, +224124, +5337400, +-10670406, +5336221, +10670406, +6103596, +3771525, +-7539439, +3770185, +7539439, +9235506, +16768033, +-33525963, +16768030, +33525963, +-16758848, +10689564, +-21370649, +10687524, +21370649, +-4599872, +7666068, +-15324466, +7663015, +15324466, +1448133, +5761266, +-11515371, +5757575, +11515371, +5258376, +16772124, +-33534139, +16772118, +33534139, +-16767026, +12751423, +-25490780, +12747036, +25490780, +-8721243, +10113942, +-20214533, +10106682, +20214533, +-3443407, +8145025, +-16275741, +8135620, +16275741, +496571, +16774395, +-33538675, +16774385, +33538675, +-16771564, +14280137, +-28542819, +14271281, +28542819, +-11774202, +12292391, +-24561476, +12276485, +24561476, +-7791660, +10572949, +-21117532, +10550945, +21117532, +-4346678, +16775657, +-33541192, +16775639, +33541192, +-16774081, +15299683, +-30573051, +15282579, +30573051, +-13805046, +13964251, +-27887539, +13931690, +27887539, +-11118724, +12672686, +-25290241, +12625174, +25290241, +-8520644, +16776363, +-33542588, +16776330, +33542588, +-16775477, +15935196, +-31828699, +15903092, +31828699, +-15061072, +15112356, +-30152153, +15048881, +30152153, +-13384021, +14253857, +-28402950, +14157649, +28402950, +-11634291, +16776763, +-33543362, +16776704, +33543362, +-16776252, +16319830, +-32570615, +16260598, +32570615, +-15803212, +15851783, +-31574208, +15731938, +31574208, +-14806505, +15339614, +-30483871, +15153441, +30483871, +-13715838, +16777001, +-33543791, +16776896, +33543791, +-16776681, +16557673, +-32997208, +16449476, +32997208, +-16229933, +16326977, +-32422299, +16105089, +32422299, +-15654851, +16067244, +-31775024, +15717353, +31775024, +-15007381, +16777163, +-33544029, +16776972, +33544029, +-16776919, +16722590, +-33238660, +16526083, +33238660, +-16471458, +16664322, +-32912610, +16258203, +32912610, +-16145310, +16597629, +-32539419, +15951593, +32539419, +-15772007, +16777306, +-33544162, +16776962, +33544162, +-16777051, +16869955, +-33374105, +16514205, +33374105, +-16606944, +16969714, +-33190996, +16231282, +33190996, +-16423780, +17084972, +-32979442, +15904406, +32979442, +-16212162, +16777480, +-33544235, +16776860, +33544235, +-16777125, +17051328, +-33449703, +16408452, +33449703, +-16682565, +17347583, +-33347437, +16009901, +33347437, +-16580267, +17691668, +-33228659, +15547002, +33228659, +-16461454, +16777750, +-33544275, +16776632, +33544275, +-16777165, +17331222, +-33491780, +16170648, +33491780, +-16724654, +17931550, +-33434840, +15513363, +33434840, +-16667697, +18630855, +-33368512, +14747710, +33368512, +-16601349, +16778210, +-33544298, +16776194, +33544298, +-16777188, +17809628, +-33515162, +15715631, +33515162, +-16748043, +18929991, +-33483514, +14563611, +33483514, +-16716385, +20237212, +-33446587, +13219451, +33446587, +-16679448, +16779025, +-33544310, +16775392, +33544310, +-16777200, +18657612, +-33528145, +14880634, +33528145, +-16761030, +20699844, +-33510571, +12820822, +33510571, +-16743451, +23084863, +-33490047, +10415274, +33490047, +-16722921, +16717684, +-33395091, +16717682, +33395091, +-16658149, +3567009, +-7125006, +3566590, +7125006, +9643617, +1921926, +-3838751, +1921455, +3838751, +12933835, +1248662, +-2493824, +1248170, +2493824, +14280384, +16744147, +-33447952, +16744143, +33447952, +-16711074, +5493785, +-10973174, +5492622, +10973174, +5790808, +3173694, +-6338342, +3172292, +6338342, +10431230, +2124754, +-4242881, +2123244, +4242881, +12529218, +16758861, +-33477342, +16758855, +33477342, +-16740500, +7843885, +-15665884, +7840892, +15665884, +1092439, +4968649, +-9921376, +4964692, +9921376, +6843875, +3478437, +-6944043, +3473981, +6944043, +9824798, +16767035, +-33493665, +16767024, +33493665, +-16756842, +10284421, +-20536999, +10277346, +20536999, +-3784550, +7240254, +-14452686, +7229862, +14452686, +2307100, +5379798, +-10734231, +5367379, +10734231, +6030039, +16771575, +-33502725, +16771555, +33502725, +-16765913, +12431046, +-24816749, +12415632, +24816749, +-8069462, +9702049, +-19355664, +9676957, +19355664, +-2601790, +7722611, +-15394544, +7690499, +15394544, +1364106, +16774099, +-33507752, +16774063, +33507752, +-16770946, +14062583, +-28059903, +14031160, +28059903, +-11316527, +11962999, +-23841519, +11907273, +23841519, +-7093056, +10188929, +-20277142, +10112667, +20277142, +-3524380, +16775510, +-33510541, +16775445, +33510541, +-16773738, +15175102, +-30252637, +15114019, +30252637, +-13511905, +13753207, +-27358123, +13637911, +27358123, +-10613901, +12400971, +-24605416, +12234119, +24605416, +-7857874, +16776310, +-33512088, +16776193, +33512088, +-16775287, +15888242, +-31623221, +15773117, +31623221, +-14884143, +15028972, +-29795608, +14802570, +29795608, +-13054325, +14142237, +-27909578, +13801000, +27909578, +-11166021, +16776787, +-33512946, +16776575, +33512946, +-16776146, +16345172, +-32438302, +16132251, +32438302, +-15700207, +15905856, +-31344484, +15476429, +31344484, +-14605069, +15428324, +-30155514, +14763558, +30155514, +-13414665, +16777110, +-33513422, +16776729, +33513422, +-16776623, +16668950, +-32908744, +16279482, +32908744, +-16171216, +16555594, +-32275015, +15758344, +32275015, +-15536722, +16428465, +-31564284, +15173886, +31564284, +-14825134, +16777395, +-33513686, +16776708, +33513686, +-16776887, +16961758, +-33175594, +16253845, +33175594, +-16438387, +17158212, +-32815329, +15696692, +32815329, +-16077688, +17382578, +-32403880, +15060381, +32403880, +-15665743, +16777745, +-33513832, +16776505, +33513832, +-16777033, +17323903, +-33325470, +16041757, +33325470, +-16588444, +17911332, +-33122874, +15251488, +33122874, +-16385604, +18589203, +-32889086, +14339546, +32889086, +-16151534, +16778283, +-33513913, +16776048, +33513913, +-16777115, +17883505, +-33409180, +15565966, +33409180, +-16672255, +19078451, +-33295944, +14257648, +33295944, +-16558883, +20465440, +-33164510, +12739067, +33164510, +-16427290, +16779203, +-33513958, +16775173, +33513958, +-16777160, +18840265, +-33455789, +14655871, +33455789, +-16718921, +21075121, +-33392715, +12357866, +33392715, +-16655771, +23677621, +-33319266, +9681828, +33319266, +-16582233, +16780834, +-33513983, +16773567, +33513983, +-16777185, +20536227, +-33481696, +12985848, +33481696, +-16744859, +24614855, +-33446630, +8872112, +33446630, +-16709751, +29373075, +-33405721, +4072934, +33405721, +-16668793, +16658572, +-33156710, +16658568, +33156710, +-16539925, +1995694, +-3971702, +1995225, +3971702, +12786296, +1019334, +-2028355, +1018835, +2028355, +14739047, +648397, +-1290041, +647886, +1290041, +15480933, +16711208, +-33261470, +16711201, +33261470, +-16645192, +3284873, +-6536727, +3283483, +6536727, +10208860, +1752746, +-3487071, +1751198, +3487071, +13273272, +1134254, +-2255981, +1132642, +2255981, +14510319, +16740546, +-33319859, +16740534, +33319859, +-16703864, +5119019, +-10184853, +5115113, +10184853, +6543083, +2916766, +-5800820, +2912122, +5800820, +10948329, +1940950, +-3858260, +1935979, +3858260, +12900288, +16756866, +-33352332, +16756844, +33352332, +-16736493, +7416141, +-14750709, +7405941, +14750709, +1955134, +4618132, +-9178604, +4604884, +9178604, +7554200, +3205731, +-6365873, +3190944, +6365873, +10380541, +16765937, +-33370369, +16765897, +33370369, +-16754618, +9875714, +-19631961, +9851238, +19631961, +-2949736, +6828874, +-13556870, +6793592, +13556870, +3154751, +5021920, +-9953987, +4980230, +9953987, +6775066, +16770983, +-33380381, +16770911, +33380381, +-16764679, +12107731, +-24045066, +12053679, +24045066, +-7384194, +9304697, +-18433704, +9218200, +18433704, +-1745681, +7330173, +-14480925, +7220819, +14480925, +2226224, +16773804, +-33385937, +16773674, +33385937, +-16770261, +13857067, +-27469883, +13745731, +27469883, +-10825583, +11667230, +-23028209, +11472403, +23028209, +-6362417, +9861509, +-19365642, +9597835, +19365642, +-2682128, +16775405, +-33389019, +16775170, +33389019, +-16773358, +15094166, +-29826057, +14876207, +29826057, +-13193157, +13629575, +-26722225, +13221948, +26722225, +-10074307, +12261304, +-23822520, +11676482, +23822520, +-7160571, +16776358, +-33390729, +16775935, +33390729, +-16775076, +15939973, +-31315809, +15527360, +31315809, +-14690117, +15140254, +-29331850, +14333520, +29331850, +-12696558, +14324552, +-27308240, +13115821, +27308240, +-10663157, +16777004, +-33391677, +16776241, +33391677, +-16776029, +16564519, +-32208051, +15799374, +32208051, +-15586676, +16349720, +-31011538, +14811870, +31011538, +-14384374, +16117884, +-29720119, +13746038, +29720119, +-13086705, +16777574, +-33392203, +16776199, +33392203, +-16776558, +17142623, +-32725183, +15740903, +32725183, +-16106310, +17523746, +-32028793, +14660021, +32028793, +-15406551, +17949452, +-31250941, +13452699, +31250941, +-14624935, +16778273, +-33392495, +16775794, +33392495, +-16776851, +17864511, +-33019221, +15314476, +33019221, +-16401771, +19019582, +-32622294, +13760557, +32622294, +-16002923, +20335886, +-32169961, +11989731, +32169961, +-15548401, +16779350, +-33392657, +16774879, +33392657, +-16777014, +18982972, +-33184592, +14362186, +33184592, +-16567942, +21350554, +-32961046, +11769976, +32961046, +-16343314, +24079688, +-32703362, +8781912, +32703362, +-16084383, +16781190, +-33392746, +16773130, +33392746, +-16777104, +20896303, +-33277026, +12541737, +33277026, +-16660824, +25343199, +-33151977, +7969185, +33151977, +-16535169, +30502384, +-33006896, +2664219, +33006896, +-16389387, +16784451, +-33392796, +16769918, +33392796, +-16777154, +24288258, +-33328516, +9201520, +33328516, +-16712562, +32423187, +-33258828, +996567, +33258828, +-16642538, +41895320, +-33177686, +-8557101, +33177686, +-16561003, +16541595, +-32447498, +16541587, +32447498, +-16305966, +1060925, +-2080590, +1060426, +2080590, +14655865, +525478, +-1030256, +524962, +1030256, +15726776, +330321, +-647437, +329800, +647437, +16117095, +16645717, +-32651734, +16645703, +32651734, +-16514203, +1820789, +-3570095, +1819248, +3570095, +13137179, +924575, +-1812018, +922942, +1812018, +14929699, +586684, +-1149186, +585016, +1149186, +15605516, +16704036, +-32766121, +16704011, +32766121, +-16630831, +3020875, +-5921138, +3016266, +5921138, +10740076, +1597573, +-3128764, +1592487, +3128764, +13587156, +1030124, +-2015487, +1024848, +2015487, +14722244, +16736565, +-32829909, +16736521, +32829909, +-16695869, +4762013, +-9328185, +4748922, +9328185, +7266281, +2679566, +-5241091, +2664205, +5241091, +11433446, +1773912, +-3463620, +1757564, +3463620, +13245740, +16754673, +-32865395, +16754593, +32865395, +-16732050, +7001772, +-13700468, +6967104, +13700468, +2808340, +4293363, +-8378312, +4249089, +8378312, +8234764, +2960061, +-5758307, +2911058, +5758307, +10906097, +16764756, +-32885110, +16764611, +32885110, +-16752151, +9480188, +-18513215, +9395722, +18513215, +-2098694, +6453693, +-12542171, +6334194, +12542171, +3989330, +4710641, +-9103264, +4570966, +9103264, +7495609, +16770393, +-32896054, +16770133, +32896054, +-16763310, +11816276, +-22992949, +11627131, +22992949, +-6666191, +8975726, +-17314789, +8678280, +17314789, +-876790, +7032408, +-13430164, +6660869, +13430164, +3083940, +16773593, +-32902127, +16773124, +32902127, +-16769502, +13735615, +-26557052, +13341720, +26557052, +-10300120, +11528165, +-21946606, +10848400, +21946606, +-5599349, +9752563, +-18238110, +8842853, +18238110, +-1818200, +16775499, +-32905496, +16774654, +32905496, +-16772937, +15200588, +-29054957, +14423589, +29054957, +-12846961, +13857004, +-25769995, +12417855, +25769995, +-9497643, +12624453, +-22756500, +10577873, +22756500, +-6425111, +16776792, +-32907365, +16775267, +32907365, +-16774843, +16366344, +-30654089, +14888294, +30654089, +-14477422, +15978753, +-28526295, +13106406, +28526295, +-12307942, +15588057, +-26381456, +11310242, +26381456, +-10121083, +16777933, +-32908402, +16775183, +32908402, +-16775900, +17493802, +-31619287, +14744943, +31619287, +-15461529, +18212414, +-30325234, +12706927, +30325234, +-14142124, +18982725, +-28938081, +10522286, +28938081, +-12727795, +16779330, +-32908977, +16774372, +32908977, +-16776486, +18928041, +-32181280, +13883707, +32181280, +-16034532, +21163118, +-31424334, +10876855, +31424334, +-15262757, +23650871, +-30581814, +7530076, +30581814, +-14403731, +16781484, +-32909296, +16772543, +32909296, +-16776811, +21161996, +-32501674, +11976424, +32501674, +-16361204, +25812009, +-32068975, +6885234, +32068975, +-15920027, +31103385, +-31576594, +1091831, +31576594, +-15418000, +16785164, +-32909473, +16769043, +32909473, +-16776991, +24988064, +-32682139, +8334356, +32682139, +-16545204, +33795794, +-32438043, +-722252, +32438043, +-16296325, +43946128, +-32156738, +-11159403, +32156738, +-16009510, +16791687, +-32909571, +16762620, +32909571, +-16777091, +31772521, +-32783096, +1652834, +32783096, +-16648139, +47961229, +-32646423, +-14675225, +32646423, +-16508788, +66751682, +-32487785, +-33627423, +32487785, +-16347043, +16312500, +-30141556, +16312485, +30141556, +-15847769, +547598, +-1011354, +547084, +1011354, +15682534, +266448, +-491849, +265925, +491849, +16244843, +166111, +-306446, +165584, +306446, +16445521, +16516262, +-30518049, +16516236, +30518049, +-16255282, +962487, +-1776938, +960857, +1776938, +14853872, +474742, +-875656, +473062, +875656, +15829413, +297520, +-548176, +295821, +548176, +16183875, +16631492, +-30730944, +16631443, +30730944, +-16485719, +1660146, +-3062870, +1655081, +3062870, +13461989, +838172, +-1543806, +832831, +1543806, +15106213, +530135, +-974532, +524691, +974532, +15722390, +16696110, +-30850307, +16696022, +30850307, +-16614916, +2776642, +-5116472, +2761387, +5116472, +11239187, +1456845, +-2676477, +1440152, +2676477, +13880219, +936151, +-1713835, +918891, +1713835, +14922174, +16732191, +-30916910, +16732031, +30916910, +-16687006, +4430219, +-8145523, +4386431, +8145523, +7960566, +2467715, +-4512857, +2416966, +4512857, +11892535, +1628113, +-2958725, +1574387, +2958725, +13574716, +16752314, +-30953973, +16752025, +30953973, +-16727123, +6622193, +-12127616, +6504644, +12127616, +3650379, +4016541, +-7285135, +3868831, +7285135, +8891843, +2762675, +-4954883, +2600451, +4954883, +11414089, +16763575, +-30974568, +16763055, +30974568, +-16749415, +9150431, +-16639142, +8859646, +16639142, +-1232861, +6182181, +-11049974, +5778225, +11049974, +4816810, +4518629, +-7917532, +4051247, +7917532, +8207341, +16769973, +-30986002, +16769034, +30986002, +-16761791, +11676269, +-20964630, +11015683, +20964630, +-5914736, +8893418, +-15489638, +7872446, +15489638, +11352, +7041383, +-11845939, +5780568, +11845939, +3955265, +16773783, +-30992347, +16772092, +30992347, +-16768659, +13953280, +-24496534, +12561577, +24496534, +-9737641, +11970921, +-19931025, +9602265, +19931025, +-4795970, +10413172, +-16343421, +7276820, +16343421, +-912775, +16776368, +-30995868, +16773318, +30995868, +-16772470, +16007790, +-27021343, +13239901, +27021343, +-12470475, +15365527, +-23700024, +10287194, +23700024, +-8875505, +14785947, +-20702857, +7622664, +20702857, +-5631395, +16778650, +-30997821, +16773150, +30997821, +-16774583, +18157056, +-28659649, +12863925, +28659649, +-14243764, +19443806, +-26476950, +9214638, +26476950, +-11881228, +20728681, +-24297433, +5570671, +24297433, +-9522136, +16781445, +-30998904, +16771527, +30998904, +-16775756, +20988060, +-29656921, +11112361, +29656921, +-15323204, +25187743, +-28317150, +5462520, +28317150, +-13873047, +29672124, +-26886556, +-570326, +26886556, +-12324582, +16785752, +-30999505, +16767870, +30999505, +-16776406, +25444300, +-30240545, +7287830, +30240545, +-15954914, +34434980, +-29452472, +-2555854, +29452472, +-15101910, +44441242, +-28575379, +-13511474, +28575379, +-14152552, +16793112, +-30999838, +16760871, +30999838, +-16776767, +33095506, +-30574250, +-2177, +30574250, +-16316113, +50408034, +-30122291, +-17803902, +30122291, +-15826917, +70153765, +-29606811, +-38107583, +29606811, +-15268966, +16806158, +-31000023, +16748025, +31000023, +-16776967, +46670155, +-30762526, +-13373037, +30762526, +-16519902, +78789544, +-30507092, +-45768905, +30507092, +-16243423, +115942747, +-30211627, +-83241918, +30211627, +-15923613, +15872835, +-22447559, +15872807, +22447559, +-14968426, +277754, +-392434, +277231, +392434, +16222231, +133061, +-187804, +132533, +187804, +16511622, +81763, +-115256, +81233, +115256, +16614220, +16263303, +-22999746, +16263250, +22999746, +-15749337, +494605, +-698290, +492927, +698290, +15789685, +238776, +-336475, +237071, +336475, +16301369, +147228, +-207000, +145514, +207000, +16484473, +16488278, +-23317877, +16488181, +23317877, +-16199242, +872378, +-1229961, +867049, +1229961, +15037788, +426889, +-599839, +421411, +599839, +15928916, +264840, +-370629, +259308, +370629, +16253068, +16615785, +-23498145, +16615609, +23498145, +-16454179, +1513757, +-2129016, +1497126, +2129016, +13766333, +758261, +-1060001, +740806, +1060001, +15278149, +475551, +-659971, +457789, +659971, +15843875, +16687407, +-23599332, +16687089, +23599332, +-16597280, +2557116, +-3580647, +2506684, +3580647, +11713416, +1332007, +-1845009, +1277230, +1845009, +14167979, +851272, +-1163942, +794791, +1163942, +15131154, +16727486, +-23655830, +16726910, +23655830, +-16677180, +4144749, +-5758163, +3998523, +5758163, +8633944, +2297803, +-3131069, +2130198, +3131069, +12349216, +1516025, +-2019070, +1339371, +2019070, +13921820, +16749957, +-23687282, +16748918, +23687282, +-16721660, +6342807, +-8688774, +5944975, +8688774, +4489434, +3855722, +-5104454, +3363066, +5104454, +9558428, +2678286, +-3407564, +2140738, +3407564, +11958192, +16762736, +-23704762, +16760861, +23704762, +-16746380, +9059948, +-12106014, +8060542, +12106014, +-343274, +6231959, +-7847669, +4866322, +7847669, +5678936, +4678573, +-5508603, +3111768, +5508603, +8986875, +16770353, +-23714468, +16766970, +23714468, +-16760107, +12100768, +-15483427, +9796104, +15483427, +-5119656, +9659401, +-11180047, +6151573, +11180047, +966242, +8066003, +-8371376, +3772911, +8371376, +4938302, +16775520, +-23719855, +16769420, +23719855, +-16767725, +15410647, +-18317794, +10494626, +18317794, +-9128056, +14477439, +-14624233, +6204350, +14624233, +-3904573, +13754127, +-11761419, +2879032, +11761419, +144058, +16780083, +-23722844, +16769084, +23722844, +-16771951, +19348947, +-20387735, +9483664, +20387735, +-12055395, +21467038, +-17637855, +3476656, +17637855, +-8166478, +23369301, +-15168181, +-1918253, +15168181, +-4673832, +16785673, +-23724501, +16765839, +23724501, +-16774296, +24868547, +-21750945, +5891934, +21750945, +-13983265, +32392543, +-19913847, +-4230110, +19913847, +-11385217, +39938641, +-18071353, +-14381888, +18071353, +-8779537, +16794288, +-23725421, +16758525, +23725421, +-16775596, +33739025, +-22588636, +-1793870, +22588636, +-15167940, +50727371, +-21448926, +-20394010, +21448926, +-13556146, +69082218, +-20217540, +-40490298, +20217540, +-11814703, +16809008, +-23725931, +16744526, +23725931, +-16776318, +49053594, +-23081666, +-16411189, +23081666, +-15865189, +82824296, +-22406908, +-51136143, +22406908, +-14910937, +121049915, +-21643138, +-90441895, +21643138, +-13830803, +16835099, +-23726214, +16718835, +23726214, +-16776718, +76261468, +-23364505, +-43219068, +23364505, +-16265184, +140080603, +-22976059, +-107587549, +22976059, +-15715838, +214348557, +-22524014, +-182494791, +22524014, +-15076550, +15060971, +0, +15060916, +0, +-13344671, +137715, +0, +137188, +0, +16502313, +62494, +0, +61964, +0, +16652757, +35499, +0, +34969, +0, +16706748, +15779939, +0, +15779837, +0, +-14782560, +247059, +0, +245356, +0, +16284801, +112726, +0, +111009, +0, +16553481, +64282, +0, +62560, +0, +16650375, +16209124, +0, +16208934, +0, +-15640842, +441483, +0, +436010, +0, +15899723, +203401, +0, +197848, +0, +16375967, +116794, +0, +111212, +0, +16549211, +16457433, +0, +16457085, +0, +-16137302, +783510, +0, +766083, +0, +15227623, +367229, +0, +349349, +0, +16060638, +213457, +0, +195409, +0, +16368349, +16598556, +0, +16597923, +0, +-16419263, +1374332, +0, +1319705, +0, +14083179, +663683, +0, +606536, +0, +15506996, +394077, +0, +335974, +0, +16047166, +16678051, +0, +16676903, +0, +-16577738, +2365010, +0, +2198183, +0, +12214023, +1201479, +0, +1021183, +0, +14554554, +739666, +0, +554025, +0, +15483525, +16722789, +0, +16720714, +0, +-16666287, +3953214, +0, +3464275, +0, +9359728, +2180807, +0, +1624291, +0, +12972118, +1423936, +0, +838564, +0, +14514716, +16748282, +0, +16744535, +0, +-16715601, +6353786, +0, +5003926, +0, +5419504, +3973108, +0, +2314944, +0, +10489165, +2837511, +0, +1032284, +0, +12907421, +16763496, +0, +16756735, +0, +-16743015, +9775978, +0, +6325602, +0, +675636, +7269959, +0, +2584558, +0, +6922698, +5878520, +0, +507384, +0, +10391313, +16773826, +0, +16761629, +0, +-16758239, +14526462, +0, +6429723, +0, +-4178968, +13351086, +0, +1026117, +0, +2400012, +12566846, +0, +-2579306, +0, +6789676, +16782950, +0, +16760954, +0, +-16766688, +21346996, +0, +3817102, +0, +-8386881, +24548257, +0, +-5261828, +0, +-2509212, +27136746, +0, +-12602908, +0, +2243378, +16794129, +0, +16754463, +0, +-16771376, +31942756, +0, +-3625011, +0, +-11540529, +45048673, +0, +-21256423, +0, +-7015034, +57646140, +0, +-38203817, +0, +-2665107, +16811358, +0, +16739835, +0, +-16773977, +49676415, +0, +-19243342, +0, +-13655857, +82339984, +0, +-55005915, +0, +-10556853, +118287496, +0, +-94363999, +0, +-7146281, +16840799, +0, +16711837, +0, +-16775419, +80691383, +0, +-48942961, +0, +-14971206, +149858505, +0, +-120064524, +0, +-13016765, +233520652, +0, +-206090695, +0, +-10652741, +16892981, +0, +16660455, +0, +-16776220, +136000868, +0, +-103472696, +0, +-15750956, +271801469, +0, +-240442250, +0, +-14582003, +446309601, +0, +-416452524, +0, +-13079862, diff --git a/media/libeffects/AudioShelvingFilter.cpp b/media/libeffects/AudioShelvingFilter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d8abbd2c5e61dddb6a07ccd048eac3f0ae6c1721 --- /dev/null +++ b/media/libeffects/AudioShelvingFilter.cpp @@ -0,0 +1,109 @@ +/* /android/src/frameworks/base/libs/audioflinger/AudioShelvingFilter.cpp +** +** Copyright 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 "AudioShelvingFilter.h" +#include "AudioCommon.h" +#include "EffectsMath.h" + +#include +#include + +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) + +namespace android { +// Format of the coefficient tables: +// kCoefTable[freq][gain][coef] +// freq - cutoff frequency, in octaves below Nyquist,from -10 to -6 in low +// shelf, -2 to 0 in high shelf. +// gain - gain, in millibel, starting at -9600, jumps of 1024, to 4736 millibel. +// coef - 0: b0 +// 1: b1 +// 2: b2 +// 3: -a1 +// 4: -a2 +static const size_t kHiInDims[2] = {3, 15}; +static const audio_coef_t kHiCoefTable[3*15*5] = { +#include "AudioHighShelfFilterCoef.inl" +}; +static const size_t kLoInDims[2] = {5, 15}; +static const audio_coef_t kLoCoefTable[5*15*5] = { +#include "AudioLowShelfFilterCoef.inl" +}; + +AudioCoefInterpolator AudioShelvingFilter::mHiCoefInterp(2, kHiInDims, 5, (const audio_coef_t*) kHiCoefTable); +AudioCoefInterpolator AudioShelvingFilter::mLoCoefInterp(2, kLoInDims, 5, (const audio_coef_t*) kLoCoefTable); + +AudioShelvingFilter::AudioShelvingFilter(ShelfType type, int nChannels, + int sampleRate) + : mBiquad(nChannels, sampleRate) + , mType(type) { + configure(nChannels, sampleRate); +} + +void AudioShelvingFilter::configure(int nChannels, int sampleRate) { + mNiquistFreq = sampleRate * 500; + mFrequencyFactor = ((1ull) << 42) / mNiquistFreq; + mBiquad.configure(nChannels, sampleRate); + setFrequency(mNominalFrequency); + commit(true); +} + +void AudioShelvingFilter::reset() { + setGain(0); + setFrequency(mType == kLowShelf ? 0 : mNiquistFreq); + commit(true); +} + +void AudioShelvingFilter::setFrequency(uint32_t millihertz) { + mNominalFrequency = millihertz; + if (UNLIKELY(millihertz > mNiquistFreq / 2)) { + millihertz = mNiquistFreq / 2; + } + uint32_t normFreq = static_cast( + (static_cast(millihertz) * mFrequencyFactor) >> 10); + uint32_t log2minFreq = (mType == kLowShelf ? (32-10) : (32-2)); + if (LIKELY(normFreq > (1U << log2minFreq))) { + mFrequency = (Effects_log2(normFreq) - (log2minFreq << 15)) << (FREQ_PRECISION_BITS - 15); + } else { + mFrequency = 0; + } +} + +void AudioShelvingFilter::setGain(int32_t millibel) { + mGain = millibel + 9600; +} + +void AudioShelvingFilter::commit(bool immediate) { + audio_coef_t coefs[5]; + int intCoord[2] = { + mFrequency >> FREQ_PRECISION_BITS, + mGain >> GAIN_PRECISION_BITS + }; + uint32_t fracCoord[2] = { + mFrequency << (32 - FREQ_PRECISION_BITS), + static_cast(mGain) << (32 - GAIN_PRECISION_BITS) + }; + if (mType == kHighShelf) { + mHiCoefInterp.getCoef(intCoord, fracCoord, coefs); + } else { + mLoCoefInterp.getCoef(intCoord, fracCoord, coefs); + } + mBiquad.setCoefs(coefs, immediate); +} + +} diff --git a/media/libeffects/AudioShelvingFilter.h b/media/libeffects/AudioShelvingFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..f72d7935404b2ad662037e0d1389ebfc682ffe01 --- /dev/null +++ b/media/libeffects/AudioShelvingFilter.h @@ -0,0 +1,146 @@ +/* /android/src/frameworks/base/libs/audioflinger/AudioShelvingFilter.h +** +** Copyright 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 AUDIO_SHELVING_FILTER_H +#define AUDIO_SHELVING_FILTER_H + +#include "AudioBiquadFilter.h" +#include "AudioCoefInterpolator.h" + +namespace android { + +// A shelving audio filter, with unity skirt gain, and controllable cutoff +// frequency and gain. +// This filter is able to suppress introduce discontinuities and other artifacts +// in the output, even when changing parameters abruptly. +// Parameters can be set to any value - this class will make sure to clip them +// when they are out of supported range. +// +// Implementation notes: +// This class uses an underlying biquad filter whose parameters are determined +// using a linear interpolation from a coefficient table, using a +// AudioCoefInterpolator. +// All is left for this class to do is mapping between high-level parameters to +// fractional indices into the coefficient table. +class AudioShelvingFilter { +public: + // Shelf type + enum ShelfType { + kLowShelf, + kHighShelf + }; + + // Constructor. Resets the filter (see reset()). + // type Type of the filter (high shelf or low shelf). + // nChannels Number of input/output channels (interlaced). + // sampleRate The input/output sample rate, in Hz. + AudioShelvingFilter(ShelfType type, int nChannels, int sampleRate); + + // Reconfiguration of the filter. Changes input/output format, but does not + // alter current parameter values. Clears delay lines. + // nChannels Number of input/output channels (interlaced). + // sampleRate The input/output sample rate, in Hz. + void configure(int nChannels, int sampleRate); + + // Resets the filter parameters to the following values: + // frequency: 0 + // gain: 0 + // It also disables the filter. Does not clear the delay lines. + void reset(); + + // Clears delay lines. Does not alter parameter values. + void clear() { mBiquad.clear(); } + + // Sets gain value. Actual change will only take place upon commit(). + // This value will be remembered even if the filter is in disabled() state. + // millibel Gain value in millibel (1/100 of decibel). + void setGain(int32_t millibel); + + // Gets the gain, in millibel, as set. + int32_t getGain() const { return mGain - 9600; } + + // Sets cutoff frequency value. Actual change will only take place upon + // commit(). + // This value will be remembered even if the filter is in disabled() state. + // millihertz Frequency value in mHz. + void setFrequency(uint32_t millihertz); + + // Gets the frequency, in mHz, as set. + uint32_t getFrequency() const { return mNominalFrequency; } + + // Applies all parameter changes done to this point in time. + // If the filter is disabled, the new parameters will take place when it is + // enabled again. Does not introduce artifacts, unless immediate is set. + // immediate Whether to apply change abruptly (ignored if filter is + // disabled). + void commit(bool immediate = false); + + // Process a buffer of input data. The input and output should contain + // frameCount * nChannels interlaced samples. Processing can be done + // in-place, by passing the same buffer as both arguments. + // in Input buffer. + // out Output buffer. + // frameCount Number of frames to produce. + void process(const audio_sample_t in[], audio_sample_t out[], + int frameCount) { mBiquad.process(in, out, frameCount); } + + // Enables the filter, so it would start processing input. Does not + // introduce artifacts, unless immediate is set. + // immediate Whether to apply change abruptly. + void enable(bool immediate = false) { mBiquad.enable(immediate); } + + // Disabled (bypasses) the filter. Does not introduce artifacts, unless + // immediate is set. + // immediate Whether to apply change abruptly. + void disable(bool immediate = false) { mBiquad.disable(immediate); } + +private: + // Precision for the mFrequency member. + static const int FREQ_PRECISION_BITS = 26; + // Precision for the mGain member. + static const int GAIN_PRECISION_BITS = 10; + + // Shelf type. + ShelfType mType; + // Nyquist, in mHz. + uint32_t mNiquistFreq; + // Fractional index into the gain dimension of the coef table in + // GAIN_PRECISION_BITS precision. + int32_t mGain; + // Fractional index into the frequency dimension of the coef table in + // FREQ_PRECISION_BITS precision. + uint32_t mFrequency; + // Nominal value of frequency, as set. + uint32_t mNominalFrequency; + // 1/Nyquist[mHz], in 42-bit precision (very small). + // Used for scaling the frequency. + uint32_t mFrequencyFactor; + + // A biquad filter, used for the actual processing. + AudioBiquadFilter mBiquad; + // A coefficient interpolator, used for mapping the high level parameters to + // the low-level biquad coefficients. This one is used for the high shelf. + static AudioCoefInterpolator mHiCoefInterp; + // A coefficient interpolator, used for mapping the high level parameters to + // the low-level biquad coefficients. This one is used for the low shelf. + static AudioCoefInterpolator mLoCoefInterp; +}; + +} + + +#endif // AUDIO_SHELVING_FILTER_H diff --git a/media/libeffects/EffectEqualizer.cpp b/media/libeffects/EffectEqualizer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c08f4f53571c913dfc66b75b9a6596f0583ca46f --- /dev/null +++ b/media/libeffects/EffectEqualizer.cpp @@ -0,0 +1,606 @@ +/* + * 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. + */ + +#define LOG_TAG "Equalizer" +#define ARRAY_SIZE(array) (sizeof array / sizeof array[0]) +//#define LOG_NDEBUG 0 +#include +#include +#include +#include +#include +#include "AudioEqualizer.h" +#include "AudioBiquadFilter.h" +#include "AudioFormatAdapter.h" +#include + +// effect_interface_t interface implementation for equalizer effect +extern "C" const struct effect_interface_s gEqualizerInterface; + +namespace android { +namespace { + +// Google Graphic Equalizer UUID: e25aa840-543b-11df-98a5-0002a5d5c51b +const effect_descriptor_t gEqualizerDescriptor = { + {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type + {0xe25aa840, 0x543b, 0x11df, 0x98a5, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid + EFFECT_API_VERSION, + (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST), + "Graphic Equalizer", + "Google Inc.", +}; +static int gEffectIndex; + +/////////////////// BEGIN EQ PRESETS /////////////////////////////////////////// +const int kNumBands = 5; +const uint32_t gFreqs[kNumBands] = { 50000, 125000, 900000, 3200000, 6300000 }; +const uint32_t gBandwidths[kNumBands] = { 0, 3600, 3600, 2400, 0 }; + +const AudioEqualizer::BandConfig gBandsClassic[kNumBands] = { + { 300, gFreqs[0], gBandwidths[0] }, + { 400, gFreqs[1], gBandwidths[1] }, + { 0, gFreqs[2], gBandwidths[2] }, + { 200, gFreqs[3], gBandwidths[3] }, + { -300, gFreqs[4], gBandwidths[4] } +}; + +const AudioEqualizer::BandConfig gBandsJazz[kNumBands] = { + { -600, gFreqs[0], gBandwidths[0] }, + { 200, gFreqs[1], gBandwidths[1] }, + { 400, gFreqs[2], gBandwidths[2] }, + { -400, gFreqs[3], gBandwidths[3] }, + { -600, gFreqs[4], gBandwidths[4] } +}; + +const AudioEqualizer::BandConfig gBandsPop[kNumBands] = { + { 400, gFreqs[0], gBandwidths[0] }, + { -400, gFreqs[1], gBandwidths[1] }, + { 300, gFreqs[2], gBandwidths[2] }, + { -400, gFreqs[3], gBandwidths[3] }, + { 600, gFreqs[4], gBandwidths[4] } +}; + +const AudioEqualizer::BandConfig gBandsRock[kNumBands] = { + { 700, gFreqs[0], gBandwidths[0] }, + { 400, gFreqs[1], gBandwidths[1] }, + { -400, gFreqs[2], gBandwidths[2] }, + { 400, gFreqs[3], gBandwidths[3] }, + { 200, gFreqs[4], gBandwidths[4] } +}; + +const AudioEqualizer::PresetConfig gEqualizerPresets[] = { + { "Classic", gBandsClassic }, + { "Jazz", gBandsJazz }, + { "Pop", gBandsPop }, + { "Rock", gBandsRock } +}; + +/////////////////// END EQ PRESETS ///////////////////////////////////////////// + +static const size_t kBufferSize = 32; + +typedef AudioFormatAdapter FormatAdapter; + +struct EqualizerContext { + const struct effect_interface_s *itfe; + effect_config_t config; + FormatAdapter adapter; + AudioEqualizer * pEqualizer; +}; + + +//--- local function prototypes + +int Equalizer_init(EqualizerContext *pContext); +int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig); +int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue); +int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue); + + +// +//--- Effect Library Interface Implementation +// + +extern "C" int EffectQueryNumberEffects(int *pNumEffects) { + *pNumEffects = 1; + gEffectIndex = 0; + return 0; +} /* end EffectQueryNumberEffects */ + +extern "C" int EffectQueryNext(effect_descriptor_t *pDescriptor) { + if (pDescriptor == NULL) { + return -EINVAL; + } + if (gEffectIndex++ > 0) { + return -ENOENT; + } + memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t)); + return 0; +} /* end EffectQueryNext */ + +extern "C" int EffectCreate(effect_uuid_t *uuid, + effect_interface_t *pInterface) { + int ret; + int i; + + LOGV("EffectLibCreateEffect start"); + + if (pInterface == NULL || uuid == NULL) { + return -EINVAL; + } + + if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) { + return -EINVAL; + } + + EqualizerContext *pContext = new EqualizerContext; + + pContext->itfe = &gEqualizerInterface; + pContext->pEqualizer = NULL; + + ret = Equalizer_init(pContext); + if (ret < 0) { + LOGW("EffectLibCreateEffect() init failed"); + delete pContext; + return ret; + } + + *pInterface = (effect_interface_t)pContext; + + LOGV("EffectLibCreateEffect %p", pContext); + + return 0; + +} /* end EffectCreate */ + +extern "C" int EffectRelease(effect_interface_t interface) { + EqualizerContext * pContext = (EqualizerContext *)interface; + + LOGV("EffectLibReleaseEffect %p", interface); + if (pContext == NULL) { + return -EINVAL; + } + + pContext->pEqualizer->free(); + delete pContext; + + return 0; +} /* end EffectRelease */ + + +// +//--- local functions +// + +#define CHECK_ARG(cond) { \ + if (!(cond)) { \ + LOGV("Invalid argument: "#cond); \ + return -EINVAL; \ + } \ +} + +//---------------------------------------------------------------------------- +// Equalizer_configure() +//---------------------------------------------------------------------------- +// Purpose: Set input and output audio configuration. +// +// Inputs: +// pContext: effect engine context +// pConfig: pointer to effect_config_t structure holding input and output +// configuration parameters +// +// Outputs: +// +//---------------------------------------------------------------------------- + +int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig) +{ + LOGV("Equalizer_configure start"); + + CHECK_ARG(pContext != NULL); + CHECK_ARG(pConfig != NULL); + + CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate); + CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels); + CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format); + CHECK_ARG((pConfig->inputCfg.channels == CHANNEL_MONO) || (pConfig->inputCfg.channels == CHANNEL_STEREO)); + CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE + || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE); + CHECK_ARG(pConfig->inputCfg.format == PCM_FORMAT_S7_24 + || pConfig->inputCfg.format == PCM_FORMAT_S15); + + int channelCount; + if (pConfig->inputCfg.channels == CHANNEL_MONO) { + channelCount = 1; + } else { + channelCount = 2; + } + CHECK_ARG(channelCount <= AudioBiquadFilter::MAX_CHANNELS); + + pContext->pEqualizer->configure(channelCount, + pConfig->inputCfg.samplingRate); + + pContext->adapter.configure(*pContext->pEqualizer, channelCount, + pConfig->inputCfg.format, + pConfig->outputCfg.accessMode); + + return 0; +} // end Equalizer_configure + + +//---------------------------------------------------------------------------- +// Equalizer_init() +//---------------------------------------------------------------------------- +// Purpose: Initialize engine with default configuration and creates +// AudioEqualizer instance. +// +// Inputs: +// pContext: effect engine context +// +// Outputs: +// +//---------------------------------------------------------------------------- + +int Equalizer_init(EqualizerContext *pContext) +{ + int status; + + LOGV("Equalizer_init start"); + + CHECK_ARG(pContext != NULL); + + if (pContext->pEqualizer != NULL) { + pContext->pEqualizer->free(); + } + + pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; + pContext->config.inputCfg.channels = CHANNEL_STEREO; + pContext->config.inputCfg.format = PCM_FORMAT_S15; + pContext->config.inputCfg.samplingRate = 44100; + pContext->config.inputCfg.bufferProvider.getBuffer = NULL; + pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL; + pContext->config.inputCfg.bufferProvider.cookie = NULL; + pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL; + pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; + pContext->config.outputCfg.channels = CHANNEL_STEREO; + pContext->config.outputCfg.format = PCM_FORMAT_S15; + pContext->config.outputCfg.samplingRate = 44100; + pContext->config.outputCfg.bufferProvider.getBuffer = NULL; + pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL; + pContext->config.outputCfg.bufferProvider.cookie = NULL; + pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL; + + pContext->pEqualizer = AudioEqualizer::CreateInstance( + NULL, + kNumBands, + AudioBiquadFilter::MAX_CHANNELS, + 44100, + gEqualizerPresets, + ARRAY_SIZE(gEqualizerPresets)); + + for (int i = 0; i < kNumBands; ++i) { + pContext->pEqualizer->setFrequency(i, gFreqs[i]); + pContext->pEqualizer->setBandwidth(i, gBandwidths[i]); + } + + pContext->pEqualizer->enable(true); + + Equalizer_configure(pContext, &pContext->config); + + return 0; +} // end Equalizer_init + + +//---------------------------------------------------------------------------- +// Equalizer_getParameter() +//---------------------------------------------------------------------------- +// Purpose: +// Get a Equalizer parameter +// +// Inputs: +// pEqualizer - handle to instance data +// pParam - pointer to parameter +// pValue - pointer to variable to hold retrieved value +// pValueSize - pointer to value size: maximum size as input +// +// Outputs: +// *pValue updated with parameter value +// *pValueSize updated with actual value size +// +// +// Side Effects: +// +//---------------------------------------------------------------------------- + +int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue) +{ + int status = 0; + int32_t param = *pParam++; + int32_t param2; + char *name; + + switch (param) { + case EQ_PARAM_NUM_BANDS: + case EQ_PARAM_CUR_PRESET: + case EQ_PARAM_GET_NUM_OF_PRESETS: + if (*pValueSize < sizeof(int16_t)) { + return -EINVAL; + } + *pValueSize = sizeof(int16_t); + break; + + case EQ_PARAM_LEVEL_RANGE: + case EQ_PARAM_BAND_FREQ_RANGE: + if (*pValueSize < 2 * sizeof(int32_t)) { + return -EINVAL; + } + *pValueSize = 2 * sizeof(int32_t); + break; + case EQ_PARAM_BAND_LEVEL: + case EQ_PARAM_GET_BAND: + case EQ_PARAM_CENTER_FREQ: + if (*pValueSize < sizeof(int32_t)) { + return -EINVAL; + } + *pValueSize = sizeof(int32_t); + break; + + case EQ_PARAM_GET_PRESET_NAME: + break; + + default: + return -EINVAL; + } + + switch (param) { + case EQ_PARAM_NUM_BANDS: + *(int16_t *)pValue = kNumBands; + LOGV("Equalizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue); + break; + + case EQ_PARAM_LEVEL_RANGE: + *(int32_t *)pValue = -9600; + *((int32_t *)pValue + 1) = 4800; + LOGV("Equalizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d", *(int32_t *)pValue, *((int32_t *)pValue + 1)); + break; + + case EQ_PARAM_BAND_LEVEL: + param2 = *pParam; + if (param2 >= kNumBands) { + status = -EINVAL; + break; + } + *(int32_t *)pValue = pEqualizer->getGain(param2); + LOGV("Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", param2, *(int32_t *)pValue); + break; + + case EQ_PARAM_CENTER_FREQ: + param2 = *pParam; + if (param2 >= kNumBands) { + status = -EINVAL; + break; + } + *(int32_t *)pValue = pEqualizer->getFrequency(param2); + LOGV("Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d", param2, *(int32_t *)pValue); + break; + + case EQ_PARAM_BAND_FREQ_RANGE: + param2 = *pParam; + if (param2 >= kNumBands) { + status = -EINVAL; + break; + } + pEqualizer->getBandRange(param2, *(uint32_t *)pValue, *((uint32_t *)pValue + 1)); + LOGV("Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d", param2, *(int32_t *)pValue, *((int32_t *)pValue + 1)); + break; + + case EQ_PARAM_GET_BAND: + param2 = *pParam; + *(int32_t *)pValue = pEqualizer->getMostRelevantBand(param2); + LOGV("Equalizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d", param2, *(int32_t *)pValue); + break; + + case EQ_PARAM_CUR_PRESET: + *(int16_t *)pValue = pEqualizer->getPreset(); + LOGV("Equalizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue); + break; + + case EQ_PARAM_GET_NUM_OF_PRESETS: + *(int16_t *)pValue = pEqualizer->getNumPresets(); + LOGV("Equalizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue); + break; + + case EQ_PARAM_GET_PRESET_NAME: + param2 = *pParam; + if (param2 >= pEqualizer->getNumPresets()) { + status = -EINVAL; + break; + } + name = (char *)pValue; + strncpy(name, pEqualizer->getPresetName(param2), *pValueSize - 1); + name[*pValueSize - 1] = 0; + *pValueSize = strlen(name) + 1; + LOGV("Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d", param2, gEqualizerPresets[param2].name, *pValueSize); + break; + + default: + LOGV("Equalizer_getParameter() invalid param %d", param); + status = -EINVAL; + break; + } + + return status; +} // end Equalizer_getParameter + + +//---------------------------------------------------------------------------- +// Equalizer_setParameter() +//---------------------------------------------------------------------------- +// Purpose: +// Set a Equalizer parameter +// +// Inputs: +// pEqualizer - handle to instance data +// pParam - pointer to parameter +// pValue - pointer to value +// +// Outputs: +// +// +// Side Effects: +// +//---------------------------------------------------------------------------- + +int Equalizer_setParameter (AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue) +{ + int status = 0; + int32_t preset; + int32_t band; + int32_t level; + int32_t param = *pParam++; + + + switch (param) { + case EQ_PARAM_CUR_PRESET: + preset = *(int16_t *)pValue; + + LOGV("setParameter() EQ_PARAM_CUR_PRESET %d", preset); + if (preset >= pEqualizer->getNumPresets()) { + status = -EINVAL; + break; + } + pEqualizer->setPreset(preset); + pEqualizer->commit(true); + break; + case EQ_PARAM_BAND_LEVEL: + band = *pParam; + level = *(int32_t *)pValue; + LOGV("setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level); + if (band >= kNumBands) { + status = -EINVAL; + break; + } + pEqualizer->setGain(band, level); + pEqualizer->commit(true); + break; + default: + LOGV("setParameter() invalid param %d", param); + break; + } + + return status; +} // end Equalizer_setParameter + +} // namespace +} // namespace + + +// +//--- Effect Control Interface Implementation +// + +extern "C" int Equalizer_process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) +{ + android::EqualizerContext * pContext = (android::EqualizerContext *) self; + + if (pContext == NULL) { + return -EINVAL; + } + if (inBuffer == NULL || inBuffer->raw == NULL || + outBuffer == NULL || outBuffer->raw == NULL || + inBuffer->frameCount != outBuffer->frameCount) { + return -EINVAL; + } + + pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount); + return 0; +} // end Equalizer_process + +extern "C" int Equalizer_command(effect_interface_t self, int cmdCode, int cmdSize, + void *pCmdData, int *replySize, void *pReplyData) { + + android::EqualizerContext * pContext = (android::EqualizerContext *) self; + int retsize; + + if (pContext == NULL) { + return -EINVAL; + } + + android::AudioEqualizer * pEqualizer = pContext->pEqualizer; + + LOGV("Equalizer_command command %d cmdSize %d",cmdCode, cmdSize); + + switch (cmdCode) { + case EFFECT_CMD_INIT: + if (pReplyData == NULL || *replySize != sizeof(int)) { + return -EINVAL; + } + *(int *) pReplyData = Equalizer_init(pContext); + break; + case EFFECT_CMD_CONFIGURE: + if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) + || pReplyData == NULL || *replySize != sizeof(int)) { + return -EINVAL; + } + *(int *) pReplyData = Equalizer_configure(pContext, + (effect_config_t *) pCmdData); + break; + case EFFECT_CMD_RESET: + Equalizer_configure(pContext, &pContext->config); + break; + case EFFECT_CMD_GET_PARAM: { + if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || + pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) { + return -EINVAL; + } + effect_param_t *p = (effect_param_t *)pCmdData; + memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize); + p = (effect_param_t *)pReplyData; + int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); + p->status = android::Equalizer_getParameter(pEqualizer, (int32_t *)p->data, &p->vsize, + p->data + voffset); + *replySize = sizeof(effect_param_t) + voffset + p->vsize; + LOGV("Equalizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, *pReplyData %08x %08x", + *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize, + *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset), + *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset + sizeof(int32_t))); + + } break; + case EFFECT_CMD_SET_PARAM: { + LOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData); + if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || + pReplyData == NULL || *replySize != sizeof(int32_t)) { + return -EINVAL; + } + effect_param_t *p = (effect_param_t *) pCmdData; + *(int *)pReplyData = android::Equalizer_setParameter(pEqualizer, (int32_t *)p->data, + p->data + p->psize); + } break; + default: + LOGW("Equalizer_command invalid command %d",cmdCode); + return -EINVAL; + } + + return 0; +} + +// effect_interface_t interface implementation for equalizer effect +const struct effect_interface_s gEqualizerInterface = { + Equalizer_process, + Equalizer_command +}; + + diff --git a/media/libeffects/EffectReverb.c b/media/libeffects/EffectReverb.c new file mode 100644 index 0000000000000000000000000000000000000000..3181504b70d6e63d72825f8f53494e80bd1e307d --- /dev/null +++ b/media/libeffects/EffectReverb.c @@ -0,0 +1,2034 @@ +/* + * Copyright (C) 2008 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. + */ + +#define LOG_TAG "EffectReverb" +// +#define LOG_NDEBUG 0 +#include + +#include +#include "EffectReverb.h" +#include "EffectsMath.h" + +static int gEffectIndex; + +// effect_interface_t interface implementation for reverb effect +const struct effect_interface_s gReverbInterface = { + Reverb_Process, + Reverb_Command +}; + +// Google auxiliary environmental reverb UUID: 1f0ae2e0-4ef7-11df-bc09-0002a5d5c51b +static const effect_descriptor_t gAuxEnvReverbDescriptor = { + {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}}, + {0x1f0ae2e0, 0x4ef7, 0x11df, 0xbc09, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, + EFFECT_API_VERSION, + EFFECT_FLAG_TYPE_AUXILIARY, + "Aux Environmental Reverb", + "Google Inc." +}; + +// Google insert environmental reverb UUID: aa476040-6342-11df-91a4-0002a5d5c51b +static const effect_descriptor_t gInsertEnvReverbDescriptor = { + {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}}, + {0xaa476040, 0x6342, 0x11df, 0x91a4, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, + EFFECT_API_VERSION, + EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST, + "Insert Environmental reverb", + "Google Inc." +}; + +// Google auxiliary preset reverb UUID: 63909320-53a6-11df-bdbd-0002a5d5c51b +static const effect_descriptor_t gAuxPresetReverbDescriptor = { + {0x47382d60, 0xddd8, 0x4763, 0x11db, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, + {0x63909320, 0x53a6, 0x11df, 0xbdbd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, + EFFECT_API_VERSION, + EFFECT_FLAG_TYPE_AUXILIARY, + "Aux Preset Reverb", + "Google Inc." +}; + +// Google insert preset reverb UUID: d93dc6a0-6342-11df-b128-0002a5d5c51b +static const effect_descriptor_t gInsertPresetReverbDescriptor = { + {0x47382d60, 0xddd8, 0x4763, 0x11db, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, + {0xd93dc6a0, 0x6342, 0x11df, 0xb128, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, + EFFECT_API_VERSION, + EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST, + "Insert Preset Reverb", + "Google Inc." +}; + +// gDescriptors contains pointers to all defined effect descriptor in this library +static const effect_descriptor_t * const gDescriptors[] = { + &gAuxEnvReverbDescriptor, + &gInsertEnvReverbDescriptor, + &gAuxPresetReverbDescriptor, + &gInsertPresetReverbDescriptor, + NULL +}; + +/*---------------------------------------------------------------------------- + * Effect API implementation + *--------------------------------------------------------------------------*/ + +/*--- Effect Library Interface Implementation ---*/ + +int EffectQueryNumberEffects(int *pNumEffects) { + *pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *) + - 1; + gEffectIndex = 0; + return 0; +} + +int EffectQueryNext(effect_descriptor_t *pDescriptor) { + if (pDescriptor == NULL) { + return -EINVAL; + } + if (gDescriptors[gEffectIndex] == NULL) { + return -ENOENT; + } + memcpy(pDescriptor, gDescriptors[gEffectIndex++], + sizeof(effect_descriptor_t)); + return 0; +} + +int EffectCreate(effect_uuid_t *uuid, + effect_interface_t *pInterface) { + int ret; + int i; + reverb_module_t *module; + const effect_descriptor_t *desc; + int aux = 0; + int preset = 0; + + LOGV("EffectLibCreateEffect start"); + + if (pInterface == NULL || uuid == NULL) { + return -EINVAL; + } + + for (i = 0; gDescriptors[i] != NULL; i++) { + desc = gDescriptors[i]; + if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t)) + == 0) { + break; + } + } + + if (gDescriptors[i] == NULL) { + return -ENOENT; + } + + module = malloc(sizeof(reverb_module_t)); + + module->itfe = &gReverbInterface; + + if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) { + preset = 1; + } + if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) { + aux = 1; + } + ret = Reverb_Init(module, aux, preset); + if (ret < 0) { + LOGW("EffectLibCreateEffect() init failed"); + free(module); + return ret; + } + + *pInterface = (effect_interface_t) module; + + LOGV("EffectLibCreateEffect %p", module); + + return 0; +} + +int EffectRelease(effect_interface_t interface) { + reverb_module_t *pRvbModule = (reverb_module_t *)interface; + + LOGV("EffectLibReleaseEffect %p", interface); + if (interface == NULL) { + return -EINVAL; + } + + free(pRvbModule); + return 0; +} + + +/*--- Effect Control Interface Implementation ---*/ + +static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) { + reverb_object_t *pReverb; + int16_t *pSrc, *pDst; + reverb_module_t *pRvbModule = (reverb_module_t *)self; + + if (pRvbModule == NULL) { + return -EINVAL; + } + + if (inBuffer == NULL || inBuffer->raw == NULL || + outBuffer == NULL || outBuffer->raw == NULL || + inBuffer->frameCount != outBuffer->frameCount) { + return -EINVAL; + } + + pReverb = (reverb_object_t*) &pRvbModule->context; + + //if bypassed or the preset forces the signal to be completely dry + if (pReverb->m_bBypass) { + if (inBuffer->raw != outBuffer->raw && !pReverb->m_Aux) { + memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount * NUM_OUTPUT_CHANNELS * sizeof(int16_t)); + } + return 0; + } + + if (pReverb->m_nNextRoom != pReverb->m_nCurrentRoom) { + ReverbUpdateRoom(pReverb, true); + } + + pSrc = inBuffer->s16; + pDst = outBuffer->s16; + size_t numSamples = outBuffer->frameCount; + while (numSamples) { + uint32_t processedSamples; + if (numSamples > (uint32_t) pReverb->m_nUpdatePeriodInSamples) { + processedSamples = (uint32_t) pReverb->m_nUpdatePeriodInSamples; + } else { + processedSamples = numSamples; + } + + /* increment update counter */ + pReverb->m_nUpdateCounter += (int16_t) processedSamples; + /* check if update counter needs to be reset */ + if (pReverb->m_nUpdateCounter >= pReverb->m_nUpdatePeriodInSamples) { + /* update interval has elapsed, so reset counter */ + pReverb->m_nUpdateCounter -= pReverb->m_nUpdatePeriodInSamples; + ReverbUpdateXfade(pReverb, pReverb->m_nUpdatePeriodInSamples); + + } /* end if m_nUpdateCounter >= update interval */ + + Reverb(pReverb, processedSamples, pDst, pSrc); + + numSamples -= processedSamples; + if (pReverb->m_Aux) { + pDst += processedSamples; + } else { + pSrc += processedSamples * NUM_OUTPUT_CHANNELS; + } + } + + return 0; +} + +static int Reverb_Command(effect_interface_t self, int cmdCode, int cmdSize, + void *pCmdData, int *replySize, void *pReplyData) { + reverb_module_t *pRvbModule = (reverb_module_t *) self; + reverb_object_t *pReverb; + int retsize; + + if (pRvbModule == NULL) { + return -EINVAL; + } + + pReverb = (reverb_object_t*) &pRvbModule->context; + + LOGV("Reverb_Command command %d cmdSize %d",cmdCode, cmdSize); + + switch (cmdCode) { + case EFFECT_CMD_INIT: + if (pReplyData == NULL || *replySize != sizeof(int)) { + return -EINVAL; + } + *(int *) pReplyData = Reverb_Init(pRvbModule, pReverb->m_Aux, pReverb->m_Preset); + break; + case EFFECT_CMD_CONFIGURE: + if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) + || pReplyData == NULL || *replySize != sizeof(int)) { + return -EINVAL; + } + *(int *) pReplyData = Reverb_Configure(pRvbModule, + (effect_config_t *)pCmdData, false); + break; + case EFFECT_CMD_RESET: + Reverb_Reset(pReverb, false); + break; + case EFFECT_CMD_GET_PARAM: + LOGV("Reverb_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %d, pReplyData: %p",pCmdData, *replySize, pReplyData); + + if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || + pReplyData == NULL || *replySize < (int) sizeof(effect_param_t)) { + return -EINVAL; + } + effect_param_t *rep = (effect_param_t *) pReplyData; + memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t)); + LOGV("Reverb_Command EFFECT_CMD_GET_PARAM param %d, replySize %d",*(int32_t *)rep->data, rep->vsize); + rep->status = Reverb_getParameter(pReverb, *(int32_t *)rep->data, &rep->vsize, + rep->data + sizeof(int32_t)); + *replySize = sizeof(effect_param_t) + sizeof(int32_t) + rep->vsize; + break; + case EFFECT_CMD_SET_PARAM: + LOGV("Reverb_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p", + cmdSize, pCmdData, *replySize, pReplyData); + if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t))) + || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) { + return -EINVAL; + } + effect_param_t *cmd = (effect_param_t *) pCmdData; + *(int *)pReplyData = Reverb_setParameter(pReverb, *(int32_t *)cmd->data, + cmd->vsize, cmd->data + sizeof(int32_t)); + break; + default: + LOGW("Reverb_Command invalid command %d",cmdCode); + return -EINVAL; + } + + return 0; +} + + +/*---------------------------------------------------------------------------- + * Reverb internal functions + *--------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + * Reverb_Init() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize reverb context and apply default parameters + * + * Inputs: + * pRvbModule - pointer to reverb effect module + * aux - indicates if the reverb is used as auxiliary (1) or insert (0) + * preset - indicates if the reverb is used in preset (1) or environmental (0) mode + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- + */ + +int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset) { + int ret; + + LOGV("Reverb_Init module %p, aux: %d, preset: %d", pRvbModule,aux, preset); + + memset(&pRvbModule->context, 0, sizeof(reverb_object_t)); + + pRvbModule->context.m_Aux = (uint16_t)aux; + pRvbModule->context.m_Preset = (uint16_t)preset; + + pRvbModule->config.inputCfg.samplingRate = 44100; + if (aux) { + pRvbModule->config.inputCfg.channels = CHANNEL_MONO; + } else { + pRvbModule->config.inputCfg.channels = CHANNEL_STEREO; + } + pRvbModule->config.inputCfg.format = PCM_FORMAT_S15; + pRvbModule->config.inputCfg.bufferProvider.getBuffer = NULL; + pRvbModule->config.inputCfg.bufferProvider.releaseBuffer = NULL; + pRvbModule->config.inputCfg.bufferProvider.cookie = NULL; + pRvbModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; + pRvbModule->config.inputCfg.mask = EFFECT_CONFIG_ALL; + pRvbModule->config.outputCfg.samplingRate = 44100; + pRvbModule->config.outputCfg.channels = CHANNEL_STEREO; + pRvbModule->config.outputCfg.format = PCM_FORMAT_S15; + pRvbModule->config.outputCfg.bufferProvider.getBuffer = NULL; + pRvbModule->config.outputCfg.bufferProvider.releaseBuffer = NULL; + pRvbModule->config.outputCfg.bufferProvider.cookie = NULL; + pRvbModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; + pRvbModule->config.outputCfg.mask = EFFECT_CONFIG_ALL; + + ret = Reverb_Configure(pRvbModule, &pRvbModule->config, true); + if (ret < 0) { + LOGV("Reverb_Init error %d on module %p", ret, pRvbModule); + } + + return ret; +} + +/*---------------------------------------------------------------------------- + * Reverb_Init() + *---------------------------------------------------------------------------- + * Purpose: + * Set input and output audio configuration. + * + * Inputs: + * pRvbModule - pointer to reverb effect module + * pConfig - pointer to effect_config_t structure containing input + * and output audio parameters configuration + * init - true if called from init function + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- + */ + +int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig, + bool init) { + reverb_object_t *pReverb = &pRvbModule->context; + int bufferSizeInSamples; + int updatePeriodInSamples; + int xfadePeriodInSamples; + + // Check configuration compatibility with build options + if (pConfig->inputCfg.samplingRate + != pConfig->outputCfg.samplingRate + || pConfig->outputCfg.channels != OUTPUT_CHANNELS + || pConfig->inputCfg.format != PCM_FORMAT_S15 + || pConfig->outputCfg.format != PCM_FORMAT_S15) { + LOGV("Reverb_Configure invalid config"); + return -EINVAL; + } + if ((pReverb->m_Aux && (pConfig->inputCfg.channels != CHANNEL_MONO)) || + (!pReverb->m_Aux && (pConfig->inputCfg.channels != CHANNEL_STEREO))) { + LOGV("Reverb_Configure invalid config"); + return -EINVAL; + } + + memcpy(&pRvbModule->config, pConfig, sizeof(effect_config_t)); + + pReverb->m_nSamplingRate = pRvbModule->config.outputCfg.samplingRate; + + switch (pReverb->m_nSamplingRate) { + case 8000: + pReverb->m_nUpdatePeriodInBits = 5; + bufferSizeInSamples = 4096; + pReverb->m_nCosWT_5KHz = -23170; + break; + case 16000: + pReverb->m_nUpdatePeriodInBits = 6; + bufferSizeInSamples = 8192; + pReverb->m_nCosWT_5KHz = -12540; + break; + case 22050: + pReverb->m_nUpdatePeriodInBits = 7; + bufferSizeInSamples = 8192; + pReverb->m_nCosWT_5KHz = 4768; + break; + case 32000: + pReverb->m_nUpdatePeriodInBits = 7; + bufferSizeInSamples = 16384; + pReverb->m_nCosWT_5KHz = 18205; + break; + case 44100: + pReverb->m_nUpdatePeriodInBits = 8; + bufferSizeInSamples = 16384; + pReverb->m_nCosWT_5KHz = 24799; + break; + case 48000: + pReverb->m_nUpdatePeriodInBits = 8; + bufferSizeInSamples = 16384; + pReverb->m_nCosWT_5KHz = 25997; + break; + default: + LOGV("Reverb_Configure invalid sampling rate %d", pReverb->m_nSamplingRate); + return -EINVAL; + } + + // Define a mask for circular addressing, so that array index + // can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1) + // The buffer size MUST be a power of two + pReverb->m_nBufferMask = (int32_t) (bufferSizeInSamples - 1); + /* reverb parameters are updated every 2^(pReverb->m_nUpdatePeriodInBits) samples */ + updatePeriodInSamples = (int32_t) (0x1L << pReverb->m_nUpdatePeriodInBits); + /* + calculate the update counter by bitwise ANDING with this value to + generate a 2^n modulo value + */ + pReverb->m_nUpdatePeriodInSamples = (int32_t) updatePeriodInSamples; + + xfadePeriodInSamples = (int32_t) (REVERB_XFADE_PERIOD_IN_SECONDS + * (double) pReverb->m_nSamplingRate); + + // set xfade parameters + pReverb->m_nPhaseIncrement + = (int16_t) (65536 / ((int16_t) xfadePeriodInSamples + / (int16_t) updatePeriodInSamples)); + + if (init) { + ReverbReadInPresets(pReverb); + + // for debugging purposes, allow noise generator + pReverb->m_bUseNoise = true; + + // for debugging purposes, allow bypass + pReverb->m_bBypass = false; + + pReverb->m_nNextRoom = 1; + + pReverb->m_nNoise = (int16_t) 0xABCD; + } + + Reverb_Reset(pReverb, init); + + return 0; +} + +/*---------------------------------------------------------------------------- + * Reverb_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset internal states and clear delay lines. + * + * Inputs: + * pReverb - pointer to reverb context + * init - true if called from init function + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- + */ + +void Reverb_Reset(reverb_object_t *pReverb, bool init) { + int bufferSizeInSamples = (int32_t) (pReverb->m_nBufferMask + 1); + int maxApSamples; + int maxDelaySamples; + int maxEarlySamples; + int ap1In; + int delay0In; + int delay1In; + int32_t i; + uint16_t nOffset; + + maxApSamples = ((int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16); + maxDelaySamples = ((int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate) + >> 16); + maxEarlySamples = ((int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate) + >> 16); + + ap1In = (AP0_IN + maxApSamples + GUARD); + delay0In = (ap1In + maxApSamples + GUARD); + delay1In = (delay0In + maxDelaySamples + GUARD); + // Define the max offsets for the end points of each section + // i.e., we don't expect a given section's taps to go beyond + // the following limits + + pReverb->m_nEarly0in = (delay1In + maxDelaySamples + GUARD); + pReverb->m_nEarly1in = (pReverb->m_nEarly0in + maxEarlySamples + GUARD); + + pReverb->m_sAp0.m_zApIn = AP0_IN; + + pReverb->m_zD0In = delay0In; + + pReverb->m_sAp1.m_zApIn = ap1In; + + pReverb->m_zD1In = delay1In; + + pReverb->m_zOutLpfL = 0; + pReverb->m_zOutLpfR = 0; + + pReverb->m_nRevFbkR = 0; + pReverb->m_nRevFbkL = 0; + + // set base index into circular buffer + pReverb->m_nBaseIndex = 0; + + // clear the reverb delay line + for (i = 0; i < bufferSizeInSamples; i++) { + pReverb->m_nDelayLine[i] = 0; + } + + ReverbUpdateRoom(pReverb, init); + + pReverb->m_nUpdateCounter = 0; + + pReverb->m_nPhase = -32768; + + pReverb->m_nSin = 0; + pReverb->m_nCos = 0; + pReverb->m_nSinIncrement = 0; + pReverb->m_nCosIncrement = 0; + + // set delay tap lengths + nOffset = ReverbCalculateNoise(pReverb); + + pReverb->m_zD1Cross = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion + + nOffset; + + nOffset = ReverbCalculateNoise(pReverb); + + pReverb->m_zD0Cross = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion + - nOffset; + + nOffset = ReverbCalculateNoise(pReverb); + + pReverb->m_zD0Self = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion + - nOffset; + + nOffset = ReverbCalculateNoise(pReverb); + + pReverb->m_zD1Self = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion + + nOffset; +} + +/*---------------------------------------------------------------------------- + * Reverb_getParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Get a Reverb parameter + * + * Inputs: + * pReverb - handle to instance data + * param - parameter + * pValue - pointer to variable to hold retrieved value + * pSize - pointer to value size: maximum size as input + * + * Outputs: + * *pValue updated with parameter value + * *pSize updated with actual value size + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- + */ +int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, + void *pValue) { + int32_t *pValue32; + int16_t *pValue16; + t_reverb_properties *pProperties; + int32_t i; + int32_t temp; + int32_t temp2; + size_t size; + + if (pReverb->m_Preset && param != REVERB_PARAM_PRESET) { + return -EINVAL; + } + if (!pReverb->m_Preset && param == REVERB_PARAM_PRESET) { + return -EINVAL; + } + + switch (param) { + case REVERB_PARAM_ROOM_LEVEL: + case REVERB_PARAM_ROOM_HF_LEVEL: + case REVERB_PARAM_DECAY_HF_RATIO: + case REVERB_PARAM_REFLECTIONS_LEVEL: + case REVERB_PARAM_REVERB_LEVEL: + case REVERB_PARAM_DIFFUSION: + case REVERB_PARAM_DENSITY: + size = sizeof(int16_t); + break; + + case REVERB_PARAM_BYPASS: + case REVERB_PARAM_PRESET: + case REVERB_PARAM_DECAY_TIME: + case REVERB_PARAM_REFLECTIONS_DELAY: + case REVERB_PARAM_REVERB_DELAY: + size = sizeof(int32_t); + break; + + case REVERB_PARAM_PROPERTIES: + size = sizeof(t_reverb_properties); + break; + + default: + return -EINVAL; + } + + if (*pSize < size) { + return -EINVAL; + } + *pSize = size; + pValue32 = (int32_t *) pValue; + pValue16 = (int16_t *) pValue; + pProperties = (t_reverb_properties *) pValue; + + switch (param) { + case REVERB_PARAM_BYPASS: + *(int32_t *) pValue = (int32_t) pReverb->m_bBypass; + break; + case REVERB_PARAM_PRESET: + *(int32_t *) pValue = (int8_t) pReverb->m_nCurrentRoom; + break; + + case REVERB_PARAM_PROPERTIES: + pValue16 = &pProperties->roomLevel; + /* FALL THROUGH */ + + case REVERB_PARAM_ROOM_LEVEL: + // Convert m_nRoomLpfFwd to millibels + temp = (pReverb->m_nRoomLpfFwd << 15) + / (32767 - pReverb->m_nRoomLpfFbk); + *pValue16 = Effects_Linear16ToMillibels(temp); + + LOGV("get REVERB_PARAM_ROOM_LEVEL %d, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", *pValue16, temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk); + + if (param == REVERB_PARAM_ROOM_LEVEL) { + break; + } + pValue16 = &pProperties->roomHFLevel; + /* FALL THROUGH */ + + case REVERB_PARAM_ROOM_HF_LEVEL: + // The ratio between linear gain at 0Hz and at 5000Hz for the room low pass is: + // (1 + a1) / sqrt(a1^2 + 2*C*a1 + 1) where: + // - a1 is minus the LP feedback gain: -pReverb->m_nRoomLpfFbk + // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz + + temp = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFbk); + LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 %d", temp); + temp2 = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nCosWT_5KHz) + << 1; + LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, 2 Cos a1 %d", temp2); + temp = 32767 + temp - temp2; + LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 + 2 Cos a1 + 1 %d", temp); + temp = Effects_Sqrt(temp) * 181; + LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, SQRT(a1^2 + 2 Cos a1 + 1) %d", temp); + temp = ((32767 - pReverb->m_nRoomLpfFbk) << 15) / temp; + + LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk); + + *pValue16 = Effects_Linear16ToMillibels(temp); + + if (param == REVERB_PARAM_ROOM_HF_LEVEL) { + break; + } + pValue32 = &pProperties->decayTime; + /* FALL THROUGH */ + + case REVERB_PARAM_DECAY_TIME: + // Calculate reverb feedback path gain + temp = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk); + temp = Effects_Linear16ToMillibels(temp); + + // Calculate decay time: g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time + temp = (-6000 * pReverb->m_nLateDelay) / temp; + + // Convert samples to ms + *pValue32 = (temp * 1000) / pReverb->m_nSamplingRate; + + LOGV("get REVERB_PARAM_DECAY_TIME, samples %d, ms %d", temp, *pValue32); + + if (param == REVERB_PARAM_DECAY_TIME) { + break; + } + pValue16 = &pProperties->decayHFRatio; + /* FALL THROUGH */ + + case REVERB_PARAM_DECAY_HF_RATIO: + // If r is the decay HF ratio (r = REVERB_PARAM_DECAY_HF_RATIO/1000) we have: + // DT_5000Hz = DT_0Hz * r + // and G_5000Hz = -6000 * d / DT_5000Hz and G_0Hz = -6000 * d / DT_0Hz in millibels so : + // r = G_0Hz/G_5000Hz in millibels + // The linear gain at 5000Hz is b0 / sqrt(a1^2 + 2*C*a1 + 1) where: + // - a1 is minus the LP feedback gain: -pReverb->m_nRvbLpfFbk + // - b0 is the LP forward gain: pReverb->m_nRvbLpfFwd + // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz + if (pReverb->m_nRvbLpfFbk == 0) { + *pValue16 = 1000; + LOGV("get REVERB_PARAM_DECAY_HF_RATIO, pReverb->m_nRvbLpfFbk == 0, ratio %d", *pValue16); + } else { + temp = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFbk); + temp2 = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nCosWT_5KHz) + << 1; + temp = 32767 + temp - temp2; + temp = Effects_Sqrt(temp) * 181; + temp = (pReverb->m_nRvbLpfFwd << 15) / temp; + // The linear gain at 0Hz is b0 / (a1 + 1) + temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767 + - pReverb->m_nRvbLpfFbk); + + temp = Effects_Linear16ToMillibels(temp); + temp2 = Effects_Linear16ToMillibels(temp2); + LOGV("get REVERB_PARAM_DECAY_HF_RATIO, gain 5KHz %d mB, gain DC %d mB", temp, temp2); + + if (temp == 0) + temp = 1; + temp = (int16_t) ((1000 * temp2) / temp); + if (temp > 1000) + temp = 1000; + + *pValue16 = temp; + LOGV("get REVERB_PARAM_DECAY_HF_RATIO, ratio %d", *pValue16); + } + + if (param == REVERB_PARAM_DECAY_HF_RATIO) { + break; + } + pValue16 = &pProperties->reflectionsLevel; + /* FALL THROUGH */ + + case REVERB_PARAM_REFLECTIONS_LEVEL: + *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nEarlyGain); + + LOGV("get REVERB_PARAM_REFLECTIONS_LEVEL, %d", *pValue16); + if (param == REVERB_PARAM_REFLECTIONS_LEVEL) { + break; + } + pValue32 = &pProperties->reflectionsDelay; + /* FALL THROUGH */ + + case REVERB_PARAM_REFLECTIONS_DELAY: + // convert samples to ms + *pValue32 = (pReverb->m_nEarlyDelay * 1000) / pReverb->m_nSamplingRate; + + LOGV("get REVERB_PARAM_REFLECTIONS_DELAY, samples %d, ms %d", pReverb->m_nEarlyDelay, *pValue32); + + if (param == REVERB_PARAM_REFLECTIONS_DELAY) { + break; + } + pValue16 = &pProperties->reverbLevel; + /* FALL THROUGH */ + + case REVERB_PARAM_REVERB_LEVEL: + // Convert linear gain to millibels + *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nLateGain << 2); + + LOGV("get REVERB_PARAM_REVERB_LEVEL %d", *pValue16); + + if (param == REVERB_PARAM_REVERB_LEVEL) { + break; + } + pValue32 = &pProperties->reverbDelay; + /* FALL THROUGH */ + + case REVERB_PARAM_REVERB_DELAY: + // convert samples to ms + *pValue32 = (pReverb->m_nLateDelay * 1000) / pReverb->m_nSamplingRate; + + LOGV("get REVERB_PARAM_REVERB_DELAY, samples %d, ms %d", pReverb->m_nLateDelay, *pValue32); + + if (param == REVERB_PARAM_REVERB_DELAY) { + break; + } + pValue16 = &pProperties->diffusion; + /* FALL THROUGH */ + + case REVERB_PARAM_DIFFUSION: + temp = (int16_t) ((1000 * (pReverb->m_sAp0.m_nApGain - AP0_GAIN_BASE)) + / AP0_GAIN_RANGE); + + if (temp < 0) + temp = 0; + if (temp > 1000) + temp = 1000; + + *pValue16 = temp; + LOGV("get REVERB_PARAM_DIFFUSION, %d, AP0 gain %d", *pValue16, pReverb->m_sAp0.m_nApGain); + + if (param == REVERB_PARAM_DIFFUSION) { + break; + } + pValue16 = &pProperties->density; + /* FALL THROUGH */ + + case REVERB_PARAM_DENSITY: + // Calculate AP delay in time units + temp = ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn) << 16) + / pReverb->m_nSamplingRate; + + temp = (int16_t) ((1000 * (temp - AP0_TIME_BASE)) / AP0_TIME_RANGE); + + if (temp < 0) + temp = 0; + if (temp > 1000) + temp = 1000; + + *pValue16 = temp; + + LOGV("get REVERB_PARAM_DENSITY, %d, AP0 delay smps %d", *pValue16, pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn); + break; + + default: + break; + } + + LOGV("Reverb_getParameter, context %p, param %d, value %d", + pReverb, param, *(int *)pValue); + + return 0; +} /* end Reverb_getParameter */ + +/*---------------------------------------------------------------------------- + * Reverb_setParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set a Reverb parameter + * + * Inputs: + * pReverb - handle to instance data + * param - parameter + * pValue - pointer to parameter value + * size - value size + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- + */ +int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, size_t size, + void *pValue) { + int32_t value32; + int16_t value16; + t_reverb_properties *pProperties; + int32_t i; + int32_t temp; + int32_t temp2; + reverb_preset_t *pPreset; + int maxSamples; + int32_t averageDelay; + size_t paramSize; + + LOGV("Reverb_setParameter, context %p, param %d, value16 %d, value32 %d", + pReverb, param, *(int16_t *)pValue, *(int32_t *)pValue); + + if (pReverb->m_Preset && param != REVERB_PARAM_PRESET) { + return -EINVAL; + } + if (!pReverb->m_Preset && param == REVERB_PARAM_PRESET) { + return -EINVAL; + } + + switch (param) { + case REVERB_PARAM_ROOM_LEVEL: + case REVERB_PARAM_ROOM_HF_LEVEL: + case REVERB_PARAM_DECAY_HF_RATIO: + case REVERB_PARAM_REFLECTIONS_LEVEL: + case REVERB_PARAM_REVERB_LEVEL: + case REVERB_PARAM_DIFFUSION: + case REVERB_PARAM_DENSITY: + paramSize = sizeof(int16_t); + break; + + case REVERB_PARAM_BYPASS: + case REVERB_PARAM_PRESET: + case REVERB_PARAM_DECAY_TIME: + case REVERB_PARAM_REFLECTIONS_DELAY: + case REVERB_PARAM_REVERB_DELAY: + paramSize = sizeof(int32_t); + break; + + case REVERB_PARAM_PROPERTIES: + paramSize = sizeof(t_reverb_properties); + break; + + default: + return -EINVAL; + } + + if (size != paramSize) { + return -EINVAL; + } + + if (paramSize == sizeof(int16_t)) { + value16 = *(int16_t *) pValue; + } else if (paramSize == sizeof(int32_t)) { + value32 = *(int32_t *) pValue; + } else { + pProperties = (t_reverb_properties *) pValue; + } + + pPreset = &pReverb->m_sPreset.m_sPreset[pReverb->m_nCurrentRoom]; + + switch (param) { + case REVERB_PARAM_BYPASS: + pReverb->m_bBypass = (uint16_t)value32; + break; + case REVERB_PARAM_PRESET: + if (value32 != REVERB_PRESET_LARGE_HALL && value32 + != REVERB_PRESET_HALL && value32 != REVERB_PRESET_CHAMBER + && value32 != REVERB_PRESET_ROOM) + return -EINVAL; + pReverb->m_nNextRoom = (int16_t) value32; + break; + + case REVERB_PARAM_PROPERTIES: + value16 = pProperties->roomLevel; + /* FALL THROUGH */ + + case REVERB_PARAM_ROOM_LEVEL: + // Convert millibels to linear 16 bit signed => m_nRoomLpfFwd + if (value16 > 0) + return -EINVAL; + + temp = Effects_MillibelsToLinear16(value16); + + pReverb->m_nRoomLpfFwd + = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRoomLpfFbk)); + + LOGV("REVERB_PARAM_ROOM_LEVEL, gain %d, new m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk); + if (param == REVERB_PARAM_ROOM_LEVEL) + break; + value16 = pProperties->roomHFLevel; + /* FALL THROUGH */ + + case REVERB_PARAM_ROOM_HF_LEVEL: + + // Limit to 0 , -40dB range because of low pass implementation + if (value16 > 0 || value16 < -4000) + return -EINVAL; + // Convert attenuation @ 5000H expressed in millibels to => m_nRoomLpfFbk + // m_nRoomLpfFbk is -a1 where a1 is the solution of: + // a1^2 + 2*(C-dG^2)/(1-dG^2)*a1 + 1 = 0 where: + // - C is cos(2*pi*5000/Fs) (pReverb->m_nCosWT_5KHz) + // - dG is G0/Gf (G0 is the linear gain at DC and Gf is the wanted gain at 5000Hz) + + // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged + // while changing HF level + temp2 = (pReverb->m_nRoomLpfFwd << 15) / (32767 + - pReverb->m_nRoomLpfFbk); + if (value16 == 0) { + pReverb->m_nRoomLpfFbk = 0; + } else { + int32_t dG2, b, delta; + + // dG^2 + temp = Effects_MillibelsToLinear16(value16); + LOGV("REVERB_PARAM_ROOM_HF_LEVEL, HF gain %d", temp); + temp = (1 << 30) / temp; + LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain %d", temp); + dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15); + LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain ^ 2 %d", dG2); + // b = 2*(C-dG^2)/(1-dG^2) + b = (int32_t) ((((int64_t) 1 << (15 + 1)) + * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2)) + / ((int64_t) 32767 - (int64_t) dG2)); + + // delta = b^2 - 4 + delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15 + + 2))); + + LOGV_IF(delta > (1<<30), " delta overflow %d", delta); + + LOGV("REVERB_PARAM_ROOM_HF_LEVEL, dG2 %d, b %d, delta %d, m_nCosWT_5KHz %d", dG2, b, delta, pReverb->m_nCosWT_5KHz); + // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2 + pReverb->m_nRoomLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1; + } + LOGV("REVERB_PARAM_ROOM_HF_LEVEL, olg DC gain %d new m_nRoomLpfFbk %d, old m_nRoomLpfFwd %d", + temp2, pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFwd); + + pReverb->m_nRoomLpfFwd + = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRoomLpfFbk)); + LOGV("REVERB_PARAM_ROOM_HF_LEVEL, new m_nRoomLpfFwd %d", pReverb->m_nRoomLpfFwd); + + if (param == REVERB_PARAM_ROOM_HF_LEVEL) + break; + value32 = pProperties->decayTime; + /* FALL THROUGH */ + + case REVERB_PARAM_DECAY_TIME: + + // Convert milliseconds to => m_nRvbLpfFwd (function of m_nRvbLpfFbk) + // convert ms to samples + value32 = (value32 * pReverb->m_nSamplingRate) / 1000; + // calculate valid decay time range as a function of current reverb delay and + // max feed back gain. Min value <=> -40dB in one pass, Max value <=> feedback gain = -1 dB + // Calculate attenuation for each round in late reverb given a total attenuation of -6000 millibels. + // g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time + averageDelay = pReverb->m_nLateDelay - pReverb->m_nMaxExcursion; + averageDelay += ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn) + + (pReverb->m_sAp1.m_zApOut - pReverb->m_sAp1.m_zApIn)) >> 1; + + temp = (-6000 * averageDelay) / value32; + LOGV("REVERB_PARAM_DECAY_TIME, delay smps %d, DT smps %d, gain mB %d",averageDelay, value32, temp); + if (temp < -4000 || temp > -100) + return -EINVAL; + + // calculate low pass gain by adding reverb input attenuation (pReverb->m_nLateGain) and substrating output + // xfade and sum gain (max +9dB) + temp -= Effects_Linear16ToMillibels(pReverb->m_nLateGain) + 900; + temp = Effects_MillibelsToLinear16(temp); + + // DC gain (temp) = b0 / (1 + a1) = pReverb->m_nRvbLpfFwd / (32767 - pReverb->m_nRvbLpfFbk) + pReverb->m_nRvbLpfFwd + = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRvbLpfFbk)); + + LOGV("REVERB_PARAM_DECAY_TIME, gain %d, new m_nRvbLpfFwd %d, old m_nRvbLpfFbk %d, reverb gain %d", temp, pReverb->m_nRvbLpfFwd, pReverb->m_nRvbLpfFbk, Effects_Linear16ToMillibels(pReverb->m_nLateGain)); + + if (param == REVERB_PARAM_DECAY_TIME) + break; + value16 = pProperties->decayHFRatio; + /* FALL THROUGH */ + + case REVERB_PARAM_DECAY_HF_RATIO: + + // We limit max value to 1000 because reverb filter is lowpass only + if (value16 < 100 || value16 > 1000) + return -EINVAL; + // Convert per mille to => m_nLpfFwd, m_nLpfFbk + + // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged + // while changing HF level + temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk); + + if (value16 == 1000) { + pReverb->m_nRvbLpfFbk = 0; + } else { + int32_t dG2, b, delta; + + temp = Effects_Linear16ToMillibels(temp2); + // G_5000Hz = G_DC * (1000/REVERB_PARAM_DECAY_HF_RATIO) in millibels + + value32 = ((int32_t) 1000 << 15) / (int32_t) value16; + LOGV("REVERB_PARAM_DECAY_HF_RATIO, DC gain %d, DC gain mB %d, 1000/R %d", temp2, temp, value32); + + temp = (int32_t) (((int64_t) temp * (int64_t) value32) >> 15); + + if (temp < -4000) { + LOGV("REVERB_PARAM_DECAY_HF_RATIO HF gain overflow %d mB", temp); + temp = -4000; + } + + temp = Effects_MillibelsToLinear16(temp); + LOGV("REVERB_PARAM_DECAY_HF_RATIO, HF gain %d", temp); + // dG^2 + temp = (temp2 << 15) / temp; + dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15); + + // b = 2*(C-dG^2)/(1-dG^2) + b = (int32_t) ((((int64_t) 1 << (15 + 1)) + * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2)) + / ((int64_t) 32767 - (int64_t) dG2)); + + // delta = b^2 - 4 + delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15 + + 2))); + + // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2 + pReverb->m_nRvbLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1; + + LOGV("REVERB_PARAM_DECAY_HF_RATIO, dG2 %d, b %d, delta %d", dG2, b, delta); + + } + + LOGV("REVERB_PARAM_DECAY_HF_RATIO, gain %d, m_nRvbLpfFbk %d, m_nRvbLpfFwd %d", temp2, pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFwd); + + pReverb->m_nRvbLpfFwd + = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRvbLpfFbk)); + + if (param == REVERB_PARAM_DECAY_HF_RATIO) + break; + value16 = pProperties->reflectionsLevel; + /* FALL THROUGH */ + + case REVERB_PARAM_REFLECTIONS_LEVEL: + // We limit max value to 0 because gain is limited to 0dB + if (value16 > 0 || value16 < -6000) + return -EINVAL; + + // Convert millibels to linear 16 bit signed and recompute m_sEarlyL.m_nGain[i] and m_sEarlyR.m_nGain[i]. + value16 = Effects_MillibelsToLinear16(value16); + for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) { + pReverb->m_sEarlyL.m_nGain[i] + = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],value16); + pReverb->m_sEarlyR.m_nGain[i] + = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],value16); + } + pReverb->m_nEarlyGain = value16; + LOGV("REVERB_PARAM_REFLECTIONS_LEVEL, m_nEarlyGain %d", pReverb->m_nEarlyGain); + + if (param == REVERB_PARAM_REFLECTIONS_LEVEL) + break; + value32 = pProperties->reflectionsDelay; + /* FALL THROUGH */ + + case REVERB_PARAM_REFLECTIONS_DELAY: + // We limit max value MAX_EARLY_TIME + // convert ms to time units + temp = (value32 * 65536) / 1000; + if (temp < 0 || temp > MAX_EARLY_TIME) + return -EINVAL; + + maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate) + >> 16; + temp = (temp * pReverb->m_nSamplingRate) >> 16; + for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) { + temp2 = temp + (((int32_t) pPreset->m_sEarlyL.m_zDelay[i] + * pReverb->m_nSamplingRate) >> 16); + if (temp2 > maxSamples) + temp2 = maxSamples; + pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp2; + temp2 = temp + (((int32_t) pPreset->m_sEarlyR.m_zDelay[i] + * pReverb->m_nSamplingRate) >> 16); + if (temp2 > maxSamples) + temp2 = maxSamples; + pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp2; + } + pReverb->m_nEarlyDelay = temp; + + LOGV("REVERB_PARAM_REFLECTIONS_DELAY, m_nEarlyDelay smps %d max smp delay %d", pReverb->m_nEarlyDelay, maxSamples); + + // Convert milliseconds to sample count => m_nEarlyDelay + if (param == REVERB_PARAM_REFLECTIONS_DELAY) + break; + value16 = pProperties->reverbLevel; + /* FALL THROUGH */ + + case REVERB_PARAM_REVERB_LEVEL: + // We limit max value to 0 because gain is limited to 0dB + if (value16 > 0 || value16 < -6000) + return -EINVAL; + // Convert millibels to linear 16 bits (gange 0 - 8191) => m_nLateGain. + pReverb->m_nLateGain = Effects_MillibelsToLinear16(value16) >> 2; + + LOGV("REVERB_PARAM_REVERB_LEVEL, m_nLateGain %d", pReverb->m_nLateGain); + + if (param == REVERB_PARAM_REVERB_LEVEL) + break; + value32 = pProperties->reverbDelay; + /* FALL THROUGH */ + + case REVERB_PARAM_REVERB_DELAY: + // We limit max value to MAX_DELAY_TIME + // convert ms to time units + temp = (value32 * 65536) / 1000; + if (temp < 0 || temp > MAX_DELAY_TIME) + return -EINVAL; + + maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate) + >> 16; + temp = (temp * pReverb->m_nSamplingRate) >> 16; + if ((temp + pReverb->m_nMaxExcursion) > maxSamples) { + temp = maxSamples - pReverb->m_nMaxExcursion; + } + if (temp < pReverb->m_nMaxExcursion) { + temp = pReverb->m_nMaxExcursion; + } + + temp -= pReverb->m_nLateDelay; + pReverb->m_nDelay0Out += temp; + pReverb->m_nDelay1Out += temp; + pReverb->m_nLateDelay += temp; + + LOGV("REVERB_PARAM_REVERB_DELAY, m_nLateDelay smps %d max smp delay %d", pReverb->m_nLateDelay, maxSamples); + + // Convert milliseconds to sample count => m_nDelay1Out + m_nMaxExcursion + if (param == REVERB_PARAM_REVERB_DELAY) + break; + + value16 = pProperties->diffusion; + /* FALL THROUGH */ + + case REVERB_PARAM_DIFFUSION: + if (value16 < 0 || value16 > 1000) + return -EINVAL; + + // Convert per mille to m_sAp0.m_nApGain, m_sAp1.m_nApGain + pReverb->m_sAp0.m_nApGain = AP0_GAIN_BASE + ((int32_t) value16 + * AP0_GAIN_RANGE) / 1000; + pReverb->m_sAp1.m_nApGain = AP1_GAIN_BASE + ((int32_t) value16 + * AP1_GAIN_RANGE) / 1000; + + LOGV("REVERB_PARAM_DIFFUSION, m_sAp0.m_nApGain %d m_sAp1.m_nApGain %d", pReverb->m_sAp0.m_nApGain, pReverb->m_sAp1.m_nApGain); + + if (param == REVERB_PARAM_DIFFUSION) + break; + + value16 = pProperties->density; + /* FALL THROUGH */ + + case REVERB_PARAM_DENSITY: + if (value16 < 0 || value16 > 1000) + return -EINVAL; + + // Convert per mille to m_sAp0.m_zApOut, m_sAp1.m_zApOut + maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16; + + temp = AP0_TIME_BASE + ((int32_t) value16 * AP0_TIME_RANGE) / 1000; + /*lint -e{702} shift for performance */ + temp = (temp * pReverb->m_nSamplingRate) >> 16; + if (temp > maxSamples) + temp = maxSamples; + pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp); + + LOGV("REVERB_PARAM_DENSITY, Ap0 delay smps %d", temp); + + temp = AP1_TIME_BASE + ((int32_t) value16 * AP1_TIME_RANGE) / 1000; + /*lint -e{702} shift for performance */ + temp = (temp * pReverb->m_nSamplingRate) >> 16; + if (temp > maxSamples) + temp = maxSamples; + pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp); + + LOGV("Ap1 delay smps %d", temp); + + break; + + default: + break; + } + return 0; +} /* end Reverb_setParameter */ + +/*---------------------------------------------------------------------------- + * ReverbUpdateXfade + *---------------------------------------------------------------------------- + * Purpose: + * Update the xfade parameters as required + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * + * + * Side Effects: + * - xfade parameters will be changed + * + *---------------------------------------------------------------------------- + */ +static int ReverbUpdateXfade(reverb_object_t *pReverb, int nNumSamplesToAdd) { + uint16_t nOffset; + int16_t tempCos; + int16_t tempSin; + + if (pReverb->m_nXfadeCounter >= pReverb->m_nXfadeInterval) { + /* update interval has elapsed, so reset counter */ + pReverb->m_nXfadeCounter = 0; + + // Pin the sin,cos values to min / max values to ensure that the + // modulated taps' coefs are zero (thus no clicks) + if (pReverb->m_nPhaseIncrement > 0) { + // if phase increment > 0, then sin -> 1, cos -> 0 + pReverb->m_nSin = 32767; + pReverb->m_nCos = 0; + + // reset the phase to match the sin, cos values + pReverb->m_nPhase = 32767; + + // modulate the cross taps because their tap coefs are zero + nOffset = ReverbCalculateNoise(pReverb); + + pReverb->m_zD1Cross = pReverb->m_nDelay1Out + - pReverb->m_nMaxExcursion + nOffset; + + nOffset = ReverbCalculateNoise(pReverb); + + pReverb->m_zD0Cross = pReverb->m_nDelay0Out + - pReverb->m_nMaxExcursion - nOffset; + } else { + // if phase increment < 0, then sin -> 0, cos -> 1 + pReverb->m_nSin = 0; + pReverb->m_nCos = 32767; + + // reset the phase to match the sin, cos values + pReverb->m_nPhase = -32768; + + // modulate the self taps because their tap coefs are zero + nOffset = ReverbCalculateNoise(pReverb); + + pReverb->m_zD0Self = pReverb->m_nDelay0Out + - pReverb->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise(pReverb); + + pReverb->m_zD1Self = pReverb->m_nDelay1Out + - pReverb->m_nMaxExcursion + nOffset; + + } // end if-else (pReverb->m_nPhaseIncrement > 0) + + // Reverse the direction of the sin,cos so that the + // tap whose coef was previously increasing now decreases + // and vice versa + pReverb->m_nPhaseIncrement = -pReverb->m_nPhaseIncrement; + + } // end if counter >= update interval + + //compute what phase will be next time + pReverb->m_nPhase += pReverb->m_nPhaseIncrement; + + //calculate what the new sin and cos need to reach by the next update + ReverbCalculateSinCos(pReverb->m_nPhase, &tempSin, &tempCos); + + //calculate the per-sample increment required to get there by the next update + /*lint -e{702} shift for performance */ + pReverb->m_nSinIncrement = (tempSin - pReverb->m_nSin) + >> pReverb->m_nUpdatePeriodInBits; + + /*lint -e{702} shift for performance */ + pReverb->m_nCosIncrement = (tempCos - pReverb->m_nCos) + >> pReverb->m_nUpdatePeriodInBits; + + /* increment update counter */ + pReverb->m_nXfadeCounter += (uint16_t) nNumSamplesToAdd; + + return 0; + +} /* end ReverbUpdateXfade */ + +/*---------------------------------------------------------------------------- + * ReverbCalculateNoise + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a noise sample and limit its value + * + * Inputs: + * nMaxExcursion - noise value is limited to this value + * pnNoise - return new noise sample in this (not limited) + * + * Outputs: + * new limited noise value + * + * Side Effects: + * - *pnNoise noise value is updated + * + *---------------------------------------------------------------------------- + */ +static uint16_t ReverbCalculateNoise(reverb_object_t *pReverb) { + int16_t nNoise = pReverb->m_nNoise; + + // calculate new noise value + if (pReverb->m_bUseNoise) { + nNoise = (int16_t) (nNoise * 5 + 1); + } else { + nNoise = 0; + } + + pReverb->m_nNoise = nNoise; + // return the limited noise value + return (pReverb->m_nMaxExcursion & nNoise); + +} /* end ReverbCalculateNoise */ + +/*---------------------------------------------------------------------------- + * ReverbCalculateSinCos + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a new sin and cosine value based on the given phase + * + * Inputs: + * nPhase - phase angle + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * + * Side Effects: + * - *pnSin, *pnCos are updated + * + *---------------------------------------------------------------------------- + */ +static int ReverbCalculateSinCos(int16_t nPhase, int16_t *pnSin, int16_t *pnCos) { + int32_t nTemp; + int32_t nNetAngle; + + // -1 <= nPhase < 1 + // However, for the calculation, we need a value + // that ranges from -1/2 to +1/2, so divide the phase by 2 + /*lint -e{702} shift for performance */ + nNetAngle = nPhase >> 1; + + /* + Implement the following + sin(x) = (2-4*c)*x^2 + c + x + cos(x) = (2-4*c)*x^2 + c - x + + where c = 1/sqrt(2) + using the a0 + x*(a1 + x*a2) approach + */ + + /* limit the input "angle" to be between -0.5 and +0.5 */ + if (nNetAngle > EG1_HALF) { + nNetAngle = EG1_HALF; + } else if (nNetAngle < EG1_MINUS_HALF) { + nNetAngle = EG1_MINUS_HALF; + } + + /* calculate sin */ + nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); + nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); + *pnSin = (int16_t) SATURATE_EG1(nTemp); + + /* calculate cos */ + nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); + nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); + *pnCos = (int16_t) SATURATE_EG1(nTemp); + + return 0; +} /* end ReverbCalculateSinCos */ + +/*---------------------------------------------------------------------------- + * Reverb + *---------------------------------------------------------------------------- + * Purpose: + * apply reverb to the given signal + * + * Inputs: + * nNu + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * number of samples actually reverberated + * + * Side Effects: + * + *---------------------------------------------------------------------------- + */ +static int Reverb(reverb_object_t *pReverb, int nNumSamplesToAdd, + short *pOutputBuffer, short *pInputBuffer) { + int32_t i; + int32_t nDelayOut0; + int32_t nDelayOut1; + uint16_t nBase; + + uint32_t nAddr; + int32_t nTemp1; + int32_t nTemp2; + int32_t nApIn; + int32_t nApOut; + + int32_t j; + int32_t nEarlyOut; + + int32_t tempValue; + + // get the base address + nBase = pReverb->m_nBaseIndex; + + for (i = 0; i < nNumSamplesToAdd; i++) { + // ********** Left Allpass - start + nApIn = *pInputBuffer; + if (!pReverb->m_Aux) { + pInputBuffer++; + } + // store to early delay line + nAddr = CIRCULAR(nBase, pReverb->m_nEarly0in, pReverb->m_nBufferMask); + pReverb->m_nDelayLine[nAddr] = (short) nApIn; + + // left input = (left dry * m_nLateGain) + right feedback from previous period + + nApIn = SATURATE(nApIn + pReverb->m_nRevFbkR); + nApIn = MULT_EG1_EG1(nApIn, pReverb->m_nLateGain); + + // fetch allpass delay line out + //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, pReverb->m_nBufferMask); + nAddr + = CIRCULAR(nBase, pReverb->m_sAp0.m_zApOut, pReverb->m_nBufferMask); + nDelayOut0 = pReverb->m_nDelayLine[nAddr]; + + // calculate allpass feedforward; subtract the feedforward result + nTemp1 = MULT_EG1_EG1(nApIn, pReverb->m_sAp0.m_nApGain); + nApOut = SATURATE(nDelayOut0 - nTemp1); // allpass output + + // calculate allpass feedback; add the feedback result + nTemp1 = MULT_EG1_EG1(nApOut, pReverb->m_sAp0.m_nApGain); + nTemp1 = SATURATE(nApIn + nTemp1); + + // inject into allpass delay + nAddr + = CIRCULAR(nBase, pReverb->m_sAp0.m_zApIn, pReverb->m_nBufferMask); + pReverb->m_nDelayLine[nAddr] = (short) nTemp1; + + // inject allpass output into delay line + nAddr = CIRCULAR(nBase, pReverb->m_zD0In, pReverb->m_nBufferMask); + pReverb->m_nDelayLine[nAddr] = (short) nApOut; + + // ********** Left Allpass - end + + // ********** Right Allpass - start + nApIn = (*pInputBuffer++); + // store to early delay line + nAddr = CIRCULAR(nBase, pReverb->m_nEarly1in, pReverb->m_nBufferMask); + pReverb->m_nDelayLine[nAddr] = (short) nApIn; + + // right input = (right dry * m_nLateGain) + left feedback from previous period + /*lint -e{702} use shift for performance */ + nApIn = SATURATE(nApIn + pReverb->m_nRevFbkL); + nApIn = MULT_EG1_EG1(nApIn, pReverb->m_nLateGain); + + // fetch allpass delay line out + nAddr + = CIRCULAR(nBase, pReverb->m_sAp1.m_zApOut, pReverb->m_nBufferMask); + nDelayOut1 = pReverb->m_nDelayLine[nAddr]; + + // calculate allpass feedforward; subtract the feedforward result + nTemp1 = MULT_EG1_EG1(nApIn, pReverb->m_sAp1.m_nApGain); + nApOut = SATURATE(nDelayOut1 - nTemp1); // allpass output + + // calculate allpass feedback; add the feedback result + nTemp1 = MULT_EG1_EG1(nApOut, pReverb->m_sAp1.m_nApGain); + nTemp1 = SATURATE(nApIn + nTemp1); + + // inject into allpass delay + nAddr + = CIRCULAR(nBase, pReverb->m_sAp1.m_zApIn, pReverb->m_nBufferMask); + pReverb->m_nDelayLine[nAddr] = (short) nTemp1; + + // inject allpass output into delay line + nAddr = CIRCULAR(nBase, pReverb->m_zD1In, pReverb->m_nBufferMask); + pReverb->m_nDelayLine[nAddr] = (short) nApOut; + + // ********** Right Allpass - end + + // ********** D0 output - start + // fetch delay line self out + nAddr = CIRCULAR(nBase, pReverb->m_zD0Self, pReverb->m_nBufferMask); + nDelayOut0 = pReverb->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nSin); + + // fetch delay line cross out + nAddr = CIRCULAR(nBase, pReverb->m_zD1Cross, pReverb->m_nBufferMask); + nDelayOut0 = pReverb->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp2 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nCos); + + // calculate unfiltered delay out + nDelayOut0 = SATURATE(nTemp1 + nTemp2); + + // ********** D0 output - end + + // ********** D1 output - start + // fetch delay line self out + nAddr = CIRCULAR(nBase, pReverb->m_zD1Self, pReverb->m_nBufferMask); + nDelayOut1 = pReverb->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nSin); + + // fetch delay line cross out + nAddr = CIRCULAR(nBase, pReverb->m_zD0Cross, pReverb->m_nBufferMask); + nDelayOut1 = pReverb->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp2 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nCos); + + // calculate unfiltered delay out + nDelayOut1 = SATURATE(nTemp1 + nTemp2); + + // ********** D1 output - end + + // ********** mixer and feedback - start + // sum is fedback to right input (R + L) + nDelayOut0 = (short) SATURATE(nDelayOut0 + nDelayOut1); + + // difference is feedback to left input (R - L) + /*lint -e{685} lint complains that it can't saturate negative */ + nDelayOut1 = (short) SATURATE(nDelayOut1 - nDelayOut0); + + // ********** mixer and feedback - end + + // calculate lowpass filter (mixer scale factor included in LPF feedforward) + nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nRvbLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverb->m_nRevFbkL, pReverb->m_nRvbLpfFbk); + + // calculate filtered delay out and simultaneously update LPF state variable + // filtered delay output is stored in m_nRevFbkL + pReverb->m_nRevFbkL = (short) SATURATE(nTemp1 + nTemp2); + + // calculate lowpass filter (mixer scale factor included in LPF feedforward) + nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nRvbLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverb->m_nRevFbkR, pReverb->m_nRvbLpfFbk); + + // calculate filtered delay out and simultaneously update LPF state variable + // filtered delay output is stored in m_nRevFbkR + pReverb->m_nRevFbkR = (short) SATURATE(nTemp1 + nTemp2); + + // ********** start early reflection generator, left + //psEarly = &(pReverb->m_sEarlyL); + + + for (j = 0; j < REVERB_MAX_NUM_REFLECTIONS; j++) { + // fetch delay line out + //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], pReverb->m_nBufferMask); + nAddr + = CIRCULAR(nBase, pReverb->m_sEarlyL.m_zDelay[j], pReverb->m_nBufferMask); + + nTemp1 = pReverb->m_nDelayLine[nAddr]; + + // calculate reflection + //nTemp1 = MULT_EG1_EG1(nDelayOut0, psEarly->m_nGain[j]); + nTemp1 = MULT_EG1_EG1(nTemp1, pReverb->m_sEarlyL.m_nGain[j]); + + nDelayOut0 = SATURATE(nDelayOut0 + nTemp1); + + } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + + // apply lowpass to early reflections and reverb output + //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nRvbLpfFwd); + nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nRoomLpfFwd); + + //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk); + nTemp2 = MULT_EG1_EG1(pReverb->m_zOutLpfL, pReverb->m_nRoomLpfFbk); + + // calculate filtered out and simultaneously update LPF state variable + // filtered output is stored in m_zOutLpfL + pReverb->m_zOutLpfL = (short) SATURATE(nTemp1 + nTemp2); + + //sum with output buffer + tempValue = *pOutputBuffer; + *pOutputBuffer++ = (short) SATURATE(tempValue+pReverb->m_zOutLpfL); + + // ********** end early reflection generator, left + + // ********** start early reflection generator, right + //psEarly = &(pReverb->m_sEarlyR); + + for (j = 0; j < REVERB_MAX_NUM_REFLECTIONS; j++) { + // fetch delay line out + nAddr + = CIRCULAR(nBase, pReverb->m_sEarlyR.m_zDelay[j], pReverb->m_nBufferMask); + nTemp1 = pReverb->m_nDelayLine[nAddr]; + + // calculate reflection + nTemp1 = MULT_EG1_EG1(nTemp1, pReverb->m_sEarlyR.m_nGain[j]); + + nDelayOut1 = SATURATE(nDelayOut1 + nTemp1); + + } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + + // apply lowpass to early reflections + nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nRoomLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverb->m_zOutLpfR, pReverb->m_nRoomLpfFbk); + + // calculate filtered out and simultaneously update LPF state variable + // filtered output is stored in m_zOutLpfR + pReverb->m_zOutLpfR = (short) SATURATE(nTemp1 + nTemp2); + + //sum with output buffer + tempValue = *pOutputBuffer; + *pOutputBuffer++ = (short) SATURATE(tempValue + pReverb->m_zOutLpfR); + + // ********** end early reflection generator, right + + // decrement base addr for next sample period + nBase--; + + pReverb->m_nSin += pReverb->m_nSinIncrement; + pReverb->m_nCos += pReverb->m_nCosIncrement; + + } // end for (i=0; i < nNumSamplesToAdd; i++) + + // store the most up to date version + pReverb->m_nBaseIndex = nBase; + + return 0; +} /* end Reverb */ + +/*---------------------------------------------------------------------------- + * ReverbUpdateRoom + *---------------------------------------------------------------------------- + * Purpose: + * Update the room's preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - reverb paramters (fbk, fwd, etc) will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- + */ +static int ReverbUpdateRoom(reverb_object_t *pReverb, bool fullUpdate) { + int temp; + int i; + int maxSamples; + int earlyDelay; + int earlyGain; + + reverb_preset_t *pPreset = + &pReverb->m_sPreset.m_sPreset[pReverb->m_nNextRoom]; + + if (fullUpdate) { + pReverb->m_nRvbLpfFwd = pPreset->m_nRvbLpfFwd; + pReverb->m_nRvbLpfFbk = pPreset->m_nRvbLpfFbk; + + pReverb->m_nEarlyGain = pPreset->m_nEarlyGain; + //stored as time based, convert to sample based + pReverb->m_nLateGain = pPreset->m_nLateGain; + pReverb->m_nRoomLpfFbk = pPreset->m_nRoomLpfFbk; + pReverb->m_nRoomLpfFwd = pPreset->m_nRoomLpfFwd; + + // set the early reflections gains + earlyGain = pPreset->m_nEarlyGain; + for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) { + pReverb->m_sEarlyL.m_nGain[i] + = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],earlyGain); + pReverb->m_sEarlyR.m_nGain[i] + = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],earlyGain); + } + + pReverb->m_nMaxExcursion = pPreset->m_nMaxExcursion; + + pReverb->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain; + pReverb->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain; + + // set the early reflections delay + earlyDelay = ((int) pPreset->m_nEarlyDelay * pReverb->m_nSamplingRate) + >> 16; + pReverb->m_nEarlyDelay = earlyDelay; + maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate) + >> 16; + for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) { + //stored as time based, convert to sample based + temp = earlyDelay + (((int) pPreset->m_sEarlyL.m_zDelay[i] + * pReverb->m_nSamplingRate) >> 16); + if (temp > maxSamples) + temp = maxSamples; + pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp; + //stored as time based, convert to sample based + temp = earlyDelay + (((int) pPreset->m_sEarlyR.m_zDelay[i] + * pReverb->m_nSamplingRate) >> 16); + if (temp > maxSamples) + temp = maxSamples; + pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp; + } + + maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate) + >> 16; + //stored as time based, convert to sample based + /*lint -e{702} shift for performance */ + temp = (pPreset->m_nLateDelay * pReverb->m_nSamplingRate) >> 16; + if ((temp + pReverb->m_nMaxExcursion) > maxSamples) { + temp = maxSamples - pReverb->m_nMaxExcursion; + } + temp -= pReverb->m_nLateDelay; + pReverb->m_nDelay0Out += temp; + pReverb->m_nDelay1Out += temp; + pReverb->m_nLateDelay += temp; + + maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp0_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * pReverb->m_nSamplingRate) >> 16; + if (temp > maxSamples) + temp = maxSamples; + pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp); + + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp1_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * pReverb->m_nSamplingRate) >> 16; + if (temp > maxSamples) + temp = maxSamples; + pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp); + //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut; + } + + //stored as time based, convert to sample based + temp = pPreset->m_nXfadeInterval; + /*lint -e{702} shift for performance */ + temp = (temp * pReverb->m_nSamplingRate) >> 16; + pReverb->m_nXfadeInterval = (uint16_t) temp; + //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval; + pReverb->m_nXfadeCounter = pReverb->m_nXfadeInterval + 1; // force update on first iteration + + + pReverb->m_nCurrentRoom = pReverb->m_nNextRoom; + + return 0; + +} /* end ReverbUpdateRoom */ + +/*---------------------------------------------------------------------------- + * ReverbReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global reverb preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- + */ +static int ReverbReadInPresets(reverb_object_t *pReverb) { + + int preset = 0; + int defaultPreset = 0; + + //now init any remaining presets to defaults + for (defaultPreset = preset; defaultPreset < REVERB_MAX_ROOM_TYPE; defaultPreset++) { + reverb_preset_t *pPreset = &pReverb->m_sPreset.m_sPreset[defaultPreset]; + if (defaultPreset == 0 || defaultPreset > REVERB_MAX_ROOM_TYPE - 1) { + pPreset->m_nRvbLpfFbk = 8307; + pPreset->m_nRvbLpfFwd = 14768; + pPreset->m_nEarlyGain = 27690; + pPreset->m_nEarlyDelay = 1311; + pPreset->m_nLateGain = 8191; + pPreset->m_nLateDelay = 3932; + pPreset->m_nRoomLpfFbk = 3692; + pPreset->m_nRoomLpfFwd = 24569; + pPreset->m_sEarlyL.m_zDelay[0] = 1376; + pPreset->m_sEarlyL.m_nGain[0] = 22152; + pPreset->m_sEarlyL.m_zDelay[1] = 2163; + pPreset->m_sEarlyL.m_nGain[1] = 17537; + pPreset->m_sEarlyL.m_zDelay[2] = 0; + pPreset->m_sEarlyL.m_nGain[2] = 14768; + pPreset->m_sEarlyL.m_zDelay[3] = 1835; + pPreset->m_sEarlyL.m_nGain[3] = 14307; + pPreset->m_sEarlyL.m_zDelay[4] = 0; + pPreset->m_sEarlyL.m_nGain[4] = 13384; + pPreset->m_sEarlyR.m_zDelay[0] = 721; + pPreset->m_sEarlyR.m_nGain[0] = 20306; + pPreset->m_sEarlyR.m_zDelay[1] = 2621; + pPreset->m_sEarlyR.m_nGain[1] = 17537; + pPreset->m_sEarlyR.m_zDelay[2] = 0; + pPreset->m_sEarlyR.m_nGain[2] = 14768; + pPreset->m_sEarlyR.m_zDelay[3] = 0; + pPreset->m_sEarlyR.m_nGain[3] = 16153; + pPreset->m_sEarlyR.m_zDelay[4] = 0; + pPreset->m_sEarlyR.m_nGain[4] = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6388; + pPreset->m_nAp0_ApGain = 15691; + pPreset->m_nAp0_ApOut = 711; + pPreset->m_nAp1_ApGain = 16317; + pPreset->m_nAp1_ApOut = 1029; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } else if (defaultPreset == 1) { + pPreset->m_nRvbLpfFbk = 6461; + pPreset->m_nRvbLpfFwd = 14307; + pPreset->m_nEarlyGain = 27690; + pPreset->m_nEarlyDelay = 1311; + pPreset->m_nLateGain = 8191; + pPreset->m_nLateDelay = 3932; + pPreset->m_nRoomLpfFbk = 3692; + pPreset->m_nRoomLpfFwd = 24569; + pPreset->m_sEarlyL.m_zDelay[0] = 1376; + pPreset->m_sEarlyL.m_nGain[0] = 22152; + pPreset->m_sEarlyL.m_zDelay[1] = 1462; + pPreset->m_sEarlyL.m_nGain[1] = 17537; + pPreset->m_sEarlyL.m_zDelay[2] = 0; + pPreset->m_sEarlyL.m_nGain[2] = 14768; + pPreset->m_sEarlyL.m_zDelay[3] = 1835; + pPreset->m_sEarlyL.m_nGain[3] = 14307; + pPreset->m_sEarlyL.m_zDelay[4] = 0; + pPreset->m_sEarlyL.m_nGain[4] = 13384; + pPreset->m_sEarlyR.m_zDelay[0] = 721; + pPreset->m_sEarlyR.m_nGain[0] = 20306; + pPreset->m_sEarlyR.m_zDelay[1] = 2621; + pPreset->m_sEarlyR.m_nGain[1] = 17537; + pPreset->m_sEarlyR.m_zDelay[2] = 0; + pPreset->m_sEarlyR.m_nGain[2] = 14768; + pPreset->m_sEarlyR.m_zDelay[3] = 0; + pPreset->m_sEarlyR.m_nGain[3] = 16153; + pPreset->m_sEarlyR.m_zDelay[4] = 0; + pPreset->m_sEarlyR.m_nGain[4] = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6391; + pPreset->m_nAp0_ApGain = 15230; + pPreset->m_nAp0_ApOut = 708; + pPreset->m_nAp1_ApGain = 15547; + pPreset->m_nAp1_ApOut = 1023; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } else if (defaultPreset == 2) { + pPreset->m_nRvbLpfFbk = 5077; + pPreset->m_nRvbLpfFwd = 12922; + pPreset->m_nEarlyGain = 27690; + pPreset->m_nEarlyDelay = 1311; + pPreset->m_nLateGain = 8191; + pPreset->m_nLateDelay = 3932; + pPreset->m_nRoomLpfFbk = 3692; + pPreset->m_nRoomLpfFwd = 21703; + pPreset->m_sEarlyL.m_zDelay[0] = 1376; + pPreset->m_sEarlyL.m_nGain[0] = 22152; + pPreset->m_sEarlyL.m_zDelay[1] = 1462; + pPreset->m_sEarlyL.m_nGain[1] = 17537; + pPreset->m_sEarlyL.m_zDelay[2] = 0; + pPreset->m_sEarlyL.m_nGain[2] = 14768; + pPreset->m_sEarlyL.m_zDelay[3] = 1835; + pPreset->m_sEarlyL.m_nGain[3] = 14307; + pPreset->m_sEarlyL.m_zDelay[4] = 0; + pPreset->m_sEarlyL.m_nGain[4] = 13384; + pPreset->m_sEarlyR.m_zDelay[0] = 721; + pPreset->m_sEarlyR.m_nGain[0] = 20306; + pPreset->m_sEarlyR.m_zDelay[1] = 2621; + pPreset->m_sEarlyR.m_nGain[1] = 17537; + pPreset->m_sEarlyR.m_zDelay[2] = 0; + pPreset->m_sEarlyR.m_nGain[2] = 14768; + pPreset->m_sEarlyR.m_zDelay[3] = 0; + pPreset->m_sEarlyR.m_nGain[3] = 16153; + pPreset->m_sEarlyR.m_zDelay[4] = 0; + pPreset->m_sEarlyR.m_nGain[4] = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6449; + pPreset->m_nAp0_ApGain = 15691; + pPreset->m_nAp0_ApOut = 774; + pPreset->m_nAp1_ApGain = 16317; + pPreset->m_nAp1_ApOut = 1155; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } else if (defaultPreset == 3) { + pPreset->m_nRvbLpfFbk = 5077; + pPreset->m_nRvbLpfFwd = 11076; + pPreset->m_nEarlyGain = 27690; + pPreset->m_nEarlyDelay = 1311; + pPreset->m_nLateGain = 8191; + pPreset->m_nLateDelay = 3932; + pPreset->m_nRoomLpfFbk = 3692; + pPreset->m_nRoomLpfFwd = 20474; + pPreset->m_sEarlyL.m_zDelay[0] = 1376; + pPreset->m_sEarlyL.m_nGain[0] = 22152; + pPreset->m_sEarlyL.m_zDelay[1] = 1462; + pPreset->m_sEarlyL.m_nGain[1] = 17537; + pPreset->m_sEarlyL.m_zDelay[2] = 0; + pPreset->m_sEarlyL.m_nGain[2] = 14768; + pPreset->m_sEarlyL.m_zDelay[3] = 1835; + pPreset->m_sEarlyL.m_nGain[3] = 14307; + pPreset->m_sEarlyL.m_zDelay[4] = 0; + pPreset->m_sEarlyL.m_nGain[4] = 13384; + pPreset->m_sEarlyR.m_zDelay[0] = 721; + pPreset->m_sEarlyR.m_nGain[0] = 20306; + pPreset->m_sEarlyR.m_zDelay[1] = 2621; + pPreset->m_sEarlyR.m_nGain[1] = 17537; + pPreset->m_sEarlyR.m_zDelay[2] = 0; + pPreset->m_sEarlyR.m_nGain[2] = 14768; + pPreset->m_sEarlyR.m_zDelay[3] = 0; + pPreset->m_sEarlyR.m_nGain[3] = 16153; + pPreset->m_sEarlyR.m_zDelay[4] = 0; + pPreset->m_sEarlyR.m_nGain[4] = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6470; //6483; + pPreset->m_nAp0_ApGain = 14768; + pPreset->m_nAp0_ApOut = 792; + pPreset->m_nAp1_ApGain = 14777; + pPreset->m_nAp1_ApOut = 1191; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + } + + return 0; +} diff --git a/media/libeffects/EffectReverb.h b/media/libeffects/EffectReverb.h new file mode 100644 index 0000000000000000000000000000000000000000..cd1489144268d21dda956e4b390fc2a98c7d280d --- /dev/null +++ b/media/libeffects/EffectReverb.h @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2008 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 ANDROID_EFFECTREVERB_H_ +#define ANDROID_EFFECTREVERB_H_ + +#include + + +/*------------------------------------ + * defines + *------------------------------------ +*/ + +/* +CIRCULAR() calculates the array index using modulo arithmetic. +The "trick" is that modulo arithmetic is simplified by masking +the effective address where the mask is (2^n)-1. This only works +if the buffer size is a power of two. +*/ +#define CIRCULAR(base,offset,size) (uint32_t)( \ + ( \ + ((int32_t)(base)) + ((int32_t)(offset)) \ + ) \ + & size \ + ) + +#define NUM_OUTPUT_CHANNELS 2 +#define OUTPUT_CHANNELS CHANNEL_STEREO + +#define REVERB_BUFFER_SIZE_IN_SAMPLES_MAX 16384 + +#define REVERB_MAX_ROOM_TYPE 4 // any room numbers larger than this are invalid +#define REVERB_MAX_NUM_REFLECTIONS 5 // max num reflections per channel + + +// xfade parameters +#define REVERB_XFADE_PERIOD_IN_SECONDS (double) (100.0 / 1000.0) // xfade once every this many seconds + + +/**********/ +/* the entire synth uses various flags in a bit field */ + +/* if flag is set, synth reset has been requested */ +#define REVERB_FLAG_RESET_IS_REQUESTED 0x01 /* bit 0 */ +#define MASK_REVERB_RESET_IS_REQUESTED 0x01 +#define MASK_REVERB_RESET_IS_NOT_REQUESTED (uint32_t)(~MASK_REVERB_RESET_IS_REQUESTED) + +/* +by default, we always want to update ALL channel parameters +when we reset the synth (e.g., during GM ON) +*/ +#define DEFAULT_REVERB_FLAGS 0x0 + +/* coefficients for generating sin, cos */ +#define REVERB_PAN_G2 4294940151 /* -0.82842712474619 = 2 - 4/sqrt(2) */ +/* +int32_t nPanG1 = +1.0 for sin +int32_t nPanG1 = -1.0 for cos +*/ +#define REVERB_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ + +/*************************************************************/ +// define the input injection points +#define GUARD 5 // safety guard of this many samples + +#define MAX_AP_TIME (int) ((20*65536)/1000) // delay time in time units (65536th of sec) +#define MAX_DELAY_TIME (int) ((65*65536)/1000) // delay time in time units +#define MAX_EARLY_TIME (int) ((65*65536)/1000) // delay time in time units + +#define AP0_IN 0 + + +#define REVERB_DEFAULT_ROOM_NUMBER 1 // default preset number +#define DEFAULT_AP0_GAIN 19400 +#define DEFAULT_AP1_GAIN -19400 + +#define REVERB_DEFAULT_WET 32767 +#define REVERB_DEFAULT_DRY 0 + +#define REVERB_WET_MAX 32767 +#define REVERB_WET_MIN 0 +#define REVERB_DRY_MAX 32767 +#define REVERB_DRY_MIN 0 + +// constants for reverb density +// The density expressed in permilles changes the Allpass delay in a linear manner in the range defined by +// AP0_TIME_BASE to AP0_TIME_BASE + AP0_TIME_RANGE +#define AP0_TIME_BASE (int)((9*65536)/1000) +#define AP0_TIME_RANGE (int)((4*65536)/1000) +#define AP1_TIME_BASE (int)((12*65536)/1000) +#define AP1_TIME_RANGE (int)((8*65536)/1000) + +// constants for reverb diffusion +// The diffusion expressed in permilles changes the Allpass gain in a linear manner in the range defined by +// AP0_GAIN_BASE to AP0_GAIN_BASE + AP0_GAIN_RANGE +#define AP0_GAIN_BASE (int)(9830) +#define AP0_GAIN_RANGE (int)(19660-9830) +#define AP1_GAIN_BASE (int)(6553) +#define AP1_GAIN_RANGE (int)(22936-6553) + + +/* parameters for each allpass */ +typedef struct +{ + uint16_t m_zApOut; // delay offset for ap out + + int16_t m_nApGain; // gain for ap + + uint16_t m_zApIn; // delay offset for ap in + +} allpass_object_t; + + +/* parameters for early reflections */ +typedef struct +{ + uint16_t m_zDelay[REVERB_MAX_NUM_REFLECTIONS]; // delay offset for ap out + + int16_t m_nGain[REVERB_MAX_NUM_REFLECTIONS]; // gain for ap + +} early_reflection_object_t; + +//demo +typedef struct +{ + int16_t m_nRvbLpfFbk; + int16_t m_nRvbLpfFwd; + int16_t m_nRoomLpfFbk; + int16_t m_nRoomLpfFwd; + + int16_t m_nEarlyGain; + int16_t m_nEarlyDelay; + int16_t m_nLateGain; + int16_t m_nLateDelay; + + early_reflection_object_t m_sEarlyL; + early_reflection_object_t m_sEarlyR; + + uint16_t m_nMaxExcursion; //28 + int16_t m_nXfadeInterval; + + int16_t m_nAp0_ApGain; //30 + int16_t m_nAp0_ApOut; + int16_t m_nAp1_ApGain; + int16_t m_nAp1_ApOut; + int16_t m_nDiffusion; + + int16_t m_rfu4; + int16_t m_rfu5; + int16_t m_rfu6; + int16_t m_rfu7; + int16_t m_rfu8; + int16_t m_rfu9; + int16_t m_rfu10; //43 + +} reverb_preset_t; + +typedef struct +{ + reverb_preset_t m_sPreset[REVERB_MAX_ROOM_TYPE]; //array of presets + +} reverb_preset_bank_t; + + +/* parameters for each reverb */ +typedef struct +{ + /* update counter keeps track of when synth params need updating */ + /* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */ + int16_t m_nUpdateCounter; + + uint16_t m_nBaseIndex; // base index for circular buffer + + // reverb delay line offsets, allpass parameters, etc: + + short m_nRevFbkR; // combine feedback reverb right out with dry left in + short m_zOutLpfL; // left reverb output + + allpass_object_t m_sAp0; // allpass 0 (left channel) + + uint16_t m_zD0In; // delay offset for delay line D0 in + + short m_nRevFbkL; // combine feedback reverb left out with dry right in + short m_zOutLpfR; // right reverb output + + allpass_object_t m_sAp1; // allpass 1 (right channel) + + uint16_t m_zD1In; // delay offset for delay line D1 in + + // delay output taps, notice criss cross order + uint16_t m_zD0Self; // self feeds forward d0 --> d0 + + uint16_t m_zD1Cross; // cross feeds across d1 --> d0 + + uint16_t m_zD1Self; // self feeds forward d1 --> d1 + + uint16_t m_zD0Cross; // cross feeds across d0 --> d1 + + int16_t m_nSin; // gain for self taps + + int16_t m_nCos; // gain for cross taps + + int16_t m_nSinIncrement; // increment for gain + + int16_t m_nCosIncrement; // increment for gain + + int16_t m_nRvbLpfFwd; // reverb feedback lpf forward gain (includes scaling for mixer) + + int16_t m_nRvbLpfFbk; // reverb feedback lpf feedback gain + + int16_t m_nRoomLpfFwd; // room lpf forward gain (includes scaling for mixer) + + int16_t m_nRoomLpfFbk; // room lpf feedback gain + + uint16_t m_nXfadeInterval; // update/xfade after this many samples + + uint16_t m_nXfadeCounter; // keep track of when to xfade + + int16_t m_nPhase; // -1 <= m_nPhase < 1 + // but during sin,cos calculations + // use m_nPhase/2 + + int16_t m_nPhaseIncrement; // add this to m_nPhase each frame + + int16_t m_nNoise; // random noise sample + + uint16_t m_nMaxExcursion; // the taps can excurse +/- this amount + + uint16_t m_bUseNoise; // if TRUE, use noise as input signal + + uint16_t m_bBypass; // if TRUE, then bypass reverb and copy input to output + + int16_t m_nCurrentRoom; // preset number for current room + + int16_t m_nNextRoom; // preset number for next room + + int16_t m_nEarlyGain; // gain for early (widen) signal + int16_t m_nEarlyDelay; // initial dealy for early (widen) signal + int16_t m_nEarly0in; + int16_t m_nEarly1in; + int16_t m_nLateGain; // gain for late reverb + int16_t m_nLateDelay; + + int16_t m_nDiffusion; + + early_reflection_object_t m_sEarlyL; // left channel early reflections + early_reflection_object_t m_sEarlyR; // right channel early reflections + + short m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES_MAX]; // one large delay line for all reverb elements + + reverb_preset_t pPreset; + + reverb_preset_bank_t m_sPreset; + + //int8_t preset; + uint32_t m_nSamplingRate; + int32_t m_nUpdatePeriodInBits; + int32_t m_nBufferMask; + int32_t m_nUpdatePeriodInSamples; + int32_t m_nDelay0Out; + int32_t m_nDelay1Out; + int16_t m_nCosWT_5KHz; + + uint16_t m_Aux; // if TRUE, is connected as auxiliary effect + uint16_t m_Preset; // if TRUE, expose preset revert interface + +} reverb_object_t; + + + +typedef struct reverb_module_s { + const struct effect_interface_s *itfe; + effect_config_t config; + reverb_object_t context; +} reverb_module_t; + +/*------------------------------------ + * Effect API + *------------------------------------ +*/ +int EffectQueryNumberEffects(int *pNumEffects); +int EffectQueryNext(effect_descriptor_t *pDescriptor); +int EffectCreate(effect_uuid_t *effectUID, effect_interface_t *pInterface); +int EffectRelease(effect_interface_t interface); + +static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer); +static int Reverb_Command(effect_interface_t self, int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData); + + +/*------------------------------------ + * internal functions + *------------------------------------ +*/ + +int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset); +int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig, bool init); +void Reverb_Reset(reverb_object_t *pReverb, bool init); + +int Reverb_setParameter (reverb_object_t *pReverb, int32_t param, size_t size, void *pValue); +int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, void *pValue); + +/*---------------------------------------------------------------------------- + * ReverbUpdateXfade + *---------------------------------------------------------------------------- + * Purpose: + * Update the xfade parameters as required + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * + * + * Side Effects: + * - xfade parameters will be changed + * + *---------------------------------------------------------------------------- +*/ +static int ReverbUpdateXfade(reverb_object_t* pReverbData, int nNumSamplesToAdd); + +/*---------------------------------------------------------------------------- + * ReverbCalculateNoise + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a noise sample and limit its value + * + * Inputs: + * Pointer to reverb context + * + * Outputs: + * new limited noise value + * + * Side Effects: + * - pReverbData->m_nNoise value is updated + * + *---------------------------------------------------------------------------- +*/ +static uint16_t ReverbCalculateNoise(reverb_object_t *pReverbData); + +/*---------------------------------------------------------------------------- + * ReverbCalculateSinCos + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a new sin and cosine value based on the given phase + * + * Inputs: + * nPhase - phase angle + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * + * Side Effects: + * - *pnSin, *pnCos are updated + * + *---------------------------------------------------------------------------- +*/ +static int ReverbCalculateSinCos(int16_t nPhase, int16_t *pnSin, int16_t *pnCos); + +/*---------------------------------------------------------------------------- + * Reverb + *---------------------------------------------------------------------------- + * Purpose: + * apply reverb to the given signal + * + * Inputs: + * nNu + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * number of samples actually reverberated + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static int Reverb(reverb_object_t* pReverbData, int nNumSamplesToAdd, short *pOutputBuffer, short *pInputBuffer); + +/*---------------------------------------------------------------------------- + * ReverbReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global reverb preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static int ReverbReadInPresets(reverb_object_t* pReverbData); + + +/*---------------------------------------------------------------------------- + * ReverbUpdateRoom + *---------------------------------------------------------------------------- + * Purpose: + * Update the room's preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - reverb paramters (fbk, fwd, etc) will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- +*/ +static int ReverbUpdateRoom(reverb_object_t* pReverbData, bool fullUpdate); + + +static int ReverbComputeConstants(reverb_object_t *pReverbData, uint32_t samplingRate); + +#endif /*ANDROID_EFFECTREVERB_H_*/ diff --git a/media/libeffects/EffectsFactory.c b/media/libeffects/EffectsFactory.c new file mode 100644 index 0000000000000000000000000000000000000000..35a100108dc966c52d4ee51783199edd3e45b1f0 --- /dev/null +++ b/media/libeffects/EffectsFactory.c @@ -0,0 +1,604 @@ +/* + * Copyright (C) 2010 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. + */ + +#define LOG_TAG "EffectsFactory" +//#define LOG_NDEBUG 0 + +#include "EffectsFactory.h" +#include +#include +#include + + +static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects +static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries +static pthread_mutex_t gLibLock = PTHREAD_MUTEX_INITIALIZER; // controls access to gLibraryList +static list_elem_t *gCurLib; // current library in enumeration process +static list_elem_t *gCurEffect; // current effect in enumeration process + +static const char * const gEffectLibPath = "/system/lib/soundfx"; // path to built-in effect libraries +static int gInitDone; // true is global initialization has been preformed + +///////////////////////////////////////////////// +// Local functions prototypes +///////////////////////////////////////////////// + +static int init(); +static int loadLibrary(const char *libPath, int *handle); +static int unloadLibrary(int handle); +static int numEffectModules(); +static int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc); +static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len); + +///////////////////////////////////////////////// +// Effect Control Interface functions +///////////////////////////////////////////////// + +int Effect_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) +{ + int ret = init(); + if (ret < 0) { + return ret; + } + effect_entry_t *fx = (effect_entry_t *)self; + pthread_mutex_lock(&gLibLock); + if (fx->lib == NULL) { + pthread_mutex_unlock(&gLibLock); + return -EPIPE; + } + pthread_mutex_lock(&fx->lib->lock); + pthread_mutex_unlock(&gLibLock); + + ret = (*fx->subItfe)->process(fx->subItfe, inBuffer, outBuffer); + pthread_mutex_unlock(&fx->lib->lock); + return ret; +} + +int Effect_Command(effect_interface_t self, int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData) +{ + int ret = init(); + if (ret < 0) { + return ret; + } + effect_entry_t *fx = (effect_entry_t *)self; + pthread_mutex_lock(&gLibLock); + if (fx->lib == NULL) { + pthread_mutex_unlock(&gLibLock); + return -EPIPE; + } + pthread_mutex_lock(&fx->lib->lock); + pthread_mutex_unlock(&gLibLock); + + ret = (*fx->subItfe)->command(fx->subItfe, cmdCode, cmdSize, pCmdData, replySize, pReplyData); + pthread_mutex_unlock(&fx->lib->lock); + return ret; +} + +const struct effect_interface_s gInterface = { + Effect_Process, + Effect_Command +}; + +///////////////////////////////////////////////// +// Effect Factory Interface functions +///////////////////////////////////////////////// + +int EffectQueryNumberEffects(int *pNumEffects) +{ + int ret = init(); + if (ret < 0) { + return ret; + } + if (pNumEffects == NULL) { + return -EINVAL; + } + + pthread_mutex_lock(&gLibLock); + *pNumEffects = numEffectModules(); + pthread_mutex_unlock(&gLibLock); + LOGV("EffectQueryNumberEffects(): %d", *pNumEffects); + return ret; +} + +int EffectQueryNext(effect_descriptor_t *pDescriptor) +{ + int ret = init(); + if (ret < 0) { + return ret; + } + if (pDescriptor == NULL) { + return -EINVAL; + } + + pthread_mutex_lock(&gLibLock); + ret = -ENOENT; + while (gCurLib) { + if (gCurEffect) { + memcpy(pDescriptor, gCurEffect->object, sizeof(effect_descriptor_t)); + gCurEffect = gCurEffect->next; + ret = 0; + break; + } else { + gCurLib = gCurLib->next; + gCurEffect = ((lib_entry_t *)gCurLib->object)->effects; + } + } + char str[256]; + dumpEffectDescriptor(pDescriptor, str, 256); + LOGV("EffectQueryNext() desc:%s", str); + pthread_mutex_unlock(&gLibLock); + return ret; +} + +int EffectGetDescriptor(effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) +{ + lib_entry_t *l = NULL; + effect_descriptor_t *d = NULL; + + int ret = init(); + if (ret < 0) { + return ret; + } + if (pDescriptor == NULL || uuid == NULL) { + return -EINVAL; + } + pthread_mutex_lock(&gLibLock); + ret = findEffect(uuid, &l, &d); + if (ret == 0) { + memcpy(pDescriptor, d, sizeof(effect_descriptor_t)); + } + pthread_mutex_unlock(&gLibLock); + return ret; +} + +int EffectCreate(effect_uuid_t *uuid, effect_interface_t *pInterface) +{ + list_elem_t *e = gLibraryList; + lib_entry_t *l = NULL; + effect_descriptor_t *d = NULL; + effect_interface_t itfe; + effect_entry_t *fx; + int found = 0; + int ret; + + if (uuid == NULL || pInterface == NULL) { + return -EINVAL; + } + + LOGV("EffectCreate() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n", + uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion, + uuid->clockSeq, uuid->node[0], uuid->node[1],uuid->node[2], + uuid->node[3],uuid->node[4],uuid->node[5]); + + ret = init(); + + if (ret < 0) { + LOGW("EffectCreate() init error: %d", ret); + return ret; + } + + pthread_mutex_lock(&gLibLock); + + ret = findEffect(uuid, &l, &d); + if (ret < 0){ + goto exit; + } + + // create effect in library + ret = l->createFx(uuid, &itfe); + if (ret < 0) { + LOGW("EffectCreate() library %s: could not create fx %s", l->path, d->name); + goto exit; + } + + // add entry to effect list + fx = (effect_entry_t *)malloc(sizeof(effect_entry_t)); + fx->subItfe = itfe; + fx->itfe = (struct effect_interface_s *)&gInterface; + fx->lib = l; + + e = (list_elem_t *)malloc(sizeof(list_elem_t)); + e->object = fx; + e->next = gEffectList; + gEffectList = e; + + *pInterface = (effect_interface_t)fx; + + LOGV("EffectCreate() created entry %p with sub itfe %p in library %s", *pInterface, itfe, l->path); + +exit: + pthread_mutex_unlock(&gLibLock); + return ret; +} + +int EffectRelease(effect_interface_t interface) +{ + effect_entry_t *fx; + list_elem_t *e1; + list_elem_t *e2; + + int ret = init(); + if (ret < 0) { + return ret; + } + + // remove effect from effect list + pthread_mutex_lock(&gLibLock); + e1 = gEffectList; + e2 = NULL; + while (e1) { + if (e1->object == interface) { + if (e2) { + e2->next = e1->next; + } else { + gEffectList = e1->next; + } + fx = (effect_entry_t *)e1->object; + free(e1); + break; + } + e2 = e1; + e1 = e1->next; + } + if (e1 == NULL) { + ret = -ENOENT; + goto exit; + } + + // release effect in library + if (fx->lib == NULL) { + LOGW("EffectRelease() fx %p library already unloaded", interface); + } else { + pthread_mutex_lock(&fx->lib->lock); + fx->lib->releaseFx(fx->subItfe); + pthread_mutex_unlock(&fx->lib->lock); + } + free(fx); + +exit: + pthread_mutex_unlock(&gLibLock); + return ret; +} + +int EffectLoadLibrary(const char *libPath, int *handle) +{ + int ret = init(); + if (ret < 0) { + return ret; + } + if (libPath == NULL) { + return -EINVAL; + } + return loadLibrary(libPath, handle); +} + +int EffectUnloadLibrary(int handle) +{ + int ret = init(); + if (ret < 0) { + return ret; + } + + return unloadLibrary(handle); +} + +int EffectIsNullUuid(effect_uuid_t *uuid) +{ + if (memcmp(uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t))) { + return 0; + } + return 1; +} + +///////////////////////////////////////////////// +// Local functions +///////////////////////////////////////////////// + +int init() { + struct dirent *ent; + DIR *dir = NULL; + char libpath[PATH_MAX]; + int hdl; + + if (gInitDone) { + return 0; + } + + pthread_mutex_init(&gLibLock, NULL); + + // load built-in libraries + dir = opendir(gEffectLibPath); + if (dir == NULL) { + return -ENODEV; + } + while ((ent = readdir(dir)) != NULL) { + LOGV("init() reading file %s", ent->d_name); + if ((strlen(ent->d_name) < 3) || + strncmp(ent->d_name, "lib", 3) != 0 || + strncmp(ent->d_name + strlen(ent->d_name) - 3, ".so", 3) != 0) { + continue; + } + strcpy(libpath, gEffectLibPath); + strcat(libpath, "/"); + strcat(libpath, ent->d_name); + if (loadLibrary(libpath, &hdl) < 0) { + LOGW("init() failed to load library %s",libpath); + } + } + closedir(dir); + + gInitDone = 1; + LOGV("init() done"); + return 0; +} + + +int loadLibrary(const char *libPath, int *handle) +{ + void *hdl; + effect_QueryNumberEffects_t queryNumFx; + effect_QueryNextEffect_t queryFx; + effect_CreateEffect_t createFx; + effect_ReleaseEffect_t releaseFx; + int numFx; + int fx; + int ret; + list_elem_t *e, *descHead = NULL; + lib_entry_t *l; + + if (handle == NULL) { + return -EINVAL; + } + + *handle = 0; + + hdl = dlopen(libPath, RTLD_NOW); + if (hdl == 0) { + LOGW("could open lib %s", libPath); + return -ENODEV; + } + + // Check functions availability + queryNumFx = (effect_QueryNumberEffects_t)dlsym(hdl, "EffectQueryNumberEffects"); + if (queryNumFx == NULL) { + LOGW("could not get EffectQueryNumberEffects from lib %s", libPath); + ret = -ENODEV; + goto error; + } + queryFx = (effect_QueryNextEffect_t)dlsym(hdl, "EffectQueryNext"); + if (queryFx == NULL) { + LOGW("could not get EffectQueryNext from lib %s", libPath); + ret = -ENODEV; + goto error; + } + createFx = (effect_CreateEffect_t)dlsym(hdl, "EffectCreate"); + if (createFx == NULL) { + LOGW("could not get EffectCreate from lib %s", libPath); + ret = -ENODEV; + goto error; + } + releaseFx = (effect_ReleaseEffect_t)dlsym(hdl, "EffectRelease"); + if (releaseFx == NULL) { + LOGW("could not get EffectRelease from lib %s", libPath); + ret = -ENODEV; + goto error; + } + + // load effect descriptors + ret = queryNumFx(&numFx); + if (ret) { + goto error; + } + + for (fx = 0; fx < numFx; fx++) { + effect_descriptor_t *d = malloc(sizeof(effect_descriptor_t)); + if (d == NULL) { + ret = -ENOMEM; + goto error; + } + ret = queryFx(d); + if (ret == 0) { +#if (LOG_NDEBUG==0) + char s[256]; + dumpEffectDescriptor(d, s, 256); + LOGV("loadLibrary() read descriptor %p:%s",d, s); +#endif + if (d->apiVersion != EFFECT_API_VERSION) { + LOGW("Bad API version %04x on lib %s", d->apiVersion, libPath); + free(d); + continue; + } + e = malloc(sizeof(list_elem_t)); + if (e == NULL) { + free(d); + ret = -ENOMEM; + goto error; + } + e->object = d; + e->next = descHead; + descHead = e; + } else { + LOGW("Error querying effect # %d on lib %s", fx, libPath); + } + } + // add entry for library in gLibraryList + l = malloc(sizeof(lib_entry_t)); + l->handle = hdl; + strncpy(l->path, libPath, PATH_MAX); + l->createFx = createFx; + l->releaseFx = releaseFx; + l->effects = descHead; + pthread_mutex_init(&l->lock, NULL); + + e = malloc(sizeof(list_elem_t)); + pthread_mutex_lock(&gLibLock); + e->next = gLibraryList; + e->object = l; + gLibraryList = e; + pthread_mutex_unlock(&gLibLock); + LOGV("loadLibrary() linked library %p", l); + + *handle = (int)hdl; + + return 0; + +error: + LOGW("loadLibrary() error: %d on lib: %s", ret, libPath); + while (descHead) { + free(descHead->object); + e = descHead->next; + free(descHead); + descHead = e;; + } + dlclose(hdl); + return ret; +} + +int unloadLibrary(int handle) +{ + void *hdl; + int ret; + list_elem_t *el1, *el2; + lib_entry_t *l; + effect_entry_t *fx; + + pthread_mutex_lock(&gLibLock); + el1 = gLibraryList; + el2 = NULL; + while (el1) { + l = (lib_entry_t *)el1->object; + if (handle == (int)l->handle) { + if (el2) { + el2->next = el1->next; + } else { + gLibraryList = el1->next; + } + free(el1); + break; + } + el2 = el1; + el1 = el1->next; + } + pthread_mutex_unlock(&gLibLock); + if (el1 == NULL) { + return -ENOENT; + } + + // clear effect descriptor list + el1 = l->effects; + while (el1) { + free(el1->object); + el2 = el1->next; + free(el1); + el1 = el2; + } + + // disable all effects from this library + pthread_mutex_lock(&l->lock); + el1 = gEffectList; + while (el1) { + fx = (effect_entry_t *)el1->object; + if (fx->lib == l) { + fx->lib = NULL; + } + el1 = el1->next; + } + pthread_mutex_unlock(&l->lock); + + dlclose(l->handle); + free(l); + return 0; +} + + + +int numEffectModules() { + list_elem_t *e = gLibraryList; + int cnt = 0; + + // Reset pointers for EffectQueryNext() + gCurLib = e; + if (e) { + gCurEffect = ((lib_entry_t *)e->object)->effects; + } + while (e) { + lib_entry_t *l = (lib_entry_t *)e->object; + list_elem_t *efx = l->effects; + while (efx) { + cnt++; + efx = efx->next; + } + e = e->next; + } + return cnt; +} + +int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc) +{ + list_elem_t *e = gLibraryList; + lib_entry_t *l = NULL; + effect_descriptor_t *d = NULL; + int found = 0; + int ret = 0; + + while (e && !found) { + l = (lib_entry_t *)e->object; + list_elem_t *efx = l->effects; + while (efx) { + d = (effect_descriptor_t *)efx->object; + if (memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) { + found = 1; + break; + } + efx = efx->next; + } + e = e->next; + } + if (!found) { + LOGV("findEffect() effect not found"); + ret = -ENOENT; + } else { + LOGV("findEffect() found effect: %s in lib %s", d->name, l->path); + *lib = l; + *desc = d; + } + + return ret; +} + +void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len) { + char s[256]; + + snprintf(str, len, "\nEffect Descriptor %p:\n", desc); + sprintf(s, "- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n", + desc->uuid.timeLow, desc->uuid.timeMid, desc->uuid.timeHiAndVersion, + desc->uuid.clockSeq, desc->uuid.node[0], desc->uuid.node[1],desc->uuid.node[2], + desc->uuid.node[3],desc->uuid.node[4],desc->uuid.node[5]); + strncat(str, s, len); + sprintf(s, "- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n", + desc->type.timeLow, desc->type.timeMid, desc->type.timeHiAndVersion, + desc->type.clockSeq, desc->type.node[0], desc->type.node[1],desc->type.node[2], + desc->type.node[3],desc->type.node[4],desc->type.node[5]); + strncat(str, s, len); + sprintf(s, "- apiVersion: %04X\n- flags: %08X\n", + desc->apiVersion, desc->flags); + strncat(str, s, len); + sprintf(s, "- name: %s\n", desc->name); + strncat(str, s, len); + sprintf(s, "- implementor: %s\n", desc->implementor); + strncat(str, s, len); +} + diff --git a/media/libeffects/EffectsFactory.h b/media/libeffects/EffectsFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..17ad3f01681be701d12a028cf54b0668f37c04b7 --- /dev/null +++ b/media/libeffects/EffectsFactory.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010 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 ANDROID_EFFECTSFACTORY_H_ +#define ANDROID_EFFECTSFACTORY_H_ + +#include +#include +#include +#include + + +#if __cplusplus +extern "C" { +#endif + +typedef struct list_elem_s { + void *object; + struct list_elem_s *next; +} list_elem_t; + +typedef struct lib_entry_s { + char path[PATH_MAX]; + void *handle; + effect_CreateEffect_t createFx; + effect_ReleaseEffect_t releaseFx; + list_elem_t *effects; //list of effect_descriptor_t + pthread_mutex_t lock; +} lib_entry_t; + +typedef struct effect_entry_s { + struct effect_interface_s *itfe; + effect_interface_t subItfe; + lib_entry_t *lib; +} effect_entry_t; + +#if __cplusplus +} // extern "C" +#endif + + +#endif /*ANDROID_EFFECTSFACTORY_H_*/ diff --git a/media/libeffects/EffectsMath.c b/media/libeffects/EffectsMath.c new file mode 100644 index 0000000000000000000000000000000000000000..41ec66252b6fbfea4bcbe0ae32eb5bd217f7b76f --- /dev/null +++ b/media/libeffects/EffectsMath.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2008 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. + */ +#define LOG_TAG "EFFECTSMATH" +//#define LOG_NDEBUG 0 +#include +#include + +#include "EffectsMath.h" + +// gLogTab contains pre-calculated values of log2(1 + ai5*2^-1 + ai4*2^-2 + ai3*2^-3 + ai2*2^-4 + ai1*2^-5 + ai0*2^-6) +// for integers in the range 0 to 63 (i = ai5*2^5 + ai4*2^4 + ai3*2^3 + ai2*2^2 + ai1*2^1 + ai0*2^0) +// It is used for a better than piece wise approximation of lin to log2 conversion + +static const uint16_t gLogTab[] = +{ + 0, 733, 1455, 2166, + 2866, 3556, 4236, 4907, + 5568, 6220, 6863, 7498, + 8124, 8742, 9352, 9954, + 10549, 11136, 11716, 12289, + 12855, 13415, 13968, 14514, + 15055, 15589, 16117, 16639, + 17156, 17667, 18173, 18673, + 19168, 19658, 20143, 20623, + 21098, 21568, 22034, 22495, + 22952, 23404, 23852, 24296, + 24736, 25172, 25604, 26031, + 26455, 26876, 27292, 27705, + 28114, 28520, 28922, 29321, + 29717, 30109, 30498, 30884, + 31267, 31647, 32024, 32397, + 32768 +}; + +int32_t Effects_log2(uint32_t x) { + int32_t exp = 31 - __builtin_clz(x); + uint32_t segStart = x >> (exp - 6); + uint32_t i = segStart & 0x3F; + int32_t log = (int32_t)gLogTab[i]; + int32_t logEnd = (int32_t)gLogTab[i+1]; + segStart <<= exp - 6; + + return (exp << 15) + log + (((x - segStart) * (logEnd - log)) >> (exp - 6)); +} + +// gExpTab[i] = (2^(i>>6)) << 22 +static const uint32_t gExpTab[] = { + 4194304, 4239977, 4286147, 4332820, + 4380002, 4427697, 4475911, 4524651, + 4573921, 4623728, 4674077, 4724974, + 4776426, 4828438, 4881016, 4934167, + 4987896, 5042211, 5097117, 5152621, + 5208729, 5265449, 5322786, 5380747, + 5439339, 5498570, 5558445, 5618973, + 5680159, 5742012, 5804539, 5867746, + 5931642, 5996233, 6061528, 6127533, + 6194258, 6261709, 6329894, 6398822, + 6468501, 6538938, 6610143, 6682122, + 6754886, 6828442, 6902799, 6977965, + 7053950, 7130763, 7208412, 7286906, + 7366255, 7446469, 7527555, 7609525, + 7692387, 7776152, 7860829, 7946428, + 8032959, 8120432, 8208857, 8298246, + 8388608 +}; + + +uint32_t Effects_exp2(int32_t x) { + int32_t i = x >> 15; + assert(i < 32); + x &= (1 << 15) - 1; + int32_t j = x >> 9; + x &= (1 << 9) - 1; + uint32_t exp = gExpTab[j]; + uint32_t expEnd = gExpTab[j+1]; + + return ((exp << 9) + (expEnd - exp) * x) >> (31 - i); +} + + +int16_t Effects_MillibelsToLinear16 (int32_t nGain) +{ + nGain = ((nGain + MB_TO_LIN_K1) << 15 ) / MB_TO_LIN_K2; + uint32_t exp2 = Effects_exp2(nGain); + + if (exp2 > 32767) exp2 = 32767; + + return (int16_t)exp2; +} + + +int16_t Effects_Linear16ToMillibels (int32_t nGain) +{ + return (int16_t)(((MB_TO_LIN_K2*Effects_log2(nGain))>>15)-MB_TO_LIN_K1); +} + + +int32_t Effects_Sqrt(int32_t in) +{ + int32_t tmp; + int32_t out = 0; + int32_t i; + int32_t j; + + + if (in == 0) return 0; + + if (in >= 0x10000000) + { + out = 0x4000; + in -= 0x10000000; + } + + j = 32 - __builtin_clz(in); + + if (j & 1) j++; + j >>= 1; + + for (i = j; i > 0; i--) { + tmp = (out << i) + (1 << ((i - 1)*2)); + if (in >= tmp) + { + out += 1 << (i-1); + in -= tmp; + } + } + + return out; +} + diff --git a/media/libeffects/EffectsMath.h b/media/libeffects/EffectsMath.h new file mode 100644 index 0000000000000000000000000000000000000000..2a44399e3f77988c3379244da7d0b28a823755ad --- /dev/null +++ b/media/libeffects/EffectsMath.h @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2008 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 ANDROID_EFFECTSMATH_H_ +#define ANDROID_EFFECTSMATH_H_ + +#include + +#if __cplusplus +extern "C" { +#endif + +/** coefs for pan, generates sin, cos */ +#define COEFF_PAN_G2 -27146 /* -0.82842712474619 = 2 - 4/sqrt(2) */ +#define COEFF_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ + +/* +coefficients for approximating +2^x = gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3 +where x is a int.frac number representing number of octaves. +Actually, we approximate only the 2^(frac) using the power series +and implement the 2^(int) as a shift, so that +2^x == 2^(int.frac) == 2^(int) * 2^(fract) + == (gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3) << (int) + +The gn2toX.. were generated using a best fit for a 3rd +order polynomial, instead of taking the coefficients from +a truncated Taylor (or Maclaurin?) series. +*/ + +#define GN2_TO_X0 32768 /* 1 */ +#define GN2_TO_X1 22833 /* 0.696807861328125 */ +#define GN2_TO_X2 7344 /* 0.22412109375 */ +#define GN2_TO_X3 2588 /* 0.0789794921875 */ + +/*---------------------------------------------------------------------------- + * Fixed Point Math + *---------------------------------------------------------------------------- + * These macros are used for fixed point multiplies. If the processor + * supports fixed point multiplies, replace these macros with inline + * assembly code to improve performance. + *---------------------------------------------------------------------------- +*/ + +/* Fixed point multiply 0.15 x 0.15 = 0.15 returned as 32-bits */ +#define FMUL_15x15(a,b) \ + /*lint -e(704) */ \ + (((int32_t)(a) * (int32_t)(b)) >> 15) + +/* Fixed point multiply 0.7 x 0.7 = 0.15 returned as 32-bits */ +#define FMUL_7x7(a,b) \ + /*lint -e(704) */ \ + (((int32_t)(a) * (int32_t)(b) ) << 1) + +/* Fixed point multiply 0.8 x 0.8 = 0.15 returned as 32-bits */ +#define FMUL_8x8(a,b) \ + /*lint -e(704) */ \ + (((int32_t)(a) * (int32_t)(b) ) >> 1) + +/* Fixed point multiply 0.8 x 1.15 = 0.15 returned as 32-bits */ +#define FMUL_8x15(a,b) \ + /*lint -e(704) */ \ + (((int32_t)((a) << 7) * (int32_t)(b)) >> 15) + +/* macros for fractional phase accumulator */ +/* +Note: changed the _U32 to _I32 on 03/14/02. This should not +affect the phase calculations, and should allow us to reuse these +macros for other audio sample related math. +*/ +#define HARDWARE_BIT_WIDTH 32 + +#define NUM_PHASE_INT_BITS 1 +#define NUM_PHASE_FRAC_BITS 15 + +#define PHASE_FRAC_MASK (uint32_t) ((0x1L << NUM_PHASE_FRAC_BITS) -1) + +#define GET_PHASE_INT_PART(x) (uint32_t)((uint32_t)(x) >> NUM_PHASE_FRAC_BITS) +#define GET_PHASE_FRAC_PART(x) (uint32_t)((uint32_t)(x) & PHASE_FRAC_MASK) + +#define DEFAULT_PHASE_FRAC 0 +#define DEFAULT_PHASE_INT 0 + +/* +Linear interpolation calculates: +output = (1-frac) * sample[n] + (frac) * sample[n+1] + +where conceptually 0 <= frac < 1 + +For a fixed point implementation, frac is actually an integer value +with an implied binary point one position to the left. The value of +one (unity) is given by PHASE_ONE +one half and one quarter are useful for 4-point linear interp. +*/ +#define PHASE_ONE (int32_t) (0x1L << NUM_PHASE_FRAC_BITS) + +/* + Multiply the signed audio sample by the unsigned fraction. +- a is the signed audio sample +- b is the unsigned fraction (cast to signed int as long as coef + uses (n-1) or less bits, where n == hardware bit width) +*/ +#define MULT_AUDIO_COEF(audio,coef) /*lint -e704 */ \ + (int32_t)( \ + ( \ + ((int32_t)(audio)) * ((int32_t)(coef)) \ + ) \ + >> NUM_PHASE_FRAC_BITS \ + ) \ + /* lint +704 */ + +/* wet / dry calculation macros */ +#define NUM_WET_DRY_FRAC_BITS 7 // 15 +#define NUM_WET_DRY_INT_BITS 9 // 1 + +/* define a 1.0 */ +#define WET_DRY_ONE (int32_t) ((0x1L << NUM_WET_DRY_FRAC_BITS)) +#define WET_DRY_MINUS_ONE (int32_t) (~WET_DRY_ONE) +#define WET_DRY_FULL_SCALE (int32_t) (WET_DRY_ONE - 1) + +#define MULT_AUDIO_WET_DRY_COEF(audio,coef) /*lint -e(702) */ \ + (int32_t)( \ + ( \ + ((int32_t)(audio)) * ((int32_t)(coef)) \ + ) \ + >> NUM_WET_DRY_FRAC_BITS \ + ) + +/* Envelope 1 (EG1) calculation macros */ +#define NUM_EG1_INT_BITS 1 +#define NUM_EG1_FRAC_BITS 15 + +/* the max positive gain used in the synth for EG1 */ +/* SYNTH_FULL_SCALE_EG1_GAIN must match the value in the dls2eas +converter, otherwise, the values we read from the .eas file are bogus. */ +#define SYNTH_FULL_SCALE_EG1_GAIN (int32_t) ((0x1L << NUM_EG1_FRAC_BITS) -1) + +/* define a 1.0 */ +#define EG1_ONE (int32_t) ((0x1L << NUM_EG1_FRAC_BITS)) +#define EG1_MINUS_ONE (int32_t) (~SYNTH_FULL_SCALE_EG1_GAIN) + +#define EG1_HALF (int32_t) (EG1_ONE/2) +#define EG1_MINUS_HALF (int32_t) (EG1_MINUS_ONE/2) + +/* +We implement the EG1 using a linear gain value, which means that the +attack segment is handled by incrementing (adding) the linear gain. +However, EG1 treats the Decay, Sustain, and Release differently than +the Attack portion. For Decay, Sustain, and Release, the gain is +linear on dB scale, which is equivalent to exponential damping on +a linear scale. Because we use a linear gain for EG1, we implement +the Decay and Release as multiplication (instead of incrementing +as we did for the attack segment). +Therefore, we need the following macro to implement the multiplication +(i.e., exponential damping) during the Decay and Release segments of +the EG1 +*/ +#define MULT_EG1_EG1(gain,damping) /*lint -e(704) */ \ + (int32_t)( \ + ( \ + ((int32_t)(gain)) * ((int32_t)(damping)) \ + ) \ + >> NUM_EG1_FRAC_BITS \ + ) + +// Use the following macro specifically for the filter, when multiplying +// the b1 coefficient. The 0 <= |b1| < 2, which therefore might overflow +// in certain conditions because we store b1 as a 1.15 value. +// Instead, we could store b1 as b1p (b1' == b1 "prime") where +// b1p == b1/2, thus ensuring no potential overflow for b1p because +// 0 <= |b1p| < 1 +// However, during the filter calculation, we must account for the fact +// that we are using b1p instead of b1, and thereby multiply by +// an extra factor of 2. Rather than multiply by an extra factor of 2, +// we can instead shift the result right by one less, hence the +// modified shift right value of (NUM_EG1_FRAC_BITS -1) +#define MULT_EG1_EG1_X2(gain,damping) /*lint -e(702) */ \ + (int32_t)( \ + ( \ + ((int32_t)(gain)) * ((int32_t)(damping)) \ + ) \ + >> (NUM_EG1_FRAC_BITS -1) \ + ) + +#define SATURATE_EG1(x) /*lint -e{734} saturation operation */ \ + ((int32_t)(x) > SYNTH_FULL_SCALE_EG1_GAIN) ? (SYNTH_FULL_SCALE_EG1_GAIN) : \ + ((int32_t)(x) < EG1_MINUS_ONE) ? (EG1_MINUS_ONE) : (x); + + +/* use "digital cents" == "dents" instead of cents */ +/* we coudl re-use the phase frac macros, but if we do, +we must change the phase macros to cast to _I32 instead of _U32, +because using a _U32 cast causes problems when shifting the exponent +for the 2^x calculation, because right shift a negative values MUST +be sign extended, or else the 2^x calculation is wrong */ + +/* use "digital cents" == "dents" instead of cents */ +#define NUM_DENTS_FRAC_BITS 12 +#define NUM_DENTS_INT_BITS (HARDWARE_BIT_WIDTH - NUM_DENTS_FRAC_BITS) + +#define DENTS_FRAC_MASK (int32_t) ((0x1L << NUM_DENTS_FRAC_BITS) -1) + +#define GET_DENTS_INT_PART(x) /*lint -e(704) */ \ + (int32_t)((int32_t)(x) >> NUM_DENTS_FRAC_BITS) + +#define GET_DENTS_FRAC_PART(x) (int32_t)((int32_t)(x) & DENTS_FRAC_MASK) + +#define DENTS_ONE (int32_t) (0x1L << NUM_DENTS_FRAC_BITS) + +/* use CENTS_TO_DENTS to convert a value in cents to dents */ +#define CENTS_TO_DENTS (int32_t) (DENTS_ONE * (0x1L << NUM_EG1_FRAC_BITS) / 1200L) \ + + +/* +For gain, the LFO generates a value that modulates in terms +of dB. However, we use a linear gain value, so we must convert +the LFO value in dB to a linear gain. Normally, we would use +linear gain = 10^x, where x = LFO value in dB / 20. +Instead, we implement 10^x using our 2^x approximation. +because + + 10^x = 2^(log2(10^x)) = 2^(x * log2(10)) + +so we need to multiply by log2(10) which is just a constant. +Ah, but just wait -- our 2^x actually doesn't exactly implement +2^x, but it actually assumes that the input is in cents, and within +the 2^x approximation converts its input from cents to octaves +by dividing its input by 1200. + +So, in order to convert the LFO gain value in dB to something +that our existing 2^x approximation can use, multiply the LFO gain +by log2(10) * 1200 / 20 + +The divide by 20 helps convert dB to linear gain, and we might +as well incorporate that operation into this conversion. +Of course, we need to keep some fractional bits, so multiply +the constant by NUM_EG1_FRAC_BITS +*/ + +/* use LFO_GAIN_TO_CENTS to convert the LFO gain value to cents */ +#if 0 +#define DOUBLE_LOG2_10 (double) (3.32192809488736) /* log2(10) */ + +#define DOUBLE_LFO_GAIN_TO_CENTS (double) \ + ( \ + (DOUBLE_LOG2_10) * \ + 1200.0 / \ + 20.0 \ + ) + +#define LFO_GAIN_TO_CENTS (int32_t) \ + ( \ + DOUBLE_LFO_GAIN_TO_CENTS * \ + (0x1L << NUM_EG1_FRAC_BITS) \ + ) +#endif + +#define LFO_GAIN_TO_CENTS (int32_t) (1671981156L >> (23 - NUM_EG1_FRAC_BITS)) + + +#define MULT_DENTS_COEF(dents,coef) /*lint -e704 */ \ + (int32_t)( \ + ( \ + ((int32_t)(dents)) * ((int32_t)(coef)) \ + ) \ + >> NUM_DENTS_FRAC_BITS \ + ) \ + /* lint +e704 */ + + +/* we use 16-bits in the PC per audio sample */ +#define BITS_PER_AUDIO_SAMPLE 16 + +/* we define 1 as 1.0 - 1 LSbit */ +#define DISTORTION_ONE (int32_t)((0x1L << (BITS_PER_AUDIO_SAMPLE-1)) -1) +#define DISTORTION_MINUS_ONE (int32_t)(~DISTORTION_ONE) + +/* drive coef is given as int.frac */ +#define NUM_DRIVE_COEF_INT_BITS 1 +#define NUM_DRIVE_COEF_FRAC_BITS 4 + +#define MULT_AUDIO_DRIVE(audio,drive) /*lint -e(702) */ \ + (int32_t) ( \ + ( \ + ((int32_t)(audio)) * ((int32_t)(drive)) \ + ) \ + >> NUM_DRIVE_COEF_FRAC_BITS \ + ) + +#define MULT_AUDIO_AUDIO(audio1,audio2) /*lint -e(702) */ \ + (int32_t) ( \ + ( \ + ((int32_t)(audio1)) * ((int32_t)(audio2)) \ + ) \ + >> (BITS_PER_AUDIO_SAMPLE-1) \ + ) + +#define SATURATE(x) \ + ((((int32_t)(x)) > DISTORTION_ONE) ? (DISTORTION_ONE) : \ + (((int32_t)(x)) < DISTORTION_MINUS_ONE) ? (DISTORTION_MINUS_ONE) : ((int32_t)(x))); + + +/*---------------------------------------------------------------------------- + * Effects_log2() + *---------------------------------------------------------------------------- + * Purpose: + * Fixed-point log2 function. + * + * Inputs: + * Input is interpreted as an integer (should not be 0). + * + * Outputs: + * Output is in 15-bit precision. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +int32_t Effects_log2(uint32_t x); + +/*---------------------------------------------------------------------------- + * Effects_exp2() + *---------------------------------------------------------------------------- + * Purpose: + * Fixed-point radix-2 exponent. + * + * Inputs: + * Input is in 15-bit precision. Must be non-negative and less than 32. + * + * Outputs: + * Output is an integer. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +uint32_t Effects_exp2(int32_t x); + +/*---------------------------------------------------------------------------- + * Effects_MillibelsToLinear16() + *---------------------------------------------------------------------------- + * Purpose: + * Transform gain in millibels to linear gain multiplier: + * + * mB = 2000*log(lin/32767) + * => lin = 2^((mB+2000*log(32767))/2000*log(2)) + * => lin = Effects_exp2(((mB + K1) << 15) / K2) + * with: + * K1 = 2000*log(32767) and K2 = 2000*log(2) + * + * Inputs: + * nGain - log scale value in millibels. + * + * Outputs: + * Returns a 16-bit linear value approximately equal to 2^(nGain/1024) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +#define MB_TO_LIN_K1 9031 +#define MB_TO_LIN_K2 602 +int16_t Effects_MillibelsToLinear16 (int32_t nGain); + +/*---------------------------------------------------------------------------- + * Effects_Linear16ToMillibels() + *---------------------------------------------------------------------------- + * Purpose: + * Transform linear gain multiplier to millibels + * mB = 2000*log(lin/32767) + * = 2000*log(2)*log2(lin)-2000*log(32767) + * => mB = K1*Effects_log2(lin) + K2 + * with: + * K1 = 2000*log(2) and K2 = -2000*log(32767) + * + * Inputs: + * nGain - linear multiplier ranging form 0 to 32767 (corresponding to [0 1] gain range). + * + * Outputs: + * Returns a 16-bit log value expressed in milllibels. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +int16_t Effects_Linear16ToMillibels (int32_t nGain); + +/*---------------------------------------------------------------------------- + * Effects_Sqrt() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the square root of the argument given. + * + * Inputs: + * in - positive number in the range 0 - 2^28 + * + * Outputs: + * Returned value: square root of in. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +int32_t Effects_Sqrt(int32_t in); + +#if __cplusplus +} // extern "C" +#endif + +#endif /*ANDROID_EFFECTSMATH_H_*/ + diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 3adabccb7b2903048d10088ba625385dd00a061d..29cd2ee502a44bef7f850af15d530137377a312e 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -26,7 +26,9 @@ LOCAL_SRC_FILES:= \ MediaScannerClient.cpp \ autodetect.cpp \ IMediaDeathNotifier.cpp \ - MediaProfiles.cpp + MediaProfiles.cpp \ + IEffect.cpp \ + IEffectClient.cpp LOCAL_SHARED_LIBRARIES := \ libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index ad037d6e42b40ac4eb8c260fcbc10192949a57a4..fd2b1cea8bf7fb3adffaa542f0f0d9815ef955ac 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -430,7 +430,7 @@ status_t AudioRecord::openRecord( mCblkMemory = cblk; mCblk = static_cast(cblk->pointer()); mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); - mCblk->out = 0; + mCblk->flags &= ~CBLK_DIRECTION_MSK; mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; mCblk->waitTimeMs = 0; return NO_ERROR; @@ -644,10 +644,10 @@ bool AudioRecord::processAudioBuffer(const sp& thread) // Manage overrun callback if (mActive && (mCblk->framesAvailable_l() == 0)) { - LOGV("Overrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag); - if (mCblk->flowControlFlag == 0) { + LOGV("Overrun user: %x, server: %x, flags %04x", mCblk->user, mCblk->server, mCblk->flags); + if ((mCblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) { mCbf(EVENT_OVERRUN, mUserData, 0); - mCblk->flowControlFlag = 1; + mCblk->flags |= CBLK_UNDERRUN_ON; } } diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index cd7bcd5be3bb9ca6bed33395ea3e98a74dedab5c..c350532bfeb148c9c86dd4d5e5b242e66377543a 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -124,10 +124,6 @@ status_t AudioTrack::set( if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { return NO_INIT; } - int afFrameCount; - if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { - return NO_INIT; - } uint32_t afLatency; if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) { return NO_INIT; @@ -173,48 +169,13 @@ status_t AudioTrack::set( return BAD_VALUE; } - if (!AudioSystem::isLinearPCM(format)) { - if (sharedBuffer != 0) { - frameCount = sharedBuffer->size(); - } - } else { - // Ensure that buffer depth covers at least audio hardware latency - uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); - if (minBufCount < 2) minBufCount = 2; - - int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; - - if (sharedBuffer == 0) { - if (frameCount == 0) { - frameCount = minFrameCount; - } - if (notificationFrames == 0) { - notificationFrames = frameCount/2; - } - // Make sure that application is notified with sufficient margin - // before underrun - if (notificationFrames > frameCount/2) { - notificationFrames = frameCount/2; - } - if (frameCount < minFrameCount) { - LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount); - return BAD_VALUE; - } - } else { - // Ensure that buffer alignment matches channelcount - if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) { - LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount); - return BAD_VALUE; - } - frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t); - } - } - mVolume[LEFT] = 1.0f; mVolume[RIGHT] = 1.0f; + mFrameCount = frameCount; + mNotificationFramesReq = notificationFrames; // create the IAudioTrack status_t status = createTrack(streamType, sampleRate, format, channelCount, - frameCount, flags, sharedBuffer, output); + frameCount, flags, sharedBuffer, output, true); if (status != NO_ERROR) { return status; @@ -238,10 +199,7 @@ status_t AudioTrack::set( mMuted = false; mActive = 0; mCbf = cbf; - mNotificationFrames = notificationFrames; - mRemainingFrames = notificationFrames; mUserData = user; - mLatency = afLatency + (1000*mFrameCount) / sampleRate; mLoopCount = 0; mMarkerPosition = 0; mMarkerReached = false; @@ -281,7 +239,7 @@ int AudioTrack::channelCount() const uint32_t AudioTrack::frameCount() const { - return mFrameCount; + return mCblk->frameCount; } int AudioTrack::frameSize() const @@ -303,6 +261,7 @@ sp& AudioTrack::sharedBuffer() void AudioTrack::start() { sp t = mAudioTrackThread; + status_t status; LOGV("start %p", this); if (t != 0) { @@ -325,11 +284,18 @@ void AudioTrack::start() setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT); } - status_t status = mAudioTrack->start(); + if (mCblk->flags & CBLK_INVALID_MSK) { + LOGW("start() track %p invalidated, creating a new one", this); + // no need to clear the invalid flag as this cblk will not be used anymore + // force new track creation + status = DEAD_OBJECT; + } else { + status = mAudioTrack->start(); + } if (status == DEAD_OBJECT) { LOGV("start() dead IAudioTrack: creating a new one"); status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount, - mFrameCount, mFlags, mSharedBuffer, getOutput()); + mFrameCount, mFlags, mSharedBuffer, getOutput(), false); if (status == NO_ERROR) { status = mAudioTrack->start(); if (status == NO_ERROR) { @@ -479,14 +445,14 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount } if (loopStart >= loopEnd || - loopEnd - loopStart > mFrameCount) { - LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user); + loopEnd - loopStart > cblk->frameCount) { + LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, cblk->frameCount, cblk->user); return BAD_VALUE; } - if ((mSharedBuffer != 0) && (loopEnd > mFrameCount)) { + if ((mSharedBuffer != 0) && (loopEnd > cblk->frameCount)) { LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d", - loopStart, loopEnd, mFrameCount); + loopStart, loopEnd, cblk->frameCount); return BAD_VALUE; } @@ -566,7 +532,7 @@ status_t AudioTrack::setPosition(uint32_t position) if (position > mCblk->user) return BAD_VALUE; mCblk->server = position; - mCblk->forceReady = 1; + mCblk->flags |= CBLK_FORCEREADY_ON; return NO_ERROR; } @@ -586,7 +552,7 @@ status_t AudioTrack::reload() flush(); - mCblk->stepUser(mFrameCount); + mCblk->stepUser(mCblk->frameCount); return NO_ERROR; } @@ -607,7 +573,8 @@ status_t AudioTrack::createTrack( int frameCount, uint32_t flags, const sp& sharedBuffer, - audio_io_handle_t output) + audio_io_handle_t output, + bool enforceFrameCount) { status_t status; const sp& audioFlinger = AudioSystem::get_audio_flinger(); @@ -616,6 +583,61 @@ status_t AudioTrack::createTrack( return NO_INIT; } + int afSampleRate; + if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { + return NO_INIT; + } + int afFrameCount; + if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { + return NO_INIT; + } + uint32_t afLatency; + if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) { + return NO_INIT; + } + + mNotificationFramesAct = mNotificationFramesReq; + if (!AudioSystem::isLinearPCM(format)) { + if (sharedBuffer != 0) { + frameCount = sharedBuffer->size(); + } + } else { + // Ensure that buffer depth covers at least audio hardware latency + uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); + if (minBufCount < 2) minBufCount = 2; + + int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; + + if (sharedBuffer == 0) { + if (frameCount == 0) { + frameCount = minFrameCount; + } + if (mNotificationFramesAct == 0) { + mNotificationFramesAct = frameCount/2; + } + // Make sure that application is notified with sufficient margin + // before underrun + if (mNotificationFramesAct > (uint32_t)frameCount/2) { + mNotificationFramesAct = frameCount/2; + } + if (frameCount < minFrameCount) { + if (enforceFrameCount) { + LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount); + return BAD_VALUE; + } else { + frameCount = minFrameCount; + } + } + } else { + // Ensure that buffer alignment matches channelcount + if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) { + LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount); + return BAD_VALUE; + } + frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t); + } + } + sp track = audioFlinger->createTrack(getpid(), streamType, sampleRate, @@ -641,20 +663,20 @@ status_t AudioTrack::createTrack( mCblkMemory.clear(); mCblkMemory = cblk; mCblk = static_cast(cblk->pointer()); - mCblk->out = 1; - // Update buffer size in case it has been limited by AudioFlinger during track creation - mFrameCount = mCblk->frameCount; + mCblk->flags |= CBLK_DIRECTION_OUT; if (sharedBuffer == 0) { mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); } else { mCblk->buffers = sharedBuffer->pointer(); // Force buffer full condition as data is already present in shared memory - mCblk->stepUser(mFrameCount); + mCblk->stepUser(mCblk->frameCount); } mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000); mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; mCblk->waitTimeMs = 0; + mRemainingFrames = mNotificationFramesAct; + mLatency = afLatency + (1000*mCblk->frameCount) / sampleRate; return NO_ERROR; } @@ -685,8 +707,15 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) cblk->lock.unlock(); return WOULD_BLOCK; } - - result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); + if (!(cblk->flags & CBLK_INVALID_MSK)) { + result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); + } + if (cblk->flags & CBLK_INVALID_MSK) { + LOGW("obtainBuffer() track %p invalidated, creating a new one", this); + // no need to clear the invalid flag as this cblk will not be used anymore + cblk->lock.unlock(); + goto create_new_track; + } if (__builtin_expect(result!=NO_ERROR, false)) { cblk->waitTimeMs += waitTimeMs; if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { @@ -700,8 +729,9 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) result = mAudioTrack->start(); if (result == DEAD_OBJECT) { LOGW("obtainBuffer() dead IAudioTrack: creating a new one"); +create_new_track: result = createTrack(mStreamType, cblk->sampleRate, mFormat, mChannelCount, - mFrameCount, mFlags, mSharedBuffer, getOutput()); + mFrameCount, mFlags, mSharedBuffer, getOutput(), false); if (result == NO_ERROR) { cblk = mCblk; cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; @@ -826,13 +856,13 @@ bool AudioTrack::processAudioBuffer(const sp& thread) // Manage underrun callback if (mActive && (mCblk->framesReady() == 0)) { - LOGV("Underrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag); - if (mCblk->flowControlFlag == 0) { + LOGV("Underrun user: %x, server: %x, flags %04x", mCblk->user, mCblk->server, mCblk->flags); + if ((mCblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) { mCbf(EVENT_UNDERRUN, mUserData, 0); if (mCblk->server == mCblk->frameCount) { mCbf(EVENT_BUFFER_END, mUserData, 0); } - mCblk->flowControlFlag = 1; + mCblk->flags |= CBLK_UNDERRUN_ON; if (mSharedBuffer != 0) return false; } } @@ -932,7 +962,7 @@ bool AudioTrack::processAudioBuffer(const sp& thread) while (frames); if (frames == 0) { - mRemainingFrames = mNotificationFrames; + mRemainingFrames = mNotificationFramesAct; } else { mRemainingFrames = frames; } @@ -949,7 +979,7 @@ status_t AudioTrack::dump(int fd, const Vector& args) const result.append(" AudioTrack::dump\n"); snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType, mVolume[0], mVolume[1]); result.append(buffer); - snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mFrameCount); + snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mCblk->frameCount); result.append(buffer); snprintf(buffer, 255, " sample rate(%d), status(%d), muted(%d)\n", (mCblk == 0) ? 0 : mCblk->sampleRate, mStatus, mMuted); result.append(buffer); @@ -986,7 +1016,7 @@ audio_track_cblk_t::audio_track_cblk_t() : lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0), userBase(0), serverBase(0), buffers(0), frameCount(0), loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0), - flowControlFlag(1), forceReady(0) + flags(0) { } @@ -996,7 +1026,7 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) u += frameCount; // Ensure that user is never ahead of server for AudioRecord - if (out) { + if (flags & CBLK_DIRECTION_MSK) { // If stepServer() has been called once, switch to normal obtainBuffer() timeout period if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) { bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; @@ -1013,7 +1043,7 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) this->user = u; // Clear flow control error condition as new data has been written/read to/from buffer. - flowControlFlag = 0; + flags &= ~CBLK_UNDERRUN_MSK; return u; } @@ -1038,7 +1068,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) uint32_t s = this->server; s += frameCount; - if (out) { + if (flags & CBLK_DIRECTION_MSK) { // Mark that we have read the first buffer so that next time stepUser() is called // we switch to normal obtainBuffer() timeout period if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) { @@ -1089,7 +1119,7 @@ uint32_t audio_track_cblk_t::framesAvailable_l() uint32_t u = this->user; uint32_t s = this->server; - if (out) { + if (flags & CBLK_DIRECTION_MSK) { uint32_t limit = (s < loopStart) ? s : loopStart; return limit + frameCount - u; } else { @@ -1102,7 +1132,7 @@ uint32_t audio_track_cblk_t::framesReady() uint32_t u = this->user; uint32_t s = this->server; - if (out) { + if (flags & CBLK_DIRECTION_MSK) { if (u < loopEnd) { return u - s; } else { diff --git a/media/libmedia/IEffect.cpp b/media/libmedia/IEffect.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e3ac7110d83b66a82a1abbca848adcd28f27e09 --- /dev/null +++ b/media/libmedia/IEffect.cpp @@ -0,0 +1,191 @@ +/* +** +** Copyright 2010, 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. +*/ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "IEffect" +#include +#include +#include +#include +#include + +namespace android { + +enum { + ENABLE = IBinder::FIRST_CALL_TRANSACTION, + DISABLE, + COMMAND, + DISCONNECT, + GET_CBLK +}; + +class BpEffect: public BpInterface +{ +public: + BpEffect(const sp& impl) + : BpInterface(impl) + { + } + + status_t enable() + { + LOGV("enable"); + Parcel data, reply; + data.writeInterfaceToken(IEffect::getInterfaceDescriptor()); + remote()->transact(ENABLE, data, &reply); + return reply.readInt32(); + } + + status_t disable() + { + LOGV("disable"); + Parcel data, reply; + data.writeInterfaceToken(IEffect::getInterfaceDescriptor()); + remote()->transact(DISABLE, data, &reply); + return reply.readInt32(); + } + + status_t command(int cmdCode, int cmdSize, void *pCmdData, int *pReplySize, void *pReplyData) + { + LOGV("command"); + Parcel data, reply; + data.writeInterfaceToken(IEffect::getInterfaceDescriptor()); + data.writeInt32(cmdCode); + int size = cmdSize; + if (pCmdData == NULL) { + size = 0; + } + data.writeInt32(size); + if (size) { + data.write(pCmdData, size); + } + if (pReplySize == NULL) { + size = 0; + } else { + size = *pReplySize; + } + data.writeInt32(size); + remote()->transact(COMMAND, data, &reply); + status_t status = reply.readInt32(); + size = reply.readInt32(); + if (size != 0 && pReplyData != NULL && pReplySize != NULL) { + reply.read(pReplyData, size); + *pReplySize = size; + } + return status; + } + + void disconnect() + { + LOGV("disconnect"); + Parcel data, reply; + data.writeInterfaceToken(IEffect::getInterfaceDescriptor()); + remote()->transact(DISCONNECT, data, &reply); + return; + } + + virtual sp getCblk() const + { + Parcel data, reply; + sp cblk; + data.writeInterfaceToken(IEffect::getInterfaceDescriptor()); + status_t status = remote()->transact(GET_CBLK, data, &reply); + if (status == NO_ERROR) { + cblk = interface_cast(reply.readStrongBinder()); + } + return cblk; + } + }; + +IMPLEMENT_META_INTERFACE(Effect, "android.media.IEffect"); + +// ---------------------------------------------------------------------- + +status_t BnEffect::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case ENABLE: { + LOGV("ENABLE"); + CHECK_INTERFACE(IEffect, data, reply); + reply->writeInt32(enable()); + return NO_ERROR; + } break; + + case DISABLE: { + LOGV("DISABLE"); + CHECK_INTERFACE(IEffect, data, reply); + reply->writeInt32(disable()); + return NO_ERROR; + } break; + + case COMMAND: { + LOGV("COMMAND"); + CHECK_INTERFACE(IEffect, data, reply); + int cmdCode = data.readInt32(); + int cmdSize = data.readInt32(); + char *cmd = NULL; + if (cmdSize) { + cmd = (char *)malloc(cmdSize); + data.read(cmd, cmdSize); + } + int replySize = data.readInt32(); + int replySz = replySize; + char *resp = NULL; + if (replySize) { + resp = (char *)malloc(replySize); + } + status_t status = command(cmdCode, cmdSize, cmd, &replySz, resp); + reply->writeInt32(status); + if (replySz < replySize) { + replySize = replySz; + } + reply->writeInt32(replySize); + if (replySize) { + reply->write(resp, replySize); + } + if (cmd) { + free(cmd); + } + if (resp) { + free(resp); + } + return NO_ERROR; + } break; + + case DISCONNECT: { + LOGV("DISCONNECT"); + CHECK_INTERFACE(IEffect, data, reply); + disconnect(); + return NO_ERROR; + } break; + + case GET_CBLK: { + CHECK_INTERFACE(IEffect, data, reply); + reply->writeStrongBinder(getCblk()->asBinder()); + return NO_ERROR; + } break; + + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android + diff --git a/media/libmedia/IEffectClient.cpp b/media/libmedia/IEffectClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7659ae2b0997cef5d3a16823744e9884b17781f --- /dev/null +++ b/media/libmedia/IEffectClient.cpp @@ -0,0 +1,141 @@ +/* +** +** Copyright 2010, 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. +*/ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "IEffectClient" +#include +#include +#include +#include + +namespace android { + +enum { + CONTROL_STATUS_CHANGED = IBinder::FIRST_CALL_TRANSACTION, + ENABLE_STATUS_CHANGED, + COMMAND_EXECUTED +}; + +class BpEffectClient: public BpInterface +{ +public: + BpEffectClient(const sp& impl) + : BpInterface(impl) + { + } + + void controlStatusChanged(bool controlGranted) + { + LOGV("controlStatusChanged"); + Parcel data, reply; + data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor()); + data.writeInt32((uint32_t)controlGranted); + remote()->transact(CONTROL_STATUS_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); + } + + void enableStatusChanged(bool enabled) + { + LOGV("enableStatusChanged"); + Parcel data, reply; + data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor()); + data.writeInt32((uint32_t)enabled); + remote()->transact(ENABLE_STATUS_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); + } + + void commandExecuted(int cmdCode, int cmdSize, void *pCmdData, int replySize, void *pReplyData) + { + LOGV("commandExecuted"); + Parcel data, reply; + data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor()); + data.writeInt32(cmdCode); + int size = cmdSize; + if (pCmdData == NULL) { + size = 0; + } + data.writeInt32(size); + if (size) { + data.write(pCmdData, size); + } + size = replySize; + if (pReplyData == NULL) { + size = 0; + } + data.writeInt32(size); + if (size) { + data.write(pReplyData, size); + } + remote()->transact(COMMAND_EXECUTED, data, &reply, IBinder::FLAG_ONEWAY); + } + +}; + +IMPLEMENT_META_INTERFACE(EffectClient, "android.media.IEffectClient"); + +// ---------------------------------------------------------------------- + +status_t BnEffectClient::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case CONTROL_STATUS_CHANGED: { + LOGV("CONTROL_STATUS_CHANGED"); + CHECK_INTERFACE(IEffectClient, data, reply); + bool hasControl = (bool)data.readInt32(); + controlStatusChanged(hasControl); + return NO_ERROR; + } break; + case ENABLE_STATUS_CHANGED: { + LOGV("ENABLE_STATUS_CHANGED"); + CHECK_INTERFACE(IEffectClient, data, reply); + bool enabled = (bool)data.readInt32(); + enableStatusChanged(enabled); + return NO_ERROR; + } break; + case COMMAND_EXECUTED: { + LOGV("COMMAND_EXECUTED"); + CHECK_INTERFACE(IEffectClient, data, reply); + int cmdCode = data.readInt32(); + int cmdSize = data.readInt32(); + char *cmd = NULL; + if (cmdSize) { + cmd = (char *)malloc(cmdSize); + data.read(cmd, cmdSize); + } + int replySize = data.readInt32(); + char *resp = NULL; + if (replySize) { + resp = (char *)malloc(replySize); + data.read(resp, replySize); + } + commandExecuted(cmdCode, cmdSize, cmd, replySize, resp); + if (cmd) { + free(cmd); + } + if (resp) { + free(resp); + } + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android + diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp index 01b67374ab01905be817d5b071555f318dd39d4a..f3804b8cfd494e415583c5989d611a44127f2414 100644 --- a/media/libmedia/IOMX.cpp +++ b/media/libmedia/IOMX.cpp @@ -57,7 +57,7 @@ sp IOMX::createRendererFromJavaSurface( return NULL; } - jfieldID surfaceID = env->GetFieldID(surfaceClass, "mSurface", "I"); + jfieldID surfaceID = env->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I"); if (surfaceID == NULL) { LOGE("Can't find Surface.mSurface"); return NULL; diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk index cf97b2344ebaf04f479ecfef9b0a6021798c286b..3b678cbe991e1442ad86f5f8db2e0a0938546833 100644 --- a/media/libmediaplayerservice/Android.mk +++ b/media/libmediaplayerservice/Android.mk @@ -37,6 +37,7 @@ LOCAL_SHARED_LIBRARIES := \ libvorbisidec \ libsonivox \ libmedia \ + libcamera_client \ libandroid_runtime \ libstagefright \ libstagefright_omx \ diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 3e1f4a57ba66791045f1ffebbe2b0806b311319e..11f30168fdc98d861e1eb1cd6c498fce92cfed4b 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -228,14 +228,10 @@ MediaPlayerService::~MediaPlayerService() sp MediaPlayerService::createMediaRecorder(pid_t pid) { -#ifndef NO_OPENCORE sp recorder = new MediaRecorderClient(this, pid); wp w = recorder; Mutex::Autolock lock(mLock); mMediaRecorderClients.add(w); -#else - sp recorder = NULL; -#endif LOGV("Create new media recorder client from pid %d", pid); return recorder; } @@ -758,7 +754,7 @@ player_type getPlayerType(const char* url) int len = strlen(FILE_EXTS[i].extension); int start = lenURL - len; if (start > 0) { - if (!strncmp(url + start, FILE_EXTS[i].extension, len)) { + if (!strncasecmp(url + start, FILE_EXTS[i].extension, len)) { if (FILE_EXTS[i].playertype == VORBIS_PLAYER && !strncasecmp(url, "http://", 7) && useStagefrightForHTTP) { diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 531fd117306893e17f7e2418d644359e2da4679d..572389f243b919b444c018963f3adb4d1f60c22e 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -20,6 +20,7 @@ #include "StagefrightRecorder.h" +#include #include #include #include @@ -30,8 +31,13 @@ #include #include #include +#include +#include #include #include +#include +#include +#include namespace android { @@ -83,6 +89,12 @@ status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) { } status_t StagefrightRecorder::setVideoSize(int width, int height) { + if (width <= 0 || height <= 0) { + LOGE("Invalid video size: %dx%d", width, height); + return BAD_VALUE; + } + + // Additional check on the dimension will be performed later mVideoWidth = width; mVideoHeight = height; @@ -90,13 +102,37 @@ status_t StagefrightRecorder::setVideoSize(int width, int height) { } status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) { + if (frames_per_second <= 0 || frames_per_second > 30) { + LOGE("Invalid video frame rate: %d", frames_per_second); + return BAD_VALUE; + } + + // Additional check on the frame rate will be performed later mFrameRate = frames_per_second; return OK; } status_t StagefrightRecorder::setCamera(const sp &camera) { - mCamera = camera; + LOGV("setCamera: pid %d pid %d", IPCThreadState::self()->getCallingPid(), getpid()); + if (camera == 0) { + LOGE("camera is NULL"); + return UNKNOWN_ERROR; + } + + mFlags &= ~ FLAGS_SET_CAMERA | FLAGS_HOT_CAMERA; + mCamera = Camera::create(camera); + if (mCamera == 0) { + LOGE("Unable to connect to camera"); + return UNKNOWN_ERROR; + } + + LOGV("Connected to camera"); + mFlags |= FLAGS_SET_CAMERA; + if (mCamera->previewEnabled()) { + LOGV("camera is hot"); + mFlags |= FLAGS_HOT_CAMERA; + } return OK; } @@ -127,9 +163,216 @@ status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t leng return OK; } -status_t StagefrightRecorder::setParameters(const String8 ¶ms) { - mParams = params; +// Attempt to parse an int64 literal optionally surrounded by whitespace, +// returns true on success, false otherwise. +static bool safe_strtoi64(const char *s, int64_t *val) { + char *end; + *val = strtoll(s, &end, 10); + + if (end == s || errno == ERANGE) { + return false; + } + + // Skip trailing whitespace + while (isspace(*end)) { + ++end; + } + + // For a successful return, the string must contain nothing but a valid + // int64 literal optionally surrounded by whitespace. + + return *end == '\0'; +} + +// Return true if the value is in [0, 0x007FFFFFFF] +static bool safe_strtoi32(const char *s, int32_t *val) { + int64_t temp; + if (safe_strtoi64(s, &temp)) { + if (temp >= 0 && temp <= 0x007FFFFFFF) { + *val = static_cast(temp); + return true; + } + } + return false; +} + +// Trim both leading and trailing whitespace from the given string. +static void TrimString(String8 *s) { + size_t num_bytes = s->bytes(); + const char *data = s->string(); + + size_t leading_space = 0; + while (leading_space < num_bytes && isspace(data[leading_space])) { + ++leading_space; + } + + size_t i = num_bytes; + while (i > leading_space && isspace(data[i - 1])) { + --i; + } + + s->setTo(String8(&data[leading_space], i - leading_space)); +} + +status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) { + LOGV("setParamAudioSamplingRate: %d", sampleRate); + if (sampleRate <= 0) { + LOGE("Invalid audio sampling rate: %d", sampleRate); + return BAD_VALUE; + } + + // Additional check on the sample rate will be performed later. + mSampleRate = sampleRate; + return OK; +} + +status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) { + LOGV("setParamAudioNumberOfChannels: %d", channels); + if (channels <= 0 || channels >= 3) { + LOGE("Invalid number of audio channels: %d", channels); + } + + // Additional check on the number of channels will be performed later. + mAudioChannels = channels; + return OK; +} + +status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) { + LOGV("setParamAudioEncodingBitRate: %d", bitRate); + if (bitRate <= 0) { + LOGE("Invalid audio encoding bit rate: %d", bitRate); + return BAD_VALUE; + } + + // The target bit rate may not be exactly the same as the requested. + // It depends on many factors, such as rate control, and the bit rate + // range that a specific encoder supports. The mismatch between the + // the target and requested bit rate will NOT be treated as an error. + mAudioBitRate = bitRate; + return OK; +} + +status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) { + LOGV("setParamVideoEncodingBitRate: %d", bitRate); + if (bitRate <= 0) { + LOGE("Invalid video encoding bit rate: %d", bitRate); + return BAD_VALUE; + } + + // The target bit rate may not be exactly the same as the requested. + // It depends on many factors, such as rate control, and the bit rate + // range that a specific encoder supports. The mismatch between the + // the target and requested bit rate will NOT be treated as an error. + mVideoBitRate = bitRate; + return OK; +} + +status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int64_t limit, + bool limit_is_duration) { + LOGV("setParamMaxDurationOrFileSize: limit (%lld) for %s", + limit, limit_is_duration?"duration":"size"); + if (limit_is_duration) { // limit is in ms + if (limit <= 1000) { // XXX: 1 second + LOGE("Max file duration is too short: %lld us", limit); + } + mMaxFileDurationUs = limit * 1000LL; + } else { + if (limit <= 1024) { // XXX: 1 kB + LOGE("Max file size is too small: %lld bytes", limit); + } + mMaxFileSizeBytes = limit; + } + return OK; +} + +status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) { + LOGV("setParamInterleaveDuration: %d", durationUs); + if (durationUs <= 20000) { // XXX: 20 ms + LOGE("Audio/video interleave duration is too small: %d us", durationUs); + return BAD_VALUE; + } + mInterleaveDurationUs = durationUs; + return OK; +} + +status_t StagefrightRecorder::setParameter( + const String8 &key, const String8 &value) { + LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string()); + if (key == "max-duration") { + int64_t max_duration_ms; + if (safe_strtoi64(value.string(), &max_duration_ms)) { + return setParamMaxDurationOrFileSize( + max_duration_ms, true /* limit_is_duration */); + } + } else if (key == "max-filesize") { + int64_t max_filesize_bytes; + if (safe_strtoi64(value.string(), &max_filesize_bytes)) { + return setParamMaxDurationOrFileSize( + max_filesize_bytes, false /* limit is filesize */); + } + } else if (key == "audio-param-sampling-rate") { + int32_t sampling_rate; + if (safe_strtoi32(value.string(), &sampling_rate)) { + return setParamAudioSamplingRate(sampling_rate); + } + } else if (key == "audio-param-number-of-channels") { + int32_t number_of_channels; + if (safe_strtoi32(value.string(), &number_of_channels)) { + return setParamAudioNumberOfChannels(number_of_channels); + } + } else if (key == "audio-param-encoding-bitrate") { + int32_t audio_bitrate; + if (safe_strtoi32(value.string(), &audio_bitrate)) { + return setParamAudioEncodingBitRate(audio_bitrate); + } + } else if (key == "video-param-encoding-bitrate") { + int32_t video_bitrate; + if (safe_strtoi32(value.string(), &video_bitrate)) { + return setParamVideoEncodingBitRate(video_bitrate); + } + } else if (key == "param-interleave-duration-us") { + int32_t durationUs; + if (safe_strtoi32(value.string(), &durationUs)) { + return setParamInterleaveDuration(durationUs); + } + } else { + LOGE("setParameter: failed to find key %s", key.string()); + } + return BAD_VALUE; +} +status_t StagefrightRecorder::setParameters(const String8 ¶ms) { + LOGV("setParameters: %s", params.string()); + const char *cparams = params.string(); + const char *key_start = cparams; + for (;;) { + const char *equal_pos = strchr(key_start, '='); + if (equal_pos == NULL) { + LOGE("Parameters %s miss a value", cparams); + return BAD_VALUE; + } + String8 key(key_start, equal_pos - key_start); + TrimString(&key); + if (key.length() == 0) { + LOGE("Parameters %s contains an empty key", cparams); + return BAD_VALUE; + } + const char *value_start = equal_pos + 1; + const char *semicolon_pos = strchr(value_start, ';'); + String8 value; + if (semicolon_pos == NULL) { + value.setTo(value_start); + } else { + value.setTo(value_start, semicolon_pos - value_start); + } + if (setParameter(key, value) != OK) { + return BAD_VALUE; + } + if (semicolon_pos == NULL) { + break; // Reaches the end + } + key_start = semicolon_pos + 1; + } return OK; } @@ -158,40 +401,56 @@ status_t StagefrightRecorder::start() { case OUTPUT_FORMAT_AMR_WB: return startAMRRecording(); + case OUTPUT_FORMAT_AAC_ADIF: + case OUTPUT_FORMAT_AAC_ADTS: + return startAACRecording(); + default: return UNKNOWN_ERROR; } } -sp StagefrightRecorder::createAMRAudioSource() { - uint32_t sampleRate = - mAudioEncoder == AUDIO_ENCODER_AMR_NB ? 8000 : 16000; - +sp StagefrightRecorder::createAudioSource() { sp audioSource = new AudioSource( mAudioSource, - sampleRate, + mSampleRate, AudioSystem::CHANNEL_IN_MONO); status_t err = audioSource->initCheck(); if (err != OK) { + LOGE("audio source is not initialized"); return NULL; } sp encMeta = new MetaData; - encMeta->setCString( - kKeyMIMEType, - mAudioEncoder == AUDIO_ENCODER_AMR_NB - ? MEDIA_MIMETYPE_AUDIO_AMR_NB : MEDIA_MIMETYPE_AUDIO_AMR_WB); + const char *mime; + switch (mAudioEncoder) { + case AUDIO_ENCODER_AMR_NB: + case AUDIO_ENCODER_DEFAULT: + mime = MEDIA_MIMETYPE_AUDIO_AMR_NB; + break; + case AUDIO_ENCODER_AMR_WB: + mime = MEDIA_MIMETYPE_AUDIO_AMR_WB; + break; + case AUDIO_ENCODER_AAC: + mime = MEDIA_MIMETYPE_AUDIO_AAC; + break; + default: + LOGE("Unknown audio encoder: %d", mAudioEncoder); + return NULL; + } + encMeta->setCString(kKeyMIMEType, mime); int32_t maxInputSize; CHECK(audioSource->getFormat()->findInt32( kKeyMaxInputSize, &maxInputSize)); encMeta->setInt32(kKeyMaxInputSize, maxInputSize); - encMeta->setInt32(kKeyChannelCount, 1); - encMeta->setInt32(kKeySampleRate, sampleRate); + encMeta->setInt32(kKeyChannelCount, mAudioChannels); + encMeta->setInt32(kKeySampleRate, mSampleRate); + encMeta->setInt32(kKeyBitRate, mAudioBitRate); OMXClient client; CHECK_EQ(client.connect(), OK); @@ -203,22 +462,59 @@ sp StagefrightRecorder::createAMRAudioSource() { return audioEncoder; } +status_t StagefrightRecorder::startAACRecording() { + CHECK(mOutputFormat == OUTPUT_FORMAT_AAC_ADIF || + mOutputFormat == OUTPUT_FORMAT_AAC_ADTS); + + CHECK(mAudioEncoder == AUDIO_ENCODER_AAC); + CHECK(mAudioSource != AUDIO_SOURCE_LIST_END); + CHECK(mOutputFd >= 0); + + CHECK(0 == "AACWriter is not implemented yet"); + + return OK; +} + status_t StagefrightRecorder::startAMRRecording() { - if (mAudioSource == AUDIO_SOURCE_LIST_END - || mVideoSource != VIDEO_SOURCE_LIST_END) { + CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB || + mOutputFormat == OUTPUT_FORMAT_AMR_WB); + + if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) { + if (mAudioEncoder != AUDIO_ENCODER_DEFAULT && + mAudioEncoder != AUDIO_ENCODER_AMR_NB) { + LOGE("Invalid encoder %d used for AMRNB recording", + mAudioEncoder); + return UNKNOWN_ERROR; + } + if (mSampleRate != 8000) { + LOGE("Invalid sampling rate %d used for AMRNB recording", + mSampleRate); + return UNKNOWN_ERROR; + } + } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB + if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) { + LOGE("Invlaid encoder %d used for AMRWB recording", + mAudioEncoder); + return UNKNOWN_ERROR; + } + if (mSampleRate != 16000) { + LOGE("Invalid sample rate %d used for AMRWB recording", + mSampleRate); + return UNKNOWN_ERROR; + } + } + if (mAudioChannels != 1) { + LOGE("Invalid number of audio channels %d used for amr recording", + mAudioChannels); return UNKNOWN_ERROR; } - if (mOutputFormat == OUTPUT_FORMAT_AMR_NB - && mAudioEncoder != AUDIO_ENCODER_DEFAULT - && mAudioEncoder != AUDIO_ENCODER_AMR_NB) { - return UNKNOWN_ERROR; - } else if (mOutputFormat == OUTPUT_FORMAT_AMR_WB - && mAudioEncoder != AUDIO_ENCODER_AMR_WB) { + if (mAudioSource >= AUDIO_SOURCE_LIST_END) { + LOGE("Invalid audio source: %d", mAudioSource); return UNKNOWN_ERROR; } - sp audioEncoder = createAMRAudioSource(); + sp audioEncoder = createAudioSource(); if (audioEncoder == NULL) { return UNKNOWN_ERROR; @@ -227,6 +523,14 @@ status_t StagefrightRecorder::startAMRRecording() { CHECK(mOutputFd >= 0); mWriter = new AMRWriter(dup(mOutputFd)); mWriter->addSource(audioEncoder); + + if (mMaxFileDurationUs != 0) { + mWriter->setMaxFileDuration(mMaxFileDurationUs); + } + if (mMaxFileSizeBytes != 0) { + mWriter->setMaxFileSize(mMaxFileSizeBytes); + } + mWriter->setListener(mListener); mWriter->start(); return OK; @@ -235,18 +539,66 @@ status_t StagefrightRecorder::startAMRRecording() { status_t StagefrightRecorder::startMPEG4Recording() { mWriter = new MPEG4Writer(dup(mOutputFd)); + // Add audio source first if it exists + if (mAudioSource != AUDIO_SOURCE_LIST_END) { + sp audioEncoder; + switch(mAudioEncoder) { + case AUDIO_ENCODER_AMR_NB: + case AUDIO_ENCODER_AMR_WB: + case AUDIO_ENCODER_AAC: + audioEncoder = createAudioSource(); + break; + default: + LOGE("Unsupported audio encoder: %d", mAudioEncoder); + return UNKNOWN_ERROR; + } + + if (audioEncoder == NULL) { + return UNKNOWN_ERROR; + } + + mWriter->addSource(audioEncoder); + } if (mVideoSource == VIDEO_SOURCE_DEFAULT || mVideoSource == VIDEO_SOURCE_CAMERA) { CHECK(mCamera != NULL); + // Set the actual video recording frame size + CameraParameters params(mCamera->getParameters()); + params.setPreviewSize(mVideoWidth, mVideoHeight); + params.setPreviewFrameRate(mFrameRate); + String8 s = params.flatten(); + CHECK_EQ(OK, mCamera->setParameters(s)); + CameraParameters newCameraParams(mCamera->getParameters()); + + // Check on video frame size + int frameWidth = 0, frameHeight = 0; + newCameraParams.getPreviewSize(&frameWidth, &frameHeight); + if (frameWidth < 0 || frameWidth != mVideoWidth || + frameHeight < 0 || frameHeight != mVideoHeight) { + LOGE("Failed to set the video frame size to %dx%d", + mVideoWidth, mVideoHeight); + return UNKNOWN_ERROR; + } + + // Check on video frame rate + int frameRate = newCameraParams.getPreviewFrameRate(); + if (frameRate < 0 || (frameRate - mFrameRate) != 0) { + LOGE("Failed to set frame rate to %d fps. The actual " + "frame rate is %d", mFrameRate, frameRate); + } + + CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); + sp cameraSource = - CameraSource::CreateFromICamera(mCamera); + CameraSource::CreateFromCamera(mCamera); CHECK(cameraSource != NULL); - cameraSource->setPreviewSurface(mPreviewSurface); - sp enc_meta = new MetaData; + enc_meta->setInt32(kKeyBitRate, mVideoBitRate); + enc_meta->setInt32(kKeySampleRate, mFrameRate); // XXX: kKeySampleRate? + switch (mVideoEncoder) { case VIDEO_ENCODER_H263: enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); @@ -286,16 +638,19 @@ status_t StagefrightRecorder::startMPEG4Recording() { mWriter->addSource(encoder); } - if (mAudioSource != AUDIO_SOURCE_LIST_END) { - sp audioEncoder = createAMRAudioSource(); - - if (audioEncoder == NULL) { - return UNKNOWN_ERROR; - } - - mWriter->addSource(audioEncoder); + { + // MPEGWriter specific handling + MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get()); // mWriter is an MPEGWriter + writer->setInterleaveDuration(mInterleaveDurationUs); } + if (mMaxFileDurationUs != 0) { + mWriter->setMaxFileDuration(mMaxFileDurationUs); + } + if (mMaxFileSizeBytes != 0) { + mWriter->setMaxFileSize(mMaxFileSizeBytes); + } + mWriter->setListener(mListener); mWriter->start(); return OK; } @@ -314,21 +669,42 @@ status_t StagefrightRecorder::stop() { status_t StagefrightRecorder::close() { stop(); + if (mCamera != 0) { + if ((mFlags & FLAGS_HOT_CAMERA) == 0) { + LOGV("Camera was cold when we started, stopping preview"); + mCamera->stopPreview(); + } + if (mFlags & FLAGS_SET_CAMERA) { + LOGV("Unlocking camera"); + mCamera->unlock(); + } + mFlags = 0; + } return OK; } status_t StagefrightRecorder::reset() { stop(); + // No audio or video source by default mAudioSource = AUDIO_SOURCE_LIST_END; mVideoSource = VIDEO_SOURCE_LIST_END; - mOutputFormat = OUTPUT_FORMAT_LIST_END; - mAudioEncoder = AUDIO_ENCODER_LIST_END; - mVideoEncoder = VIDEO_ENCODER_LIST_END; - mVideoWidth = -1; - mVideoHeight = -1; - mFrameRate = -1; + + // Default parameters + mOutputFormat = OUTPUT_FORMAT_THREE_GPP; + mAudioEncoder = AUDIO_ENCODER_AMR_NB; + mVideoEncoder = VIDEO_ENCODER_H263; + mVideoWidth = 176; + mVideoHeight = 144; + mFrameRate = 20; + mVideoBitRate = 192000; + mSampleRate = 8000; + mAudioChannels = 1; + mAudioBitRate = 12200; + mInterleaveDurationUs = 0; + mOutputFd = -1; + mFlags = 0; return OK; } diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index 7ec412dce3d4f9b74997970171ba8ef7a4603d0d..b7d554b56a577e2e70c02bc0ffbcba31e81e7256 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -23,6 +23,7 @@ namespace android { +class Camera; struct MediaSource; struct MediaWriter; @@ -52,7 +53,12 @@ struct StagefrightRecorder : public MediaRecorderBase { virtual status_t getMaxAmplitude(int *max); private: - sp mCamera; + enum CameraFlags { + FLAGS_SET_CAMERA = 1L << 0, + FLAGS_HOT_CAMERA = 1L << 1, + }; + + sp mCamera; sp mPreviewSurface; sp mListener; sp mWriter; @@ -62,14 +68,31 @@ private: output_format mOutputFormat; audio_encoder mAudioEncoder; video_encoder mVideoEncoder; - int mVideoWidth, mVideoHeight; - int mFrameRate; + int32_t mVideoWidth, mVideoHeight; + int32_t mFrameRate; + int32_t mVideoBitRate; + int32_t mAudioBitRate; + int32_t mAudioChannels; + int32_t mSampleRate; + int32_t mInterleaveDurationUs; + int64_t mMaxFileSizeBytes; + int64_t mMaxFileDurationUs; + String8 mParams; int mOutputFd; + int32_t mFlags; status_t startMPEG4Recording(); status_t startAMRRecording(); - sp createAMRAudioSource(); + status_t startAACRecording(); + sp createAudioSource(); + status_t setParameter(const String8 &key, const String8 &value); + status_t setParamVideoEncodingBitRate(int32_t bitRate); + status_t setParamAudioEncodingBitRate(int32_t bitRate); + status_t setParamAudioNumberOfChannels(int32_t channles); + status_t setParamAudioSamplingRate(int32_t sampleRate); + status_t setParamInterleaveDuration(int32_t durationUs); + status_t setParamMaxDurationOrFileSize(int64_t limit, bool limit_is_duration); StagefrightRecorder(const StagefrightRecorder &); StagefrightRecorder &operator=(const StagefrightRecorder &); diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp index bf4424b23e217c2c476d1c55de01968bc40c7368..aec73945f00b8b56bacf225779c8186ecf968371 100644 --- a/media/libstagefright/AMRWriter.cpp +++ b/media/libstagefright/AMRWriter.cpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace android { @@ -53,8 +54,6 @@ status_t AMRWriter::initCheck() const { } status_t AMRWriter::addSource(const sp &source) { - Mutex::Autolock autoLock(mLock); - if (mInitCheck != OK) { return mInitCheck; } @@ -95,8 +94,6 @@ status_t AMRWriter::addSource(const sp &source) { } status_t AMRWriter::start() { - Mutex::Autolock autoLock(mLock); - if (mInitCheck != OK) { return mInitCheck; } @@ -127,16 +124,12 @@ status_t AMRWriter::start() { } void AMRWriter::stop() { - { - Mutex::Autolock autoLock(mLock); - - if (!mStarted) { - return; - } - - mDone = true; + if (!mStarted) { + return; } + mDone = true; + void *dummy; pthread_join(mThread, &dummy); @@ -145,6 +138,20 @@ void AMRWriter::stop() { mStarted = false; } +bool AMRWriter::exceedsFileSizeLimit() { + if (mMaxFileSizeLimitBytes == 0) { + return false; + } + return mEstimatedSizeBytes >= mMaxFileSizeLimitBytes; +} + +bool AMRWriter::exceedsFileDurationLimit() { + if (mMaxFileDurationLimitUs == 0) { + return false; + } + return mEstimatedDurationUs >= mMaxFileDurationLimitUs; +} + // static void *AMRWriter::ThreadWrapper(void *me) { static_cast(me)->threadFunc(); @@ -153,13 +160,10 @@ void *AMRWriter::ThreadWrapper(void *me) { } void AMRWriter::threadFunc() { - for (;;) { - Mutex::Autolock autoLock(mLock); - - if (mDone) { - break; - } - + mEstimatedDurationUs = 0; + mEstimatedSizeBytes = 0; + bool stoppedPrematurely = true; + while (!mDone) { MediaBuffer *buffer; status_t err = mSource->read(&buffer); @@ -167,6 +171,25 @@ void AMRWriter::threadFunc() { break; } + mEstimatedSizeBytes += buffer->range_length(); + if (exceedsFileSizeLimit()) { + buffer->release(); + buffer = NULL; + notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); + break; + } + + int64_t timestampUs; + CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); + if (timestampUs > mEstimatedDurationUs) { + mEstimatedDurationUs = timestampUs; + } + if (exceedsFileDurationLimit()) { + buffer->release(); + buffer = NULL; + notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); + break; + } ssize_t n = fwrite( (const uint8_t *)buffer->data() + buffer->range_offset(), 1, @@ -180,16 +203,26 @@ void AMRWriter::threadFunc() { break; } + // XXX: How to tell it is stopped prematurely? + if (stoppedPrematurely) { + stoppedPrematurely = false; + } + buffer->release(); buffer = NULL; } - Mutex::Autolock autoLock(mLock); + if (stoppedPrematurely) { + notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_STOP_PREMATURELY, 0); + } + + fflush(mFile); + fclose(mFile); + mFile = NULL; mReachedEOS = true; } bool AMRWriter::reachedEOS() { - Mutex::Autolock autoLock(mLock); return mReachedEOS; } diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 81f995b13758b03a8d06b1149e1d5abc1e4d4f4f..8d15013d05503dba48b600502d2647feb0c19c84 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -1,6 +1,8 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) +include frameworks/base/media/libstagefright/codecs/common/Config.mk + LOCAL_SRC_FILES:= \ ESDS.cpp \ MediaBuffer.cpp \ @@ -65,20 +67,27 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_STATIC_LIBRARIES := \ libstagefright_aacdec \ + libstagefright_aacenc \ libstagefright_amrnbdec \ libstagefright_amrnbenc \ libstagefright_amrwbdec \ + libstagefright_amrwbenc \ libstagefright_avcdec \ libstagefright_m4vh263dec \ libstagefright_mp3dec \ - libstagefright_vorbisdec + libstagefright_vorbisdec \ + libstagefright_matroska \ + libstagefright_vpxdec \ + libvpx \ LOCAL_SHARED_LIBRARIES += \ libstagefright_amrnb_common \ + libstagefright_enc_common \ libstagefright_avc_common ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true) + LOCAL_STATIC_LIBRARIES += \ libstagefright_id3 diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp index bcf24639726636d1084facfcf59a3de863621246..b79ba13a9ba32285af2172ae72f8892a64e4666e 100644 --- a/media/libstagefright/AudioPlayer.cpp +++ b/media/libstagefright/AudioPlayer.cpp @@ -87,7 +87,9 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) { DEFAULT_AUDIOSINK_BUFFERCOUNT, &AudioPlayer::AudioSinkCallback, this); if (err != OK) { - mSource->stop(); + if (!sourceAlreadyStarted) { + mSource->stop(); + } return err; } @@ -108,7 +110,9 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) { delete mAudioTrack; mAudioTrack = NULL; - mSource->stop(); + if (!sourceAlreadyStarted) { + mSource->stop(); + } return err; } diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index edabaf9ec66451d0c16707220179e66b2422bdb9..abd8abc16bb0c845f40b8dcb8d13edfce3e14d3c 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "AudioSource" +#include + #include #include diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index 075b1e344480c7f86d5c0851fa9fc40381998463..c8834f82fdacff05f16c234d763a16257a98f7c7 100644 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -14,12 +14,12 @@ * limitations under the License. */ -#include +//#define LOG_NDEBUG 0 +#define LOG_TAG "CameraSource" +#include #include -#include -#include // for property_get #include #include #include @@ -27,46 +27,10 @@ #include #include #include -#include -#include -#include #include namespace android { -static int64_t getNowUs() { - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int64_t)tv.tv_usec + tv.tv_sec * 1000000; -} - -struct DummySurface : public BnSurface { - DummySurface() {} - - virtual sp requestBuffer(int bufferIdx, int usage) { - return NULL; - } - - virtual status_t registerBuffers(const BufferHeap &buffers) { - return OK; - } - - virtual void postBuffer(ssize_t offset) {} - virtual void unregisterBuffers() {} - - virtual sp createOverlay( - uint32_t w, uint32_t h, int32_t format, int32_t orientation) { - return NULL; - } - -protected: - virtual ~DummySurface() {} - - DummySurface(const DummySurface &); - DummySurface &operator=(const DummySurface &); -}; - struct CameraSourceListener : public CameraListener { CameraSourceListener(const sp &source); @@ -100,22 +64,20 @@ void CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) { void CameraSourceListener::postData(int32_t msgType, const sp &dataPtr) { LOGV("postData(%d, ptr:%p, size:%d)", msgType, dataPtr->pointer(), dataPtr->size()); - - sp source = mSource.promote(); - if (source.get() != NULL) { - source->dataCallback(msgType, dataPtr); - } } void CameraSourceListener::postDataTimestamp( nsecs_t timestamp, int32_t msgType, const sp& dataPtr) { - LOGV("postDataTimestamp(%lld, %d, ptr:%p, size:%d)", - timestamp, msgType, dataPtr->pointer(), dataPtr->size()); + + sp source = mSource.promote(); + if (source.get() != NULL) { + source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr); + } } // static CameraSource *CameraSource::Create() { - sp camera = Camera::connect(); + sp camera = Camera::connect(0); if (camera.get() == NULL) { return NULL; @@ -125,9 +87,7 @@ CameraSource *CameraSource::Create() { } // static -CameraSource *CameraSource::CreateFromICamera(const sp &icamera) { - sp camera = Camera::create(icamera); - +CameraSource *CameraSource::CreateFromCamera(const sp &camera) { if (camera.get() == NULL) { return NULL; } @@ -140,15 +100,11 @@ CameraSource::CameraSource(const sp &camera) mWidth(0), mHeight(0), mFirstFrameTimeUs(0), - mNumFrames(0), + mLastFrameTimestampUs(0), + mNumFramesReceived(0), + mNumFramesEncoded(0), + mNumFramesDropped(0), mStarted(false) { - char value[PROPERTY_VALUE_MAX]; - if (property_get("ro.hardware", value, NULL) && !strcmp(value, "sholes")) { - // The hardware encoder(s) do not support yuv420, but only YCbYCr, - // fortunately the camera also supports this, so we needn't transcode. - mCamera->setParameters(String8("preview-format=yuv422i-yuyv")); - } - String8 s = mCamera->getParameters(); printf("params: \"%s\"\n", s.string()); @@ -162,42 +118,50 @@ CameraSource::~CameraSource() { } } -void CameraSource::setPreviewSurface(const sp &surface) { - mPreviewSurface = surface; -} - status_t CameraSource::start(MetaData *) { + LOGV("start"); CHECK(!mStarted); mCamera->setListener(new CameraSourceListener(this)); - - status_t err = - mCamera->setPreviewDisplay( - mPreviewSurface != NULL ? mPreviewSurface : new DummySurface); - CHECK_EQ(err, OK); - - mCamera->setPreviewCallbackFlags( - FRAME_CALLBACK_FLAG_ENABLE_MASK - | FRAME_CALLBACK_FLAG_COPY_OUT_MASK); - - err = mCamera->startPreview(); - CHECK_EQ(err, OK); + CHECK_EQ(OK, mCamera->startRecording()); mStarted = true; - return OK; } status_t CameraSource::stop() { - CHECK(mStarted); + LOGV("stop"); + Mutex::Autolock autoLock(mLock); + mStarted = false; + mFrameAvailableCondition.signal(); + mCamera->setListener(NULL); + mCamera->stopRecording(); - mCamera->stopPreview(); + releaseQueuedFrames(); - mStarted = false; + while (!mFramesBeingEncoded.empty()) { + LOGI("Number of outstanding frames is being encoded: %d", mFramesBeingEncoded.size()); + mFrameCompleteCondition.wait(mLock); + } + + LOGI("Frames received/encoded/dropped: %d/%d/%d, timestamp (us) last/first: %lld/%lld", + mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped, + mLastFrameTimestampUs, mFirstFrameTimeUs); + CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped); return OK; } +void CameraSource::releaseQueuedFrames() { + List >::iterator it; + while (!mFramesReceived.empty()) { + it = mFramesReceived.begin(); + mCamera->releaseRecordingFrame(*it); + mFramesReceived.erase(it); + ++mNumFramesDropped; + } +} + sp CameraSource::getFormat() { sp meta = new MetaData; meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); @@ -208,9 +172,26 @@ sp CameraSource::getFormat() { return meta; } +void CameraSource::signalBufferReturned(MediaBuffer *buffer) { + LOGV("signalBufferReturned: %p", buffer->data()); + for (List >::iterator it = mFramesBeingEncoded.begin(); + it != mFramesBeingEncoded.end(); ++it) { + if ((*it)->pointer() == buffer->data()) { + mCamera->releaseRecordingFrame((*it)); + mFramesBeingEncoded.erase(it); + ++mNumFramesEncoded; + buffer->setObserver(0); + buffer->release(); + mFrameCompleteCondition.signal(); + return; + } + } + CHECK_EQ(0, "signalBufferReturned: bogus buffer"); +} + status_t CameraSource::read( MediaBuffer **buffer, const ReadOptions *options) { - CHECK(mStarted); + LOGV("read"); *buffer = NULL; @@ -224,38 +205,46 @@ status_t CameraSource::read( { Mutex::Autolock autoLock(mLock); - while (mFrames.empty()) { + while (mStarted && mFramesReceived.empty()) { mFrameAvailableCondition.wait(mLock); } - - frame = *mFrames.begin(); - mFrames.erase(mFrames.begin()); + if (!mStarted) { + return OK; + } + frame = *mFramesReceived.begin(); + mFramesReceived.erase(mFramesReceived.begin()); frameTime = *mFrameTimes.begin(); mFrameTimes.erase(mFrameTimes.begin()); - } - - *buffer = new MediaBuffer(frame->size()); - memcpy((*buffer)->data(), frame->pointer(), frame->size()); - (*buffer)->set_range(0, frame->size()); - - (*buffer)->meta_data()->clear(); - (*buffer)->meta_data()->setInt64(kKeyTime, frameTime); + mFramesBeingEncoded.push_back(frame); + *buffer = new MediaBuffer(frame->pointer(), frame->size()); + (*buffer)->setObserver(this); + (*buffer)->add_ref(); + (*buffer)->meta_data()->setInt64(kKeyTime, frameTime); + } return OK; } -void CameraSource::dataCallback(int32_t msgType, const sp &data) { +void CameraSource::dataCallbackTimestamp(int64_t timestampUs, + int32_t msgType, const sp &data) { + LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs); + mLastFrameTimestampUs = timestampUs; Mutex::Autolock autoLock(mLock); + if (!mStarted) { + mCamera->releaseRecordingFrame(data); + ++mNumFramesReceived; + ++mNumFramesDropped; + return; + } - int64_t nowUs = getNowUs(); - if (mNumFrames == 0) { - mFirstFrameTimeUs = nowUs; + if (mNumFramesReceived == 0) { + mFirstFrameTimeUs = timestampUs; } - ++mNumFrames; + ++mNumFramesReceived; - mFrames.push_back(data); - mFrameTimes.push_back(nowUs - mFirstFrameTimeUs); + mFramesReceived.push_back(data); + mFrameTimes.push_back(timestampUs - mFirstFrameTimeUs); mFrameAvailableCondition.signal(); } diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp index a66f86b885fb787d722594a708857cff806bd9f4..475422dff0ad37be3f25c50fb5a220f2ee392c13 100644 --- a/media/libstagefright/DataSource.cpp +++ b/media/libstagefright/DataSource.cpp @@ -20,6 +20,8 @@ #include "include/WAVExtractor.h" #include "include/OggExtractor.h" +#include "matroska/MatroskaExtractor.h" + #include #include #include @@ -94,6 +96,7 @@ void DataSource::RegisterDefaultSniffers() { RegisterSniffer(SniffAMR); RegisterSniffer(SniffWAV); RegisterSniffer(SniffOgg); + RegisterSniffer(SniffMatroska); } // static diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp index b6f1af20c36116b5306fd9eae7c4f0ebc4d1641d..dd2579bca54eb617e92d61e4f3f0fa434138721d 100644 --- a/media/libstagefright/FileSource.cpp +++ b/media/libstagefright/FileSource.cpp @@ -45,6 +45,10 @@ status_t FileSource::initCheck() const { } ssize_t FileSource::readAt(off_t offset, void *data, size_t size) { + if (mFile == NULL) { + return NO_INIT; + } + Mutex::Autolock autoLock(mLock); if (mLength >= 0) { @@ -67,6 +71,10 @@ ssize_t FileSource::readAt(off_t offset, void *data, size_t size) { } status_t FileSource::getSize(off_t *size) { + if (mFile == NULL) { + return NO_INIT; + } + if (mLength >= 0) { *size = mLength; diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index a41b2f4ba44756361d2a56e4cd80c00f2c4e7520..3639db40b34696849fd60a794825aa15acb5616e 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -1633,7 +1633,7 @@ status_t MPEG4Source::read( } } -bool SniffMPEG4( +static bool LegacySniffMPEG4( const sp &source, String8 *mimeType, float *confidence) { uint8_t header[8]; @@ -1657,5 +1657,83 @@ bool SniffMPEG4( return false; } +static bool isCompatibleBrand(uint32_t fourcc) { + static const uint32_t kCompatibleBrands[] = { + FOURCC('i', 's', 'o', 'm'), + FOURCC('i', 's', 'o', '2'), + FOURCC('a', 'v', 'c', '1'), + FOURCC('3', 'g', 'p', '4'), + FOURCC('m', 'p', '4', '1'), + FOURCC('m', 'p', '4', '2'), + }; + + for (size_t i = 0; + i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]); + ++i) { + if (kCompatibleBrands[i] == fourcc) { + return true; + } + } + + return false; +} + +// Attempt to actually parse the 'ftyp' atom and determine if a suitable +// compatible brand is present. +static bool BetterSniffMPEG4( + const sp &source, String8 *mimeType, float *confidence) { + uint8_t header[12]; + if (source->readAt(0, header, 12) != 12 + || memcmp("ftyp", &header[4], 4)) { + return false; + } + + size_t atomSize = U32_AT(&header[0]); + if (atomSize < 16 || (atomSize % 4) != 0) { + return false; + } + + bool success = false; + if (isCompatibleBrand(U32_AT(&header[8]))) { + success = true; + } else { + size_t numCompatibleBrands = (atomSize - 16) / 4; + for (size_t i = 0; i < numCompatibleBrands; ++i) { + uint8_t tmp[4]; + if (source->readAt(16 + i * 4, tmp, 4) != 4) { + return false; + } + + if (isCompatibleBrand(U32_AT(&tmp[0]))) { + success = true; + break; + } + } + } + + if (!success) { + return false; + } + + *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; + *confidence = 0.3f; + + return true; +} + +bool SniffMPEG4( + const sp &source, String8 *mimeType, float *confidence) { + if (BetterSniffMPEG4(source, mimeType, confidence)) { + return true; + } + + if (LegacySniffMPEG4(source, mimeType, confidence)) { + LOGW("Identified supported mpeg4 through LegacySniffMPEG4."); + return true; + } + + return false; +} + } // namespace android diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index 2cf0ddf7b69fd8b823da98907eaa06541f3e5cfc..e0f8f9e87bc9b167e0fd60ccee6661014338916a 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "MPEG4Writer" +#include + #include #include @@ -24,8 +28,10 @@ #include #include #include +#include #include #include +#include namespace android { @@ -39,6 +45,7 @@ public: bool reachedEOS(); int64_t getDurationUs() const; + int64_t getEstimatedTrackSizeBytes() const; void writeTrackHeader(int32_t trackID); private: @@ -47,39 +54,80 @@ private: sp mSource; volatile bool mDone; int64_t mMaxTimeStampUs; + int64_t mEstimatedTrackSizeBytes; pthread_t mThread; struct SampleInfo { size_t size; - off_t offset; int64_t timestamp; }; - List mSampleInfos; + List mSampleInfos; + bool mSamplesHaveSameSize; + + List mChunkSamples; + List mChunkOffsets; + + struct StscTableEntry { + + StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) + : firstChunk(chunk), + samplesPerChunk(samples), + sampleDescriptionId(id) {} + + uint32_t firstChunk; + uint32_t samplesPerChunk; + uint32_t sampleDescriptionId; + }; + List mStscTableEntries; + + List mStssTableEntries; + + struct SttsTableEntry { + + SttsTableEntry(uint32_t count, uint32_t duration) + : sampleCount(count), sampleDuration(duration) {} + + uint32_t sampleCount; + uint32_t sampleDuration; + }; + List mSttsTableEntries; void *mCodecSpecificData; size_t mCodecSpecificDataSize; + bool mGotAllCodecSpecificData; bool mReachedEOS; + int64_t mStartTimestampUs; static void *ThreadWrapper(void *me); void threadEntry(); + status_t makeAVCCodecSpecificData( + const uint8_t *data, size_t size); + void writeOneChunk(bool isAvc); + Track(const Track &); Track &operator=(const Track &); }; +#define USE_NALLEN_FOUR 1 + MPEG4Writer::MPEG4Writer(const char *filename) : mFile(fopen(filename, "wb")), mOffset(0), - mMdatOffset(0) { + mMdatOffset(0), + mEstimatedMoovBoxSize(0), + mInterleaveDurationUs(500000) { CHECK(mFile != NULL); } MPEG4Writer::MPEG4Writer(int fd) : mFile(fdopen(fd, "wb")), mOffset(0), - mMdatOffset(0) { + mMdatOffset(0), + mEstimatedMoovBoxSize(0), + mInterleaveDurationUs(500000) { CHECK(mFile != NULL); } @@ -105,15 +153,34 @@ status_t MPEG4Writer::start() { return UNKNOWN_ERROR; } + mStartTimestampUs = 0; + mStreamableFile = true; + mWriteMoovBoxToMemory = false; + mMoovBoxBuffer = NULL; + mMoovBoxBufferOffset = 0; + beginBox("ftyp"); writeFourcc("isom"); writeInt32(0); writeFourcc("isom"); endBox(); - mMdatOffset = mOffset; - write("\x00\x00\x00\x01mdat????????", 16); + mFreeBoxOffset = mOffset; + if (mEstimatedMoovBoxSize == 0) { + // XXX: Estimate the moov box size + // based on max file size or duration limit + mEstimatedMoovBoxSize = 0x0F00; + } + CHECK(mEstimatedMoovBoxSize >= 8); + fseeko(mFile, mFreeBoxOffset, SEEK_SET); + writeInt32(mEstimatedMoovBoxSize); + write("free", 4); + + mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; + mOffset = mMdatOffset; + fseeko(mFile, mMdatOffset, SEEK_SET); + write("\x00\x00\x00\x01mdat????????", 16); for (List::iterator it = mTracks.begin(); it != mTracks.end(); ++it) { status_t err = (*it)->start(); @@ -147,14 +214,20 @@ void MPEG4Writer::stop() { } } + // Fix up the size of the 'mdat' chunk. - fseek(mFile, mMdatOffset + 8, SEEK_SET); + fseeko(mFile, mMdatOffset + 8, SEEK_SET); int64_t size = mOffset - mMdatOffset; size = hton64(size); fwrite(&size, 1, 8, mFile); - fseek(mFile, mOffset, SEEK_SET); + fseeko(mFile, mOffset, SEEK_SET); time_t now = time(NULL); + const off_t moovOffset = mOffset; + mWriteMoovBoxToMemory = true; + mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); + mMoovBoxBufferOffset = 0; + CHECK(mMoovBoxBuffer != NULL); beginBox("moov"); @@ -194,15 +267,48 @@ void MPEG4Writer::stop() { } endBox(); // moov + mWriteMoovBoxToMemory = false; + if (mStreamableFile) { + CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); + + // Moov box + fseeko(mFile, mFreeBoxOffset, SEEK_SET); + mOffset = mFreeBoxOffset; + write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); + + // Free box + mFreeBoxOffset = mStreamableFile? mOffset: mFreeBoxOffset; + fseeko(mFile, mFreeBoxOffset, SEEK_SET); + writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); + write("free", 4); + + // Free temp memory + free(mMoovBoxBuffer); + mMoovBoxBuffer = NULL; + mMoovBoxBufferOffset = 0; + } + CHECK(mBoxes.empty()); + fflush(mFile); fclose(mFile); mFile = NULL; } -off_t MPEG4Writer::addSample(MediaBuffer *buffer) { - Mutex::Autolock autoLock(mLock); +status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { + mInterleaveDurationUs = durationUs; + return OK; +} + +void MPEG4Writer::lock() { + mLock.lock(); +} +void MPEG4Writer::unlock() { + mLock.unlock(); +} + +off_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { off_t old_offset = mOffset; fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), @@ -213,31 +319,90 @@ off_t MPEG4Writer::addSample(MediaBuffer *buffer) { return old_offset; } -off_t MPEG4Writer::addLengthPrefixedSample(MediaBuffer *buffer) { - Mutex::Autolock autoLock(mLock); +static void StripStartcode(MediaBuffer *buffer) { + if (buffer->range_length() < 4) { + return; + } + + const uint8_t *ptr = + (const uint8_t *)buffer->data() + buffer->range_offset(); + + if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { + buffer->set_range( + buffer->range_offset() + 4, buffer->range_length() - 4); + } +} +off_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { off_t old_offset = mOffset; size_t length = buffer->range_length(); + +#if USE_NALLEN_FOUR + uint8_t x = length >> 24; + fwrite(&x, 1, 1, mFile); + x = (length >> 16) & 0xff; + fwrite(&x, 1, 1, mFile); + x = (length >> 8) & 0xff; + fwrite(&x, 1, 1, mFile); + x = length & 0xff; + fwrite(&x, 1, 1, mFile); +#else CHECK(length < 65536); uint8_t x = length >> 8; fwrite(&x, 1, 1, mFile); x = length & 0xff; fwrite(&x, 1, 1, mFile); +#endif fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 1, length, mFile); +#if USE_NALLEN_FOUR + mOffset += length + 4; +#else mOffset += length + 2; +#endif return old_offset; } +size_t MPEG4Writer::write( + const void *ptr, size_t size, size_t nmemb, FILE *stream) { + + const size_t bytes = size * nmemb; + if (mWriteMoovBoxToMemory) { + if (8 + mMoovBoxBufferOffset + bytes > mEstimatedMoovBoxSize) { + for (List::iterator it = mBoxes.begin(); + it != mBoxes.end(); ++it) { + (*it) += mOffset; + } + fseeko(mFile, mOffset, SEEK_SET); + fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); + fwrite(ptr, size, nmemb, stream); + mOffset += (bytes + mMoovBoxBufferOffset); + free(mMoovBoxBuffer); + mMoovBoxBuffer = NULL; + mMoovBoxBufferOffset = 0; + mWriteMoovBoxToMemory = false; + mStreamableFile = false; + } else { + memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); + mMoovBoxBufferOffset += bytes; + } + } else { + fwrite(ptr, size, nmemb, stream); + mOffset += bytes; + } + return bytes; +} + void MPEG4Writer::beginBox(const char *fourcc) { CHECK_EQ(strlen(fourcc), 4); - mBoxes.push_back(mOffset); + mBoxes.push_back(mWriteMoovBoxToMemory? + mMoovBoxBufferOffset: mOffset); writeInt32(0); writeFourcc(fourcc); @@ -249,51 +414,77 @@ void MPEG4Writer::endBox() { off_t offset = *--mBoxes.end(); mBoxes.erase(--mBoxes.end()); - fseek(mFile, offset, SEEK_SET); - writeInt32(mOffset - offset); - mOffset -= 4; - fseek(mFile, mOffset, SEEK_SET); + if (mWriteMoovBoxToMemory) { + int32_t x = htonl(mMoovBoxBufferOffset - offset); + memcpy(mMoovBoxBuffer + offset, &x, 4); + } else { + fseeko(mFile, offset, SEEK_SET); + writeInt32(mOffset - offset); + mOffset -= 4; + fseeko(mFile, mOffset, SEEK_SET); + } } void MPEG4Writer::writeInt8(int8_t x) { - fwrite(&x, 1, 1, mFile); - ++mOffset; + write(&x, 1, 1, mFile); } void MPEG4Writer::writeInt16(int16_t x) { x = htons(x); - fwrite(&x, 1, 2, mFile); - mOffset += 2; + write(&x, 1, 2, mFile); } void MPEG4Writer::writeInt32(int32_t x) { x = htonl(x); - fwrite(&x, 1, 4, mFile); - mOffset += 4; + write(&x, 1, 4, mFile); } void MPEG4Writer::writeInt64(int64_t x) { x = hton64(x); - fwrite(&x, 1, 8, mFile); - mOffset += 8; + write(&x, 1, 8, mFile); } void MPEG4Writer::writeCString(const char *s) { size_t n = strlen(s); - - fwrite(s, 1, n + 1, mFile); - mOffset += n + 1; + write(s, 1, n + 1, mFile); } void MPEG4Writer::writeFourcc(const char *s) { CHECK_EQ(strlen(s), 4); - fwrite(s, 1, 4, mFile); - mOffset += 4; + write(s, 1, 4, mFile); } void MPEG4Writer::write(const void *data, size_t size) { - fwrite(data, 1, size, mFile); - mOffset += size; + write(data, 1, size, mFile); +} + +bool MPEG4Writer::exceedsFileSizeLimit() { + // No limit + if (mMaxFileSizeLimitBytes == 0) { + return false; + } + + int64_t nTotalBytesEstimate = static_cast(mEstimatedMoovBoxSize); + for (List::iterator it = mTracks.begin(); + it != mTracks.end(); ++it) { + nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); + } + return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes); +} + +bool MPEG4Writer::exceedsFileDurationLimit() { + // No limit + if (mMaxFileDurationLimitUs == 0) { + return false; + } + + for (List::iterator it = mTracks.begin(); + it != mTracks.end(); ++it) { + if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { + return true; + } + } + return false; } bool MPEG4Writer::reachedEOS() { @@ -309,6 +500,21 @@ bool MPEG4Writer::reachedEOS() { return allDone; } +void MPEG4Writer::setStartTimestamp(int64_t timeUs) { + LOGI("setStartTimestamp: %lld", timeUs); + Mutex::Autolock autoLock(mLock); + if (mStartTimestampUs != 0) { + return; // Sorry, too late + } + mStartTimestampUs = timeUs; +} + +int64_t MPEG4Writer::getStartTimestamp() { + LOGI("getStartTimestamp: %lld", mStartTimestampUs); + Mutex::Autolock autoLock(mLock); + return mStartTimestampUs; +} + //////////////////////////////////////////////////////////////////////////////// MPEG4Writer::Track::Track( @@ -318,8 +524,11 @@ MPEG4Writer::Track::Track( mSource(source), mDone(false), mMaxTimeStampUs(0), + mEstimatedTrackSizeBytes(0), + mSamplesHaveSameSize(true), mCodecSpecificData(NULL), mCodecSpecificDataSize(0), + mGotAllCodecSpecificData(false), mReachedEOS(false) { } @@ -347,6 +556,7 @@ status_t MPEG4Writer::Track::start() { mDone = false; mMaxTimeStampUs = 0; mReachedEOS = false; + mEstimatedTrackSizeBytes = 0; pthread_create(&mThread, &attr, ThreadWrapper, this); pthread_attr_destroy(&attr); @@ -380,73 +590,163 @@ void *MPEG4Writer::Track::ThreadWrapper(void *me) { return NULL; } +#include +static void hexdump(const void *_data, size_t size) { + const uint8_t *data = (const uint8_t *)_data; + size_t offset = 0; + while (offset < size) { + printf("0x%04x ", offset); + + size_t n = size - offset; + if (n > 16) { + n = 16; + } + + for (size_t i = 0; i < 16; ++i) { + if (i == 8) { + printf(" "); + } + + if (offset + i < size) { + printf("%02x ", data[offset + i]); + } else { + printf(" "); + } + } + + printf(" "); + + for (size_t i = 0; i < n; ++i) { + if (isprint(data[offset + i])) { + printf("%c", data[offset + i]); + } else { + printf("."); + } + } + + printf("\n"); + + offset += 16; + } +} + + +status_t MPEG4Writer::Track::makeAVCCodecSpecificData( + const uint8_t *data, size_t size) { + // hexdump(data, size); + + if (mCodecSpecificData != NULL) { + LOGE("Already have codec specific data"); + return ERROR_MALFORMED; + } + + if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) { + LOGE("Must start with a start code"); + return ERROR_MALFORMED; + } + + size_t picParamOffset = 4; + while (picParamOffset + 3 < size + && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) { + ++picParamOffset; + } + + if (picParamOffset + 3 >= size) { + LOGE("Could not find start-code for pictureParameterSet"); + return ERROR_MALFORMED; + } + + size_t seqParamSetLength = picParamOffset - 4; + size_t picParamSetLength = size - picParamOffset - 4; + + mCodecSpecificDataSize = + 6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2; + + mCodecSpecificData = malloc(mCodecSpecificDataSize); + uint8_t *header = (uint8_t *)mCodecSpecificData; + header[0] = 1; + header[1] = 0x42; // profile + header[2] = 0x80; + header[3] = 0x1e; // level + +#if USE_NALLEN_FOUR + header[4] = 0xfc | 3; // length size == 4 bytes +#else + header[4] = 0xfc | 1; // length size == 2 bytes +#endif + + header[5] = 0xe0 | 1; + header[6] = seqParamSetLength >> 8; + header[7] = seqParamSetLength & 0xff; + memcpy(&header[8], &data[4], seqParamSetLength); + header += 8 + seqParamSetLength; + header[0] = 1; + header[1] = picParamSetLength >> 8; + header[2] = picParamSetLength & 0xff; + memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength); + + return OK; +} + void MPEG4Writer::Track::threadEntry() { sp meta = mSource->getFormat(); const char *mime; meta->findCString(kKeyMIMEType, &mime); - bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4); + bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || + !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); + bool is_audio = !strncasecmp(mime, "audio/", 6); int32_t count = 0; + const int64_t interleaveDurationUs = mOwner->interleaveDuration(); + int64_t chunkTimestampUs = 0; + int32_t nChunks = 0; + int32_t nZeroLengthFrames = 0; + int64_t lastTimestamp = 0; // Timestamp of the previous sample + int64_t lastDuration = 0; // Time spacing between the previous two samples + int32_t sampleCount = 1; // Sample count in the current stts table entry + uint32_t previousSampleSize = 0; // Size of the previous sample MediaBuffer *buffer; while (!mDone && mSource->read(&buffer) == OK) { if (buffer->range_length() == 0) { buffer->release(); buffer = NULL; - + ++nZeroLengthFrames; continue; } ++count; - if (is_avc && count < 3) { - size_t size = buffer->range_length(); - - switch (count) { - case 1: - { - CHECK_EQ(mCodecSpecificData, NULL); - mCodecSpecificData = malloc(size + 8); - uint8_t *header = (uint8_t *)mCodecSpecificData; - header[0] = 1; - header[1] = 0x42; // profile - header[2] = 0x80; - header[3] = 0x1e; // level - header[4] = 0xfc | 3; - header[5] = 0xe0 | 1; - header[6] = size >> 8; - header[7] = size & 0xff; - memcpy(&header[8], - (const uint8_t *)buffer->data() + buffer->range_offset(), - size); - - mCodecSpecificDataSize = size + 8; - break; - } - - case 2: - { - size_t offset = mCodecSpecificDataSize; - mCodecSpecificDataSize += size + 3; - mCodecSpecificData = realloc(mCodecSpecificData, mCodecSpecificDataSize); - uint8_t *header = (uint8_t *)mCodecSpecificData; - header[offset] = 1; - header[offset + 1] = size >> 8; - header[offset + 2] = size & 0xff; - memcpy(&header[offset + 3], - (const uint8_t *)buffer->data() + buffer->range_offset(), - size); - break; - } + int32_t isCodecConfig; + if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) + && isCodecConfig) { + CHECK(!mGotAllCodecSpecificData); + + if (is_avc) { + status_t err = makeAVCCodecSpecificData( + (const uint8_t *)buffer->data() + + buffer->range_offset(), + buffer->range_length()); + CHECK_EQ(OK, err); + } else if (is_mpeg4) { + mCodecSpecificDataSize = buffer->range_length(); + mCodecSpecificData = malloc(mCodecSpecificDataSize); + memcpy(mCodecSpecificData, + (const uint8_t *)buffer->data() + + buffer->range_offset(), + buffer->range_length()); } buffer->release(); buffer = NULL; + mGotAllCodecSpecificData = true; continue; - } + } else if (!mGotAllCodecSpecificData && + count == 1 && is_mpeg4 && mCodecSpecificData == NULL) { + // The TI mpeg4 encoder does not properly set the + // codec-specific-data flag. - if (mCodecSpecificData == NULL && is_mpeg4) { const uint8_t *data = (const uint8_t *)buffer->data() + buffer->range_offset(); @@ -474,17 +774,90 @@ void MPEG4Writer::Track::threadEntry() { memcpy(mCodecSpecificData, data, offset); buffer->set_range(buffer->range_offset() + offset, size - offset); + + if (size == offset) { + buffer->release(); + buffer = NULL; + + continue; + } + + mGotAllCodecSpecificData = true; + } else if (!mGotAllCodecSpecificData && is_avc && count < 3) { + // The TI video encoder does not flag codec specific data + // as such and also splits up SPS and PPS across two buffers. + + const uint8_t *data = + (const uint8_t *)buffer->data() + buffer->range_offset(); + + size_t size = buffer->range_length(); + + CHECK(count == 2 || mCodecSpecificData == NULL); + + size_t offset = mCodecSpecificDataSize; + mCodecSpecificDataSize += size + 4; + mCodecSpecificData = + realloc(mCodecSpecificData, mCodecSpecificDataSize); + + memcpy((uint8_t *)mCodecSpecificData + offset, + "\x00\x00\x00\x01", 4); + + memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size); + + buffer->release(); + buffer = NULL; + + if (count == 2) { + void *tmp = mCodecSpecificData; + size = mCodecSpecificDataSize; + mCodecSpecificData = NULL; + mCodecSpecificDataSize = 0; + + status_t err = makeAVCCodecSpecificData( + (const uint8_t *)tmp, size); + free(tmp); + tmp = NULL; + CHECK_EQ(OK, err); + + mGotAllCodecSpecificData = true; + } + + continue; } - off_t offset = is_avc ? mOwner->addLengthPrefixedSample(buffer) - : mOwner->addSample(buffer); + if (is_avc) StripStartcode(buffer); SampleInfo info; - info.size = is_avc ? buffer->range_length() + 2 : buffer->range_length(); - info.offset = offset; + info.size = is_avc +#if USE_NALLEN_FOUR + ? buffer->range_length() + 4 +#else + ? buffer->range_length() + 2 +#endif + : buffer->range_length(); + + // Max file size or duration handling + mEstimatedTrackSizeBytes += info.size; + if (mOwner->exceedsFileSizeLimit()) { + buffer->release(); + buffer = NULL; + mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); + break; + } + if (mOwner->exceedsFileDurationLimit()) { + buffer->release(); + buffer = NULL; + mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); + break; + } + int64_t timestampUs; CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); + if (mSampleInfos.empty()) { + mOwner->setStartTimestamp(timestampUs); + mStartTimestampUs = (timestampUs - mOwner->getStartTimestamp()); + } if (timestampUs > mMaxTimeStampUs) { mMaxTimeStampUs = timestampUs; @@ -492,20 +865,121 @@ void MPEG4Writer::Track::threadEntry() { // Our timestamp is in ms. info.timestamp = (timestampUs + 500) / 1000; - mSampleInfos.push_back(info); + if (mSampleInfos.size() > 2) { + if (lastDuration != info.timestamp - lastTimestamp) { + SttsTableEntry sttsEntry(sampleCount, lastDuration); + mSttsTableEntries.push_back(sttsEntry); + sampleCount = 1; + } else { + ++sampleCount; + } + } + if (mSamplesHaveSameSize) { + if (mSampleInfos.size() >= 2 && previousSampleSize != info.size) { + mSamplesHaveSameSize = false; + } + previousSampleSize = info.size; + } + lastDuration = info.timestamp - lastTimestamp; + lastTimestamp = info.timestamp; + +//////////////////////////////////////////////////////////////////////////////// + // Make a deep copy of the MediaBuffer less Metadata + MediaBuffer *copy = new MediaBuffer(buffer->range_length()); + memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), + buffer->range_length()); + copy->set_range(0, buffer->range_length()); + + mChunkSamples.push_back(copy); + if (interleaveDurationUs == 0) { + StscTableEntry stscEntry(++nChunks, 1, 1); + mStscTableEntries.push_back(stscEntry); + writeOneChunk(is_avc); + } else { + if (chunkTimestampUs == 0) { + chunkTimestampUs = timestampUs; + } else { + if (timestampUs - chunkTimestampUs > interleaveDurationUs) { + ++nChunks; + if (nChunks == 1 || // First chunk + (--(mStscTableEntries.end()))->samplesPerChunk != + mChunkSamples.size()) { + StscTableEntry stscEntry(nChunks, + mChunkSamples.size(), 1); + mStscTableEntries.push_back(stscEntry); + } + writeOneChunk(is_avc); + chunkTimestampUs = timestampUs; + } + } + } + + int32_t isSync = false; + if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync) && + isSync != 0) { + mStssTableEntries.push_back(mSampleInfos.size()); + } buffer->release(); buffer = NULL; } + if (mSampleInfos.empty()) { + mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_STOP_PREMATURELY, 0); + } + + // Last chunk + if (!mChunkSamples.empty()) { + ++nChunks; + StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1); + mStscTableEntries.push_back(stscEntry); + writeOneChunk(is_avc); + } + + // We don't really know how long the last frame lasts, since + // there is no frame time after it, just repeat the previous + // frame's duration. + if (mSampleInfos.size() == 1) { + lastDuration = 0; // A single sample's duration + } else { + ++sampleCount; // Count for the last sample + } + SttsTableEntry sttsEntry(sampleCount, lastDuration); + mSttsTableEntries.push_back(sttsEntry); mReachedEOS = true; + LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s", + count, nZeroLengthFrames, mSampleInfos.size(), is_audio? "audio": "video"); +} + +void MPEG4Writer::Track::writeOneChunk(bool isAvc) { + mOwner->lock(); + for (List::iterator it = mChunkSamples.begin(); + it != mChunkSamples.end(); ++it) { + off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it) + : mOwner->addSample_l(*it); + if (it == mChunkSamples.begin()) { + mChunkOffsets.push_back(offset); + } + } + mOwner->unlock(); + while (!mChunkSamples.empty()) { + List::iterator it = mChunkSamples.begin(); + (*it)->release(); + (*it) = NULL; + mChunkSamples.erase(it); + } + mChunkSamples.clear(); } int64_t MPEG4Writer::Track::getDurationUs() const { return mMaxTimeStampUs; } +int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { + return mEstimatedTrackSizeBytes; +} + void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { const char *mime; bool success = mMeta->findCString(kKeyMIMEType, &mime); @@ -550,11 +1024,24 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { success = success && mMeta->findInt32(kKeyHeight, &height); CHECK(success); - mOwner->writeInt32(width); - mOwner->writeInt32(height); + mOwner->writeInt32(width << 16); // 32-bit fixed-point value + mOwner->writeInt32(height << 16); // 32-bit fixed-point value } mOwner->endBox(); // tkhd + if (mStartTimestampUs != 0) { + mOwner->beginBox("edts"); + mOwner->writeInt32(0); // version=0, flags=0 + mOwner->beginBox("elst"); + mOwner->writeInt32(0); // version=0, flags=0 + mOwner->writeInt32(1); // a single entry + mOwner->writeInt32(mStartTimestampUs / 1000); // edit duration + mOwner->writeInt32(-1); // empty edit box to signal starting time offset + mOwner->writeInt32(1); // x1 rate + mOwner->endBox(); + mOwner->endBox(); + } + mOwner->beginBox("mdia"); mOwner->beginBox("mdhd"); @@ -569,26 +1056,15 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->beginBox("hdlr"); mOwner->writeInt32(0); // version=0, flags=0 - mOwner->writeInt32(0); // predefined - mOwner->writeFourcc(is_audio ? "soun" : "vide"); + mOwner->writeInt32(0); // component type: should be mhlr + mOwner->writeFourcc(is_audio ? "soun" : "vide"); // component subtype mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved - mOwner->writeCString(""); // name + mOwner->writeCString(is_audio ? "SoundHandler": ""); // name mOwner->endBox(); mOwner->beginBox("minf"); - - mOwner->beginBox("dinf"); - mOwner->beginBox("dref"); - mOwner->writeInt32(0); // version=0, flags=0 - mOwner->writeInt32(1); - mOwner->beginBox("url "); - mOwner->writeInt32(1); // version=0, flags=1 - mOwner->endBox(); // url - mOwner->endBox(); // dref - mOwner->endBox(); // dinf - if (is_audio) { mOwner->beginBox("smhd"); mOwner->writeInt32(0); // version=0, flags=0 @@ -604,7 +1080,18 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->writeInt16(0); mOwner->endBox(); } - mOwner->endBox(); // minf + + mOwner->beginBox("dinf"); + mOwner->beginBox("dref"); + mOwner->writeInt32(0); // version=0, flags=0 + mOwner->writeInt32(1); + mOwner->beginBox("url "); + mOwner->writeInt32(1); // version=0, flags=1 + mOwner->endBox(); // url + mOwner->endBox(); // dref + mOwner->endBox(); // dinf + + mOwner->endBox(); // minf mOwner->beginBox("stbl"); @@ -617,6 +1104,8 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { fourcc = "samr"; } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { fourcc = "sawb"; + } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { + fourcc = "mp4a"; } else { LOGE("Unknown mime type '%s'.", mime); CHECK(!"should not be here, unknown mime type."); @@ -625,10 +1114,12 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->beginBox(fourcc); // audio format mOwner->writeInt32(0); // reserved mOwner->writeInt16(0); // reserved - mOwner->writeInt16(0); // data ref index + mOwner->writeInt16(0x1); // data ref index mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved - mOwner->writeInt16(2); // channel count + int32_t nChannels; + CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); + mOwner->writeInt16(nChannels); // channel count mOwner->writeInt16(16); // sample size mOwner->writeInt16(0); // predefined mOwner->writeInt16(0); // reserved @@ -638,6 +1129,38 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { CHECK(success); mOwner->writeInt32(samplerate << 16); + if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { + mOwner->beginBox("esds"); + + mOwner->writeInt32(0); // version=0, flags=0 + mOwner->writeInt8(0x03); // ES_DescrTag + mOwner->writeInt8(23 + mCodecSpecificDataSize); + mOwner->writeInt16(0x0000);// ES_ID + mOwner->writeInt8(0x00); + + mOwner->writeInt8(0x04); // DecoderConfigDescrTag + mOwner->writeInt8(15 + mCodecSpecificDataSize); + mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 + mOwner->writeInt8(0x15); // streamType AudioStream + + mOwner->writeInt16(0x03); // XXX + mOwner->writeInt8(0x00); // buffer size 24-bit + mOwner->writeInt32(96000); // max bit rate + mOwner->writeInt32(96000); // avg bit rate + + mOwner->writeInt8(0x05); // DecoderSpecificInfoTag + mOwner->writeInt8(mCodecSpecificDataSize); + mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); + + static const uint8_t kData2[] = { + 0x06, // SLConfigDescriptorTag + 0x01, + 0x02 + }; + mOwner->write(kData2, sizeof(kData2)); + + mOwner->endBox(); // esds + } mOwner->endBox(); } else { if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { @@ -698,7 +1221,7 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { 0x00, 0x03, 0xe8, 0x00 }; mOwner->write(kData, sizeof(kData)); - + mOwner->writeInt8(0x05); // DecoderSpecificInfoTag mOwner->writeInt8(mCodecSpecificDataSize); @@ -733,49 +1256,59 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->beginBox("stts"); mOwner->writeInt32(0); // version=0, flags=0 - mOwner->writeInt32(mSampleInfos.size() - 1); - - List::iterator it = mSampleInfos.begin(); - int64_t last = (*it).timestamp; - ++it; - while (it != mSampleInfos.end()) { - mOwner->writeInt32(1); - mOwner->writeInt32((*it).timestamp - last); - - last = (*it).timestamp; - - ++it; + mOwner->writeInt32(mSttsTableEntries.size()); + for (List::iterator it = mSttsTableEntries.begin(); + it != mSttsTableEntries.end(); ++it) { + mOwner->writeInt32(it->sampleCount); + mOwner->writeInt32(it->sampleDuration); } mOwner->endBox(); // stts + if (!is_audio) { + mOwner->beginBox("stss"); + mOwner->writeInt32(0); // version=0, flags=0 + mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames + for (List::iterator it = mStssTableEntries.begin(); + it != mStssTableEntries.end(); ++it) { + mOwner->writeInt32(*it); + } + mOwner->endBox(); // stss + } + mOwner->beginBox("stsz"); mOwner->writeInt32(0); // version=0, flags=0 - mOwner->writeInt32(0); // default sample size + if (mSamplesHaveSameSize) { + List::iterator it = mSampleInfos.begin(); + mOwner->writeInt32(it->size); // default sample size + } else { + mOwner->writeInt32(0); + } mOwner->writeInt32(mSampleInfos.size()); - for (List::iterator it = mSampleInfos.begin(); - it != mSampleInfos.end(); ++it) { - mOwner->writeInt32((*it).size); + if (!mSamplesHaveSameSize) { + for (List::iterator it = mSampleInfos.begin(); + it != mSampleInfos.end(); ++it) { + mOwner->writeInt32((*it).size); + } } mOwner->endBox(); // stsz mOwner->beginBox("stsc"); mOwner->writeInt32(0); // version=0, flags=0 - mOwner->writeInt32(mSampleInfos.size()); - int32_t n = 1; - for (List::iterator it = mSampleInfos.begin(); - it != mSampleInfos.end(); ++it, ++n) { - mOwner->writeInt32(n); - mOwner->writeInt32(1); - mOwner->writeInt32(1); + mOwner->writeInt32(mStscTableEntries.size()); + for (List::iterator it = mStscTableEntries.begin(); + it != mStscTableEntries.end(); ++it) { + mOwner->writeInt32(it->firstChunk); + mOwner->writeInt32(it->samplesPerChunk); + mOwner->writeInt32(it->sampleDescriptionId); } mOwner->endBox(); // stsc mOwner->beginBox("co64"); mOwner->writeInt32(0); // version=0, flags=0 - mOwner->writeInt32(mSampleInfos.size()); - for (List::iterator it = mSampleInfos.begin(); - it != mSampleInfos.end(); ++it, ++n) { - mOwner->writeInt64((*it).offset); + mOwner->writeInt32(mChunkOffsets.size()); + for (List::iterator it = mChunkOffsets.begin(); + it != mChunkOffsets.end(); ++it) { + mOwner->writeInt64((*it)); } mOwner->endBox(); // co64 diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp index 4b3813b69cd9124321c052e00e253629f3f09cb3..327a0ce99d84b00d5a6072b02428e7daa0782adb 100644 --- a/media/libstagefright/MediaDefs.cpp +++ b/media/libstagefright/MediaDefs.cpp @@ -20,6 +20,7 @@ namespace android { const char *MEDIA_MIMETYPE_IMAGE_JPEG = "image/jpeg"; +const char *MEDIA_MIMETYPE_VIDEO_VPX = "video/x-vnd.on2.vp8"; const char *MEDIA_MIMETYPE_VIDEO_AVC = "video/avc"; const char *MEDIA_MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es"; const char *MEDIA_MIMETYPE_VIDEO_H263 = "video/3gpp"; @@ -36,5 +37,6 @@ const char *MEDIA_MIMETYPE_AUDIO_RAW = "audio/raw"; const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mpeg4"; const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/wav"; const char *MEDIA_MIMETYPE_CONTAINER_OGG = "application/ogg"; +const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA = "video/x-matroska"; } // namespace android diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp index 513f49c88b46cdd0890d11c903209c968329db77..376d715dc1960f263a3526429c5fbaf5ed234930 100644 --- a/media/libstagefright/MediaExtractor.cpp +++ b/media/libstagefright/MediaExtractor.cpp @@ -24,6 +24,8 @@ #include "include/WAVExtractor.h" #include "include/OggExtractor.h" +#include "matroska/MatroskaExtractor.h" + #include #include #include @@ -69,6 +71,8 @@ sp MediaExtractor::Create( return new WAVExtractor(source); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_OGG)) { return new OggExtractor(source); + } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MATROSKA)) { + return new MatroskaExtractor(source); } return NULL; diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 69da7efe691534e15a316f68fac10e8f01e20ebf..66011ca92d4dcac16c41ac81e8643f14ce84c72a 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -19,13 +19,16 @@ #include #include "include/AACDecoder.h" +#include "include/AACEncoder.h" #include "include/AMRNBDecoder.h" #include "include/AMRNBEncoder.h" #include "include/AMRWBDecoder.h" +#include "include/AMRWBEncoder.h" #include "include/AVCDecoder.h" #include "include/M4vH263Decoder.h" #include "include/MP3Decoder.h" #include "include/VorbisDecoder.h" +#include "include/VPXDecoder.h" #include "include/ESDS.h" @@ -60,6 +63,11 @@ static sp Make##name(const sp &source) { \ return new name(source); \ } +#define FACTORY_CREATE_ENCODER(name) \ +static sp Make##name(const sp &source, const sp &meta) { \ + return new name(source, meta); \ +} + #define FACTORY_REF(name) { #name, Make##name }, FACTORY_CREATE(MP3Decoder) @@ -69,7 +77,33 @@ FACTORY_CREATE(AACDecoder) FACTORY_CREATE(AVCDecoder) FACTORY_CREATE(M4vH263Decoder) FACTORY_CREATE(VorbisDecoder) -FACTORY_CREATE(AMRNBEncoder) +FACTORY_CREATE(VPXDecoder) +FACTORY_CREATE_ENCODER(AMRNBEncoder) +FACTORY_CREATE_ENCODER(AMRWBEncoder) +FACTORY_CREATE_ENCODER(AACEncoder) + +static sp InstantiateSoftwareEncoder( + const char *name, const sp &source, + const sp &meta) { + struct FactoryInfo { + const char *name; + sp (*CreateFunc)(const sp &, const sp &); + }; + + static const FactoryInfo kFactoryInfo[] = { + FACTORY_REF(AMRNBEncoder) + FACTORY_REF(AMRWBEncoder) + FACTORY_REF(AACEncoder) + }; + for (size_t i = 0; + i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) { + if (!strcmp(name, kFactoryInfo[i].name)) { + return (*kFactoryInfo[i].CreateFunc)(source, meta); + } + } + + return NULL; +} static sp InstantiateSoftwareCodec( const char *name, const sp &source) { @@ -86,7 +120,7 @@ static sp InstantiateSoftwareCodec( FACTORY_REF(AVCDecoder) FACTORY_REF(M4vH263Decoder) FACTORY_REF(VorbisDecoder) - FACTORY_REF(AMRNBEncoder) + FACTORY_REF(VPXDecoder) }; for (size_t i = 0; i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) { @@ -127,13 +161,16 @@ static const CodecInfo kDecoderInfo[] = { { MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" }, // { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcdec" }, { MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" }, + { MEDIA_MIMETYPE_VIDEO_VPX, "VPXDecoder" }, }; static const CodecInfo kEncoderInfo[] = { { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" }, { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBEncoder" }, { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" }, + { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" }, { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" }, + { MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" }, { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" }, @@ -141,6 +178,7 @@ static const CodecInfo kEncoderInfo[] = { { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" }, + { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" }, { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" }, { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" }, }; @@ -385,7 +423,8 @@ sp OMXCodec::Create( componentName = matchingCodecs[i].string(); #if BUILD_WITH_FULL_STAGEFRIGHT - sp softwareCodec = + sp softwareCodec = createEncoder? + InstantiateSoftwareEncoder(componentName, source, meta): InstantiateSoftwareCodec(componentName, source); if (softwareCodec != NULL) { @@ -510,19 +549,24 @@ status_t OMXCodec::configureCodec(const sp &meta) { } } + int32_t bitRate = 0; + if (mIsEncoder) { + CHECK(meta->findInt32(kKeyBitRate, &bitRate)); + } if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) { - setAMRFormat(false /* isWAMR */); + setAMRFormat(false /* isWAMR */, bitRate); } if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) { - setAMRFormat(true /* isWAMR */); + setAMRFormat(true /* isWAMR */, bitRate); } if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) { int32_t numChannels, sampleRate; CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); - setAACFormat(numChannels, sampleRate); + setAACFormat(numChannels, sampleRate, bitRate); } + if (!strncasecmp(mMIME, "video/", 6)) { int32_t width, height; bool success = meta->findInt32(kKeyWidth, &width); @@ -570,7 +614,8 @@ status_t OMXCodec::configureCodec(const sp &meta) { } if (!strcmp(mComponentName, "OMX.TI.AMR.encode") - || !strcmp(mComponentName, "OMX.TI.WBAMR.encode")) { + || !strcmp(mComponentName, "OMX.TI.WBAMR.encode") + || !strcmp(mComponentName, "OMX.TI.AAC.encode")) { setMinBufferSize(kPortIndexOutput, 8192); // XXX } @@ -683,6 +728,7 @@ static size_t getFrameSize( case OMX_COLOR_FormatCbYCrY: return width * height * 2; + case OMX_COLOR_FormatYUV420Planar: case OMX_COLOR_FormatYUV420SemiPlanar: return (width * height * 3) / 2; @@ -713,61 +759,62 @@ void OMXCodec::setVideoInputFormat( colorFormat = OMX_COLOR_FormatYCbYCr; } - CHECK_EQ(setVideoPortFormatType( - kPortIndexInput, OMX_VIDEO_CodingUnused, - colorFormat), OK); - CHECK_EQ(setVideoPortFormatType( - kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused), - OK); + status_t err; OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - def.nPortIndex = kPortIndexOutput; - OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + //////////////////////// Input port ///////////////////////// + CHECK_EQ(setVideoPortFormatType( + kPortIndexInput, OMX_VIDEO_CodingUnused, + colorFormat), OK); + InitOMXParams(&def); + def.nPortIndex = kPortIndexInput; + err = mOMX->getParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); CHECK_EQ(err, OK); + + def.nBufferSize = getFrameSize(colorFormat, width, height); + CHECK_EQ(def.eDomain, OMX_PortDomainVideo); video_def->nFrameWidth = width; video_def->nFrameHeight = height; + video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; + video_def->eColorFormat = colorFormat; - video_def->eCompressionFormat = compressionFormat; - video_def->eColorFormat = OMX_COLOR_FormatUnused; + video_def->xFramerate = (24 << 16); // Q16 format err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); CHECK_EQ(err, OK); - //////////////////////////////////////////////////////////////////////////// - + //////////////////////// Output port ///////////////////////// + CHECK_EQ(setVideoPortFormatType( + kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused), + OK); InitOMXParams(&def); - def.nPortIndex = kPortIndexInput; + def.nPortIndex = kPortIndexOutput; err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - CHECK_EQ(err, OK); - - def.nBufferSize = getFrameSize(colorFormat, width, height); - CODEC_LOGV("Setting nBufferSize = %ld", def.nBufferSize); + CHECK_EQ(err, OK); CHECK_EQ(def.eDomain, OMX_PortDomainVideo); video_def->nFrameWidth = width; video_def->nFrameHeight = height; - video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; - video_def->eColorFormat = colorFormat; - video_def->xFramerate = 24 << 16; // XXX crucial! + video_def->eCompressionFormat = compressionFormat; + video_def->eColorFormat = OMX_COLOR_FormatUnused; err = mOMX->setParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); CHECK_EQ(err, OK); + /////////////////// Codec-specific //////////////////////// switch (compressionFormat) { case OMX_VIDEO_CodingMPEG4: { @@ -889,8 +936,6 @@ status_t OMXCodec::setupAVCEncoderParameters() { h264type.bEnableFMO = OMX_FALSE; h264type.bEnableASO = OMX_FALSE; h264type.bEnableRS = OMX_FALSE; - h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; - h264type.eLevel = OMX_VIDEO_AVCLevel1b; h264type.bFrameMBsOnly = OMX_TRUE; h264type.bMBAFF = OMX_FALSE; h264type.bEntropyCodingCABAC = OMX_FALSE; @@ -915,7 +960,7 @@ status_t OMXCodec::setupAVCEncoderParameters() { CHECK_EQ(err, OK); bitrateType.eControlRate = OMX_Video_ControlRateVariable; - bitrateType.nTargetBitrate = 1000000; + bitrateType.nTargetBitrate = 3000000; err = mOMX->setParameter( mNode, OMX_IndexParamVideoBitrate, @@ -2128,11 +2173,24 @@ void OMXCodec::setState(State newState) { void OMXCodec::setRawAudioFormat( OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { + + // port definition + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + def.nPortIndex = portIndex; + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + CHECK_EQ(err, OK); + def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition, + &def, sizeof(def)), OK); + + // pcm param OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; InitOMXParams(&pcmParams); pcmParams.nPortIndex = portIndex; - status_t err = mOMX->getParameter( + err = mOMX->getParameter( mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); CHECK_EQ(err, OK); @@ -2159,7 +2217,51 @@ void OMXCodec::setRawAudioFormat( CHECK_EQ(err, OK); } -void OMXCodec::setAMRFormat(bool isWAMR) { +static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) { + if (isAMRWB) { + if (bps <= 6600) { + return OMX_AUDIO_AMRBandModeWB0; + } else if (bps <= 8850) { + return OMX_AUDIO_AMRBandModeWB1; + } else if (bps <= 12650) { + return OMX_AUDIO_AMRBandModeWB2; + } else if (bps <= 14250) { + return OMX_AUDIO_AMRBandModeWB3; + } else if (bps <= 15850) { + return OMX_AUDIO_AMRBandModeWB4; + } else if (bps <= 18250) { + return OMX_AUDIO_AMRBandModeWB5; + } else if (bps <= 19850) { + return OMX_AUDIO_AMRBandModeWB6; + } else if (bps <= 23050) { + return OMX_AUDIO_AMRBandModeWB7; + } + + // 23850 bps + return OMX_AUDIO_AMRBandModeWB8; + } else { // AMRNB + if (bps <= 4750) { + return OMX_AUDIO_AMRBandModeNB0; + } else if (bps <= 5150) { + return OMX_AUDIO_AMRBandModeNB1; + } else if (bps <= 5900) { + return OMX_AUDIO_AMRBandModeNB2; + } else if (bps <= 6700) { + return OMX_AUDIO_AMRBandModeNB3; + } else if (bps <= 7400) { + return OMX_AUDIO_AMRBandModeNB4; + } else if (bps <= 7950) { + return OMX_AUDIO_AMRBandModeNB5; + } else if (bps <= 10200) { + return OMX_AUDIO_AMRBandModeNB6; + } + + // 12200 bps + return OMX_AUDIO_AMRBandModeNB7; + } +} + +void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) { OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput; OMX_AUDIO_PARAM_AMRTYPE def; @@ -2172,9 +2274,8 @@ void OMXCodec::setAMRFormat(bool isWAMR) { CHECK_EQ(err, OK); def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; - def.eAMRBandMode = - isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0; + def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate); err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); CHECK_EQ(err, OK); @@ -2191,9 +2292,61 @@ void OMXCodec::setAMRFormat(bool isWAMR) { } } -void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) { +void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) { + CHECK(numChannels == 1 || numChannels == 2); if (mIsEncoder) { + //////////////// input port //////////////////// setRawAudioFormat(kPortIndexInput, sampleRate, numChannels); + + //////////////// output port //////////////////// + // format + OMX_AUDIO_PARAM_PORTFORMATTYPE format; + format.nPortIndex = kPortIndexOutput; + format.nIndex = 0; + status_t err = OMX_ErrorNone; + while (OMX_ErrorNone == err) { + CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat, + &format, sizeof(format)), OK); + if (format.eEncoding == OMX_AUDIO_CodingAAC) { + break; + } + format.nIndex++; + } + CHECK_EQ(OK, err); + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat, + &format, sizeof(format)), OK); + + // port definition + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + def.nPortIndex = kPortIndexOutput; + CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, + &def, sizeof(def)), OK); + def.format.audio.bFlagErrorConcealment = OMX_TRUE; + def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition, + &def, sizeof(def)), OK); + + // profile + OMX_AUDIO_PARAM_AACPROFILETYPE profile; + InitOMXParams(&profile); + profile.nPortIndex = kPortIndexOutput; + CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac, + &profile, sizeof(profile)), OK); + profile.nChannels = numChannels; + profile.eChannelMode = (numChannels == 1? + OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo); + profile.nSampleRate = sampleRate; + profile.nBitRate = bitRate; + profile.nAudioBandWidth = 0; + profile.nFrameLength = 0; + profile.nAACtools = OMX_AUDIO_AACToolAll; + profile.nAACERtools = OMX_AUDIO_AACERNone; + profile.eAACProfile = OMX_AUDIO_AACObjectLC; + profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac, + &profile, sizeof(profile)), OK); + } else { OMX_AUDIO_PARAM_AACPROFILETYPE profile; InitOMXParams(&profile); @@ -2962,6 +3115,13 @@ void OMXCodec::initOutputFormat(const sp &inputFormat) { } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) { mOutputFormat->setCString( kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); + int32_t numChannels, sampleRate, bitRate; + inputFormat->findInt32(kKeyChannelCount, &numChannels); + inputFormat->findInt32(kKeySampleRate, &sampleRate); + inputFormat->findInt32(kKeyBitRate, &bitRate); + mOutputFormat->setInt32(kKeyChannelCount, numChannels); + mOutputFormat->setInt32(kKeySampleRate, sampleRate); + mOutputFormat->setInt32(kKeyBitRate, bitRate); } else { CHECK(!"Should not be here. Unknown audio encoding."); } diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp index d0d1b14b7eeef218c30b7e5948c2fcb8214e56d5..6013b6f38a34bbc1b76ffc1ad39328e1d50ed6b2 100644 --- a/media/libstagefright/OggExtractor.cpp +++ b/media/libstagefright/OggExtractor.cpp @@ -76,7 +76,9 @@ struct MyVorbisExtractor { status_t seekToOffset(off_t offset); status_t readNextPacket(MediaBuffer **buffer); - void init(); + status_t init(); + + sp getFileMetaData() { return mFileMeta; } private: struct Page { @@ -100,13 +102,17 @@ private: vorbis_comment mVc; sp mMeta; + sp mFileMeta; ssize_t readPage(off_t offset, Page *page); status_t findNextPage(off_t startOffset, off_t *pageOffset); - void verifyHeader( + status_t verifyHeader( MediaBuffer *buffer, uint8_t type); + void parseFileMetaData(); + void extractAlbumArt(const void *data, size_t size); + MyVorbisExtractor(const MyVorbisExtractor &); MyVorbisExtractor &operator=(const MyVorbisExtractor &); }; @@ -188,9 +194,14 @@ MyVorbisExtractor::MyVorbisExtractor(const sp &source) mNextLaceIndex(0), mFirstDataOffset(-1) { mCurrentPage.mNumSegments = 0; + + vorbis_info_init(&mVi); + vorbis_comment_init(&mVc); } MyVorbisExtractor::~MyVorbisExtractor() { + vorbis_comment_clear(&mVc); + vorbis_info_clear(&mVi); } sp MyVorbisExtractor::getFormat() const { @@ -297,6 +308,7 @@ ssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) { totalSize += page->mLace[i]; } +#if 0 String8 tmp; for (size_t i = 0; i < page->mNumSegments; ++i) { char x[32]; @@ -306,6 +318,7 @@ ssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) { } LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string()); +#endif return sizeof(header) + page->mNumSegments + totalSize; } @@ -421,47 +434,60 @@ status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { } } -void MyVorbisExtractor::init() { - vorbis_info_init(&mVi); - - vorbis_comment mVc; - +status_t MyVorbisExtractor::init() { mMeta = new MetaData; mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); MediaBuffer *packet; - CHECK_EQ(readNextPacket(&packet), OK); + status_t err; + if ((err = readNextPacket(&packet)) != OK) { + return err; + } LOGV("read packet of size %d\n", packet->range_length()); - verifyHeader(packet, 1); + err = verifyHeader(packet, 1); packet->release(); packet = NULL; + if (err != OK) { + return err; + } - CHECK_EQ(readNextPacket(&packet), OK); + if ((err = readNextPacket(&packet)) != OK) { + return err; + } LOGV("read packet of size %d\n", packet->range_length()); - verifyHeader(packet, 3); + err = verifyHeader(packet, 3); packet->release(); packet = NULL; + if (err != OK) { + return err; + } - CHECK_EQ(readNextPacket(&packet), OK); + if ((err = readNextPacket(&packet)) != OK) { + return err; + } LOGV("read packet of size %d\n", packet->range_length()); - verifyHeader(packet, 5); + err = verifyHeader(packet, 5); packet->release(); packet = NULL; + if (err != OK) { + return err; + } mFirstDataOffset = mOffset + mCurrentPageSize; + + return OK; } -void MyVorbisExtractor::verifyHeader( +status_t MyVorbisExtractor::verifyHeader( MediaBuffer *buffer, uint8_t type) { const uint8_t *data = (const uint8_t *)buffer->data() + buffer->range_offset(); size_t size = buffer->range_length(); - CHECK(size >= 7); - - CHECK_EQ(data[0], type); - CHECK(!memcmp(&data[1], "vorbis", 6)); + if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { + return ERROR_MALFORMED; + } ogg_buffer buf; buf.data = (uint8_t *)data; @@ -508,18 +534,26 @@ void MyVorbisExtractor::verifyHeader( case 3: { - CHECK_EQ(0, _vorbis_unpack_comment(&mVc, &bits)); + if (0 != _vorbis_unpack_comment(&mVc, &bits)) { + return ERROR_MALFORMED; + } + + parseFileMetaData(); break; } case 5: { - CHECK_EQ(0, _vorbis_unpack_books(&mVi, &bits)); + if (0 != _vorbis_unpack_books(&mVi, &bits)) { + return ERROR_MALFORMED; + } mMeta->setData(kKeyVorbisBooks, 0, data, size); break; } } + + return OK; } uint64_t MyVorbisExtractor::approxBitrate() { @@ -530,6 +564,192 @@ uint64_t MyVorbisExtractor::approxBitrate() { return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; } +void MyVorbisExtractor::parseFileMetaData() { + mFileMeta = new MetaData; + mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); + + struct { + const char *const mTag; + uint32_t mKey; + } kMap[] = { + { "TITLE", kKeyTitle }, + { "ARTIST", kKeyArtist }, + { "ALBUM", kKeyAlbum }, + { "COMPOSER", kKeyComposer }, + { "GENRE", kKeyGenre }, + { "AUTHOR", kKeyAuthor }, + { "TRACKNUMBER", kKeyCDTrackNumber }, + { "DISCNUMBER", kKeyDiscNumber }, + { "DATE", kKeyDate }, + { "LYRICIST", kKeyWriter }, + { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, + }; + + for (int i = 0; i < mVc.comments; ++i) { + const char *comment = mVc.user_comments[i]; + + for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { + size_t tagLen = strlen(kMap[j].mTag); + if (!strncasecmp(kMap[j].mTag, comment, tagLen) + && comment[tagLen] == '=') { + if (kMap[j].mKey == kKeyAlbumArt) { + extractAlbumArt( + &comment[tagLen + 1], + mVc.comment_lengths[i] - tagLen - 1); + } else { + mFileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); + } + } + } + + } + +#if 0 + for (int i = 0; i < mVc.comments; ++i) { + LOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); + } +#endif +} + +// The returned buffer should be free()d. +static uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) { + *outSize = 0; + + if ((size % 4) != 0) { + return NULL; + } + + size_t n = size; + size_t padding = 0; + if (n >= 1 && s[n - 1] == '=') { + padding = 1; + + if (n >= 2 && s[n - 2] == '=') { + padding = 2; + } + } + + size_t outLen = 3 * size / 4 - padding; + + *outSize = outLen; + + void *buffer = malloc(outLen); + + uint8_t *out = (uint8_t *)buffer; + size_t j = 0; + uint32_t accum = 0; + for (size_t i = 0; i < n; ++i) { + char c = s[i]; + unsigned value; + if (c >= 'A' && c <= 'Z') { + value = c - 'A'; + } else if (c >= 'a' && c <= 'z') { + value = 26 + c - 'a'; + } else if (c >= '0' && c <= '9') { + value = 52 + c - '0'; + } else if (c == '+') { + value = 62; + } else if (c == '/') { + value = 63; + } else if (c != '=') { + return NULL; + } else { + if (i < n - padding) { + return NULL; + } + + value = 0; + } + + accum = (accum << 6) | value; + + if (((i + 1) % 4) == 0) { + out[j++] = (accum >> 16); + + if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } + if (j < outLen) { out[j++] = accum & 0xff; } + + accum = 0; + } + } + + return (uint8_t *)buffer; +} + +void MyVorbisExtractor::extractAlbumArt(const void *data, size_t size) { + LOGV("extractAlbumArt from '%s'", (const char *)data); + + size_t flacSize; + uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize); + + if (flac == NULL) { + LOGE("malformed base64 encoded data."); + return; + } + + LOGV("got flac of size %d", flacSize); + + uint32_t picType; + uint32_t typeLen; + uint32_t descLen; + uint32_t dataLen; + char type[128]; + + if (flacSize < 8) { + goto exit; + } + + picType = U32_AT(flac); + + if (picType != 3) { + // This is not a front cover. + goto exit; + } + + typeLen = U32_AT(&flac[4]); + if (typeLen + 1 > sizeof(type)) { + goto exit; + } + + if (flacSize < 8 + typeLen) { + goto exit; + } + + memcpy(type, &flac[8], typeLen); + type[typeLen] = '\0'; + + LOGV("picType = %d, type = '%s'", picType, type); + + if (!strcmp(type, "-->")) { + // This is not inline cover art, but an external url instead. + goto exit; + } + + descLen = U32_AT(&flac[8 + typeLen]); + + if (flacSize < 32 + typeLen + descLen) { + goto exit; + } + + dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); + + if (flacSize < 32 + typeLen + descLen + dataLen) { + goto exit; + } + + LOGV("got image data, %d trailing bytes", + flacSize - 32 - typeLen - descLen - dataLen); + + mFileMeta->setData( + kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen); + + mFileMeta->setCString(kKeyAlbumArtMIME, type); + +exit: + free(flac); + flac = NULL; +} + //////////////////////////////////////////////////////////////////////////////// OggExtractor::OggExtractor(const sp &source) @@ -537,10 +757,11 @@ OggExtractor::OggExtractor(const sp &source) mInitCheck(NO_INIT), mImpl(NULL) { mImpl = new MyVorbisExtractor(mDataSource); - CHECK_EQ(mImpl->seekToOffset(0), OK); - mImpl->init(); + mInitCheck = mImpl->seekToOffset(0); - mInitCheck = OK; + if (mInitCheck == OK) { + mInitCheck = mImpl->init(); + } } OggExtractor::~OggExtractor() { @@ -570,15 +791,7 @@ sp OggExtractor::getTrackMetaData( } sp OggExtractor::getMetaData() { - sp meta = new MetaData; - - if (mInitCheck != OK) { - return meta; - } - - meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); - - return meta; + return mImpl->getFileMetaData(); } bool SniffOgg( diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp index 03287dd1fe4c50e796bd2fc18b0aa55b0332d772..282963887c05396f3a8b5db775d2234d3a4d1107 100644 --- a/media/libstagefright/StagefrightMediaScanner.cpp +++ b/media/libstagefright/StagefrightMediaScanner.cpp @@ -26,10 +26,6 @@ // Sonivox includes #include -// Ogg Vorbis includes -#include -#include - namespace android { StagefrightMediaScanner::StagefrightMediaScanner() @@ -42,7 +38,8 @@ static bool FileHasAcceptableExtension(const char *extension) { static const char *kValidExtensions[] = { ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2", ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac", - ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota" + ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota", + ".mkv", ".mka", ".webm" }; static const size_t kNumValidExtensions = sizeof(kValidExtensions) / sizeof(kValidExtensions[0]); @@ -102,48 +99,6 @@ static status_t HandleMIDI( return OK; } -static status_t HandleOGG( - const char *filename, MediaScannerClient *client) { - int duration; - - FILE *file = fopen(filename,"r"); - if (!file) - return UNKNOWN_ERROR; - - OggVorbis_File vf; - if (ov_open(file, &vf, NULL, 0) < 0) { - return UNKNOWN_ERROR; - } - - char **ptr=ov_comment(&vf,-1)->user_comments; - while(*ptr){ - char *val = strstr(*ptr, "="); - if (val) { - int keylen = val++ - *ptr; - char key[keylen + 1]; - strncpy(key, *ptr, keylen); - key[keylen] = 0; - if (!client->addStringTag(key, val)) goto failure; - } - ++ptr; - } - - // Duration - duration = ov_time_total(&vf, -1); - if (duration > 0) { - char buffer[20]; - sprintf(buffer, "%d", duration); - if (!client->addStringTag("duration", buffer)) goto failure; - } - - ov_clear(&vf); // this also closes the FILE - return OK; - -failure: - ov_clear(&vf); // this also closes the FILE - return UNKNOWN_ERROR; -} - status_t StagefrightMediaScanner::processFile( const char *path, const char *mimeType, MediaScannerClient &client) { @@ -175,10 +130,6 @@ status_t StagefrightMediaScanner::processFile( return HandleMIDI(path, &client); } - if (!strcasecmp(extension, ".ogg")) { - return HandleOGG(path, &client); - } - if (mRetriever->setDataSource(path) == OK && mRetriever->setMode( METADATA_MODE_METADATA_RETRIEVAL_ONLY) == OK) { diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index 258be74867483e02a606482f2467024ccfe814f7..9d89c20b6da88c1e7efb7ce3241d8cada444729f 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -378,6 +378,24 @@ void StagefrightMetadataRetriever::parseMetaData() { // The duration value is a string representing the duration in ms. sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000); mMetaData.add(METADATA_KEY_DURATION, String8(tmp)); + + if (numTracks == 1) { + const char *fileMIME; + CHECK(meta->findCString(kKeyMIMEType, &fileMIME)); + + if (!strcasecmp(fileMIME, "video/x-matroska")) { + sp trackMeta = mExtractor->getTrackMetaData(0); + const char *trackMIME; + CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME)); + + if (!strncasecmp("audio/", trackMIME, 6)) { + // The matroska file only contains a single audio track, + // rewrite its mime type. + mMetaData.add( + METADATA_KEY_MIMETYPE, String8("audio/x-matroska")); + } + } + } } diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d222cd9eb9e941f55d22edf6f6196976677dd9e1 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2010 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. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "AACEncoder" +#include + +#include "AACEncoder.h" +#include "voAAC.h" +#include "cmnMemory.h" + +#include +#include +#include +#include +#include + +namespace android { + +AACEncoder::AACEncoder(const sp &source, const sp &meta) + : mSource(source), + mMeta(meta), + mStarted(false), + mBufferGroup(NULL), + mInputBuffer(NULL), + mEncoderHandle(NULL), + mApiHandle(NULL), + mMemOperator(NULL) { +} + +status_t AACEncoder::initCheck() { + CHECK(mApiHandle == NULL && mEncoderHandle == NULL); + CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate)); + CHECK(mMeta->findInt32(kKeyChannelCount, &mChannels)); + CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate)); + + mApiHandle = new VO_AUDIO_CODECAPI; + CHECK(mApiHandle); + + if (VO_ERR_NONE != voGetAACEncAPI(mApiHandle)) { + LOGE("Failed to get api handle"); + return UNKNOWN_ERROR; + } + + mMemOperator = new VO_MEM_OPERATOR; + CHECK(mMemOperator != NULL); + mMemOperator->Alloc = cmnMemAlloc; + mMemOperator->Copy = cmnMemCopy; + mMemOperator->Free = cmnMemFree; + mMemOperator->Set = cmnMemSet; + mMemOperator->Check = cmnMemCheck; + + VO_CODEC_INIT_USERDATA userData; + memset(&userData, 0, sizeof(userData)); + userData.memflag = VO_IMF_USERMEMOPERATOR; + userData.memData = (VO_PTR) mMemOperator; + if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAAC, &userData)) { + LOGE("Failed to init AAC encoder"); + return UNKNOWN_ERROR; + } + if (OK != setAudioSpecificConfigData()) { + LOGE("Failed to configure AAC encoder"); + return UNKNOWN_ERROR; + } + + // Configure AAC encoder$ + AACENC_PARAM params; + memset(¶ms, 0, sizeof(params)); + params.sampleRate = mSampleRate; + params.bitRate = mBitRate; + params.nChannels = mChannels; + params.adtsUsed = 0; // For MP4 file, don't use adts format$ + if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AAC_ENCPARAM, ¶ms)) { + LOGE("Failed to set AAC encoder parameters"); + return UNKNOWN_ERROR; + } + + return OK; +} + +static status_t getSampleRateTableIndex(int32_t sampleRate, int32_t &index) { + static const int32_t kSampleRateTable[] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000 + }; + const int32_t tableSize = sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]); + for (int32_t i = 0; i < tableSize; ++i) { + if (sampleRate == kSampleRateTable[i]) { + index = i; + return OK; + } + } + + LOGE("Sampling rate %d bps is not supported", sampleRate); + return UNKNOWN_ERROR; +} + +status_t AACEncoder::setAudioSpecificConfigData() { + LOGV("setAudioSpecificConfigData: %d hz, %d bps, and %d channels", + mSampleRate, mBitRate, mChannels); + + int32_t index; + CHECK_EQ(OK, getSampleRateTableIndex(mSampleRate, index)); + if (mChannels > 2 || mChannels <= 0) { + LOGE("Unsupported number of channels(%d)", mChannels); + return UNKNOWN_ERROR; + } + + // OMX_AUDIO_AACObjectLC + mAudioSpecificConfigData[0] = ((0x02 << 3) | (index >> 1)); + mAudioSpecificConfigData[1] = ((index & 0x01) << 7) | (mChannels << 3); + return OK; +} + +AACEncoder::~AACEncoder() { + if (mStarted) { + stop(); + } +} + +status_t AACEncoder::start(MetaData *params) { + CHECK(!mStarted); + + mBufferGroup = new MediaBufferGroup; + mBufferGroup->add_buffer(new MediaBuffer(2048)); + + CHECK_EQ(OK, initCheck()); + + mFrameCount = 0; + mSource->start(); + + mStarted = true; + + return OK; +} + +status_t AACEncoder::stop() { + CHECK(mStarted); + + if (mInputBuffer) { + mInputBuffer->release(); + mInputBuffer = NULL; + } + + delete mBufferGroup; + mBufferGroup = NULL; + + mSource->stop(); + + if (mEncoderHandle) { + CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle)); + mEncoderHandle = NULL; + } + delete mApiHandle; + mApiHandle = NULL; + + mStarted = false; + + return OK; +} + +sp AACEncoder::getFormat() { + sp srcFormat = mSource->getFormat(); + + mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); + + int64_t durationUs; + if (srcFormat->findInt64(kKeyDuration, &durationUs)) { + mMeta->setInt64(kKeyDuration, durationUs); + } + + mMeta->setCString(kKeyDecoderComponent, "AACEncoder"); + + return mMeta; +} + +status_t AACEncoder::read( + MediaBuffer **out, const ReadOptions *options) { + status_t err; + + *out = NULL; + + int64_t seekTimeUs; + CHECK(options == NULL || !options->getSeekTo(&seekTimeUs)); + + MediaBuffer *buffer; + CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); + uint8_t *outPtr = (uint8_t *)buffer->data(); + + if (mFrameCount == 0) { + memcpy(outPtr, mAudioSpecificConfigData, 2); + buffer->set_range(0, 2); + buffer->meta_data()->setInt32(kKeyIsCodecConfig, true); + *out = buffer; + ++mFrameCount; + mInputBuffer = NULL; + return OK; + } else { + buffer->meta_data()->setInt32(kKeyIsCodecConfig, false); + } + + if (mInputBuffer == NULL) { + if (mSource->read(&mInputBuffer, options) != OK) { + LOGE("failed to read from input audio source"); + return UNKNOWN_ERROR; + } + if (mInputBuffer->range_length() == 0) { + mInputBuffer->release(); + mInputBuffer = NULL; + return ERROR_END_OF_STREAM; + } + VO_CODECBUFFER inputData; + memset(&inputData, 0, sizeof(inputData)); + inputData.Buffer = (unsigned char*) mInputBuffer->data(); + inputData.Length = mInputBuffer->range_length(); + CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData)); + } + + CHECK(mInputBuffer != NULL); + + VO_CODECBUFFER outputData; + memset(&outputData, 0, sizeof(outputData)); + VO_AUDIO_OUTPUTINFO outputInfo; + memset(&outputInfo, 0, sizeof(outputInfo)); + + VO_U32 ret = VO_ERR_NONE; + int32_t outputLength = 0; + outputData.Buffer = outPtr; + outputData.Length = buffer->size(); + ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo); + if (ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL) { + outputLength += outputData.Length; + if (ret == VO_ERR_INPUT_BUFFER_SMALL) { // All done + mInputBuffer->release(); + mInputBuffer = NULL; + } + } else { + LOGE("failed to encode the input data 0x%lx", ret); + } + + buffer->set_range(0, outputLength); + ++mFrameCount; + int64_t timestampUs = (mFrameCount * 1000000LL * 1024) / mSampleRate; + + buffer->meta_data()->setInt64(kKeyTime, timestampUs); + + *out = buffer; + return OK; +} + +} // namespace android diff --git a/media/libstagefright/codecs/aacenc/Android.mk b/media/libstagefright/codecs/aacenc/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..cda4f9da09e79019f396ddade20a7263e28aafa4 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/Android.mk @@ -0,0 +1,87 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +include frameworks/base/media/libstagefright/codecs/common/Config.mk + +LOCAL_PRELINK_MODULE := false + +LOCAL_SRC_FILES := basic_op/basicop2.c basic_op/oper_32b.c + +LOCAL_SRC_FILES += \ + AACEncoder.cpp \ + src/aac_rom.c \ + src/aacenc.c \ + src/aacenc_core.c \ + src/adj_thr.c \ + src/band_nrg.c \ + src/bit_cnt.c \ + src/bitbuffer.c \ + src/bitenc.c \ + src/block_switch.c \ + src/channel_map.c \ + src/dyn_bits.c \ + src/grp_data.c \ + src/interface.c \ + src/line_pe.c \ + src/ms_stereo.c \ + src/pre_echo_control.c \ + src/psy_configuration.c \ + src/psy_main.c \ + src/qc_main.c \ + src/quantize.c \ + src/sf_estim.c \ + src/spreading.c \ + src/stat_bits.c \ + src/tns.c \ + src/transform.c \ + src/memalign.c + +ifeq ($(VOTT), v5) +LOCAL_SRC_FILES += \ + src/asm/ARMV5E/AutoCorrelation_v5.s \ + src/asm/ARMV5E/band_nrg_v5.s \ + src/asm/ARMV5E/CalcWindowEnergy_v5.s \ + src/asm/ARMV5E/PrePostMDCT_v5.s \ + src/asm/ARMV5E/R4R8First_v5.s \ + src/asm/ARMV5E/Radix4FFT_v5.s +endif + +ifeq ($(VOTT), v7) +LOCAL_SRC_FILES += \ + src/asm/ARMV5E/AutoCorrelation_v5.s \ + src/asm/ARMV5E/band_nrg_v5.s \ + src/asm/ARMV5E/CalcWindowEnergy_v5.s \ + src/asm/ARMV7/PrePostMDCT_v7.s \ + src/asm/ARMV7/R4R8First_v7.s \ + src/asm/ARMV7/Radix4FFT_v7.s +endif + +LOCAL_MODULE := libstagefright_aacenc + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := + +LOCAL_SHARED_LIBRARIES := + +LOCAL_C_INCLUDES := \ + frameworks/base/media/libstagefright/include \ + frameworks/base/media/libstagefright/codecs/common/include \ + frameworks/base/include \ + $(LOCAL_PATH)/src \ + $(LOCAL_PATH)/inc \ + $(LOCAL_PATH)/basic_op + +LOCAL_CFLAGS := $(VO_CFLAGS) + +ifeq ($(VOTT), v5) +LOCAL_CFLAGS += -DARMV5E -DARM_INASM -DARMV5_INASM +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E +endif + +ifeq ($(VOTT), v7) +LOCAL_CFLAGS += -DARMV5E -DARMV7Neon -DARM_INASM -DARMV5_INASM +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7 +endif + +include $(BUILD_STATIC_LIBRARY) diff --git a/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c b/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c new file mode 100644 index 0000000000000000000000000000000000000000..64d012ddd0a354624ca5c5ce585b7ee2f108a58b --- /dev/null +++ b/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c @@ -0,0 +1,283 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: AAC_E_SAMPLES.h + + Content: sample code for AAC encoder + +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include "voAAC.h" +#include "cmnMemory.h" + +#define VO_AAC_E_OUTPUT 1 +#define READ_SIZE (1024*8) +unsigned char outBuf[1024*8]; +unsigned char inBuf[READ_SIZE]; + +const char* HelpString = +"VisualOn AAC encoder Usage:\n" +"voAACEncTest -if -of -sr -ch -br -adts \n" +"-if input file name \n" +"-of output file name \n" +"-sr input pcm samplerate, default 44100 \n" +"-ch input pcm channel, default 2 channel \n" +"-br encoded aac bitrate, default 64000 * (samplerate/100)*channel/441(480)\n" +"-adts add or no adts header, default add adts header\n" +"For example: \n" +"./voAACEncTest -if raw.pcm -of raw.aac -sr 44100 -ch 2 -br 128000\n"; + +static int parsecmdline(int argc, char **argv,char **input_filename, char **output_filename, AACENC_PARAM *param) +{ + // notice that: + // bitRate/nChannels > 8000 + // bitRate/nChannels < 160000 + // bitRate/nChannels < sampleRate*6 + param->adtsUsed = 1; + param->bitRate = 0; + param->nChannels = 2; + param->sampleRate = 44100; + + if(argc < 5 || argc > 13) + { + return -1; + } + + argc--; + argv++; + while (argc > 0) + { + if (!strcmp(*argv, "-if")) + { + argv++; + argc--; + *input_filename = *argv; + } + else if (!strcmp(*argv, "-of")) + { + argv++; + argc--; + *output_filename = *argv; + } + else if (!strcmp(*argv, "-sr")) + { + argv++; + argc--; + param->sampleRate = atoi(*argv); + } + else if (!strcmp(*argv, "-ch")) + { + argv++; + argc--; + param->nChannels = atoi(*argv); + } + else if (!strcmp(*argv, "-br")) + { + argv++; + argc--; + param->bitRate = atoi(*argv); + } + else if(!strcmp(*argv, "-adts")) + { + argv++; + argc--; + param->adtsUsed = atoi(*argv); + } + else + { + return -1; + } + + argv++; + argc--; + } + + if(param->bitRate == 0) + { + int scale = 441; + if(param->sampleRate%8000 == 0) + scale = 480; + param->bitRate = 640*param->nChannels*param->sampleRate/scale; + } + + return 0; +} + +int ReadFile2Buf(FILE* infile,unsigned char* dest,int readSize) +{ + int readBytes = 0; + readBytes = fread(dest, 1, readSize, infile); + return readBytes; +} + +typedef int (VO_API * VOGETAUDIODECAPI) (VO_AUDIO_CODECAPI * pDecHandle); + +int main(int argc, char **argv) +{ + FILE *infile, *outfile; + int t1, t2; + VO_AUDIO_CODECAPI AudioAPI; + VO_MEM_OPERATOR moper; + VO_CODEC_INIT_USERDATA useData; + VO_HANDLE hCodec; + VO_CODECBUFFER inData; + VO_CODECBUFFER outData; + VO_AUDIO_OUTPUTINFO outInfo; + int firstWrite = 1; + int eofFile = 0; + int *info=(int*)inBuf; + int bytesLeft, nRead; + int EncoderdFrame = 0; + int total = 0; + int isOutput = 1; + int returnCode; + AACENC_PARAM aacpara; + void *handle; + void *pfunc; + VOGETAUDIODECAPI pGetAPI; + const char *infileName = NULL; + const char *outfileName = NULL; + + returnCode = parsecmdline(argc,argv, &infileName, &outfileName, &aacpara); + if(returnCode) + { + printf("%s", HelpString); + return 0; + } + + /* open input file */ + infile = fopen(infileName, "rb"); + if (!infile) { + printf("Open input file fail..."); + return -1; + } + + /* open output file */ + if(isOutput) + { + outfile = fopen(outfileName, "wb"); + if (!outfile) { + printf("Open output file fail..."); + return -1; + } + } + // set memory operators; + moper.Alloc = cmnMemAlloc; + moper.Copy = cmnMemCopy; + moper.Free = cmnMemFree; + moper.Set = cmnMemSet; + moper.Check = cmnMemCheck; + useData.memflag = VO_IMF_USERMEMOPERATOR; + useData.memData = (VO_PTR)(&moper); + // open encoder dll; + handle = dlopen("/data/local/tmp/libvoAACEncv7.so", RTLD_NOW); + if(handle == 0) + { + printf("open dll error......"); + return -1; + } + // Get API; + pfunc = dlsym(handle, "voGetAACEncAPI"); + if(pfunc == 0) + { + printf("open function error......"); + return -1; + } + pGetAPI = (VOGETAUDIODECAPI)pfunc; + returnCode = pGetAPI(&AudioAPI); + if(returnCode) + return -1; + + +//####################################### Init Encoding Section ######################################### + returnCode = AudioAPI.Init(&hCodec, VO_AUDIO_CodingAAC, &useData); + if(returnCode < 0) + { + printf("#### VOI_Error2:fail to initialize the Encoderr###\n"); + return -1; + } + + returnCode = AudioAPI.SetParam(hCodec, VO_PID_AAC_ENCPARAM, &aacpara); + + inData.Buffer = inBuf; + bytesLeft = ReadFile2Buf(infile,inData.Buffer,READ_SIZE); + +//####################################### Encoding Section ######################################### + + do { + + inData.Length = bytesLeft; + outData.Buffer = outBuf; + outData.Length = 1024*8; + + t1 = clock(); + + returnCode = AudioAPI.SetInputData(hCodec,&inData); + + do { + outData.Buffer = outBuf; + outData.Length = 1024*8; + + returnCode = AudioAPI.GetOutputData(hCodec,&outData, &outInfo); + + if(returnCode == 0) + EncoderdFrame++; + if(returnCode == VO_ERR_LICENSE_ERROR) + break; + +#if VO_AAC_E_OUTPUT + if (isOutput && returnCode == 0) + { + fwrite(outData.Buffer, 1, outData.Length, outfile); + } +#endif + } while(returnCode != (VO_ERR_INPUT_BUFFER_SMALL)); + + if(returnCode == VO_ERR_LICENSE_ERROR) + break; + + t2 = clock(); + total += t2 - t1; + + if (!eofFile) { + nRead = ReadFile2Buf(infile, inBuf,READ_SIZE); + bytesLeft = nRead; + inData.Buffer = inBuf; + if (feof(infile)) + eofFile = 1; + } + + } while (!eofFile && returnCode); + + +//################################################ End Encoding Section ####################################################### + returnCode = AudioAPI.Uninit(hCodec); + + fclose(infile); + if (outfile) + { + fclose(outfile); + } + dlclose(handle); + return 0; +} + + diff --git a/media/libstagefright/codecs/aacenc/SampleCode/Android.mk b/media/libstagefright/codecs/aacenc/SampleCode/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..52c9c0798298b121689b3340c8eb225b8e326af3 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/SampleCode/Android.mk @@ -0,0 +1,24 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := AAC_E_SAMPLES.c + +LOCAL_SRC_FILES += \ + ../../../Common/cmnMemory.c + +LOCAL_MODULE := TestvoAACEnc + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := + +LOCAL_SHARED_LIBRARIES := libvoAACEnc + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/ \ + $(LOCAL_PATH)/../../../Common \ + $(LOCAL_PATH)/../../../Include \ + +LOCAL_CFLAGS := $(VO_CFLAGS) + +include $(BUILD_EXECUTABLE) diff --git a/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile b/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..22c5dc1a54ea7cdfa755b3b0981f3228d54e8cfe --- /dev/null +++ b/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile @@ -0,0 +1,55 @@ +#/* +#** Copyright 2003-2010, VisualOn, Inc. +#** +#** 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. +#*/ + +# target6 +# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon) +VOTT:= v7 + + +# module type +# please specify the type of your module: lib or exe +VOMT:= exe + + +# module macros +# please append the additional macro definitions here for your module if necessary. +# e.g. -DVISUALON, macro VISUALON defined for your module +VOMM:= #ARMV5E + + + +# please specify the name of your module +VOTARGET:= voAACEncTestv7 + + +# please modify here to be sure to see the g1.mk +include ../../../../Tools/eclair.mk + +# dependent libraries. +VODEPLIBS:=-ldl + +# module source +# please modify here to be sure to see the ms.mk which specifies all source info of your module +include ../ms.mk + + +# please specify where is the voRelease on your PC, relative path is suggested +VORELDIR:=../../../../../Release/ + + +# please modify here to be sure to see the doit.mk +include ../../../../Tools/doit.mk + diff --git a/media/libstagefright/codecs/aacenc/SampleCode/ms.mk b/media/libstagefright/codecs/aacenc/SampleCode/ms.mk new file mode 100644 index 0000000000000000000000000000000000000000..771a56966a50111619575890655d3b4799570ffe --- /dev/null +++ b/media/libstagefright/codecs/aacenc/SampleCode/ms.mk @@ -0,0 +1,23 @@ +#/* +#** Copyright 2003-2010, VisualOn, Inc. +#** +#** 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. +#*/ + +# please list all objects needed by your target here +OBJS:=AAC_E_SAMPLES.o cmnMemory.o + +# please list all directories that all source files relative with your module(.h .c .cpp) locate +VOSRCDIR:=../ ../../../../include ../../../../Common + + diff --git a/media/libstagefright/codecs/aacenc/Tools/doit.mk b/media/libstagefright/codecs/aacenc/Tools/doit.mk new file mode 100644 index 0000000000000000000000000000000000000000..dea0b0a62684cb80e958baec220fb8d589f7ef75 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/Tools/doit.mk @@ -0,0 +1,133 @@ +#/* +# ** Copyright 2003-2010, VisualOn, Inc. +# ** +# ** 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. +# */ + +VERBOSE:=@ + + +VOMT ?= lib + +ifeq ($(VOMT), lib) +LIB_STATIC=$(VOTARGET).a +LIB_DYNAMIC=$(VOTARGET).so +endif + +ifeq ($(VOMT), exe) +TARGET=$(VOTARGET) +endif + +CFLAGS=$(VOCFLAGS) $(addprefix -I, $(VOSRCDIR)) +CPPFLAGS=$(VOCPPFLAGS) $(addprefix -I, $(VOSRCDIR)) +ifneq ($(VOTT), pc) +ASFLAGS=$(VOASFLAGS) $(addprefix -I, $(VOSRCDIR)) +endif + +LDFLAGS:=$(VOLDFLAGS) +VOTEDEPS+=$(VODEPLIBS) +VOTLDEPS+=$(VODEPLIBS) +VOSTCLIBS ?= + +vpath %.c $(VOSRCDIR) +vpath %.cpp $(VOSRCDIR) +ifneq ($(VOTT), pc) +vpath %.s $(VOSRCDIR) +endif + +ifeq ($(VOTT), pc) +BLTDIRS=$(VORELDIR)/Linux/static +BLTDIRD=$(VORELDIR)/Linux/shared +else +BLTDIRS=$(VORELDIR)/Google/$(VONJ)/lib/$(VOTT) +BLTDIRD=$(VORELDIR)/Google/$(VONJ)/so/$(VOTT) +endif + + +.PRECIOUS: $(OBJDIR)/%.o + +ifeq ($(VOMT), lib) +all: mkdirs $(LIB_STATIC) $(LIB_DYNAMIC) +mkdirs: $(OBJDIR) $(BLTDIRS) $(BLTDIRD) +else +all: mkdirs $(TARGET) +mkdirs: $(OBJDIR) +endif + +$(OBJDIR): + @if test ! -d $@; then \ + mkdir -p $@; \ + fi; + +ifeq ($(VOMT), lib) +$(BLTDIRS): + @if test ! -d $@; then \ + mkdir -p $@; \ + fi; +$(BLTDIRD): + @if test ! -d $@; then \ + mkdir -p $@; \ + fi; +endif + + +ifeq ($(VOMT), lib) +$(LIB_STATIC):$(OBJS) + $(AR) cr $@ $(OBJDIR)/*.o $(VOSTCLIBS) + $(RANLIB) $@ +ifneq ($(VODBG), yes) + #$(STRIP) $@ +endif + +$(LIB_DYNAMIC):$(OBJS) + $(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTLDEPS) +ifneq ($(VODBG), yes) + $(STRIP) $@ +endif + +else + +$(TARGET):$(OBJS) + $(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTEDEPS) +ifneq ($(VODBG), yes) + $(STRIP) $@ +endif + +endif + + +.SUFFIXES: .c .cpp .s .o +.c.o: + $(VERBOSE) $(CC) $(CFLAGS) -o $(OBJDIR)/$@ -c $< +#%.c:$(OBJDIR)/%.o +# $(VERBOSE) $(CC) $(CFLAGS) -o $@ -c $< +.cpp.o: + $(VERBOSE) $(GG) $(CPPFLAGS) -o $(OBJDIR)/$@ -c $< +ifneq ($(VOTT), pc) +.s.o: + $(VERBOSE) $(AS) $(ASFLAGS) -o $(OBJDIR)/$@ $< +endif + + +.PHONY: clean devel +clean: +ifeq ($(VOMT), lib) + -rm -fr $(OBJDIR) .*.sw* $(VOTARGET).* +else + -rm -fr $(OBJDIR) .*.sw* $(VOTARGET) +endif + +devel: + cp -a $(LIB_STATIC) $(BLTDIRS) + cp -a $(LIB_DYNAMIC) $(BLTDIRD) + diff --git a/media/libstagefright/codecs/aacenc/Tools/eclair.mk b/media/libstagefright/codecs/aacenc/Tools/eclair.mk new file mode 100644 index 0000000000000000000000000000000000000000..16883619ba1430183da2c70d30e30db0221b7f36 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/Tools/eclair.mk @@ -0,0 +1,172 @@ +#/* +# ** Copyright 2003-2010, VisualOn, Inc. +# ** +# ** 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. +# */ + +# special macro definitions for building +VOPREDEF=-DLINUX -D_LINUX + +VOPRJ ?= +VONJ ?= eclair +VOTT ?= v6 +# control the version to release out +# available: eva(evaluation), rel(release) +VOVER= +ifeq ($(VOVER), eva) +VOPREDEF+=-D__VOVER_EVA__ +endif + +# for debug or not: yes for debug, any other for release +VODBG?=ye + +# for detecting memory leak +VODML= +ifeq ($(VODML), yes) +VOPREDEF+=-DDMEMLEAK +endif + +VOPREDEF+=-D__VOTT_ARM__ -D__VONJ_ECLAIR__ +TCROOTPATH:=/opt/eclair +GCCVER:=4.4.0 +TCPATH:=$(TCROOTPATH)/prebuilt/linux-x86/toolchain/arm-eabi-$(GCCVER) +CCTPRE:=$(TCPATH)/bin/arm-eabi- +AS:=$(CCTPRE)as +AR:=$(CCTPRE)ar +NM:=$(CCTPRE)nm +CC:=$(CCTPRE)gcc +GG:=$(CCTPRE)g++ +LD:=$(CCTPRE)ld +SIZE:=$(CCTPRE)size +STRIP:=$(CCTPRE)strip +RANLIB:=$(CCTPRE)ranlib +OBJCOPY:=$(CCTPRE)objcopy +OBJDUMP:=$(CCTPRE)objdump +READELF:=$(CCTPRE)readelf +STRINGS:=$(CCTPRE)strings + +# target product dependcy +# available: dream, generic +VOTP:=sapphire-open +CCTLIB:=$(TCROOTPATH)/out/target/product/$(VOTP)/obj/lib +CCTINC:=-I$(TCROOTPATH)/system/core/include \ + -I$(TCROOTPATH)/hardware/libhardware/include \ + -I$(TCROOTPATH)/hardware/ril/include \ + -I$(TCROOTPATH)/hardware/libhardware_legacy/include \ + -I$(TCROOTPATH)/dalvik/libnativehelper/include \ + -I$(TCROOTPATH)/dalvik/libnativehelper/include/nativehelper \ + -I$(TCROOTPATH)/frameworks/base/include \ + -I$(TCROOTPATH)/frameworks/base/core/jni \ + -I$(TCROOTPATH)/frameworks/base/libs/audioflinger \ + -I$(TCROOTPATH)/external/skia/include \ + -I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/include \ + -I$(TCROOTPATH)/bionic/libc/arch-arm/include \ + -I$(TCROOTPATH)/bionic/libc/include \ + -I$(TCROOTPATH)/bionic/libstdc++/include \ + -I$(TCROOTPATH)/bionic/libc/kernel/common \ + -I$(TCROOTPATH)/bionic/libc/kernel/arch-arm \ + -I$(TCROOTPATH)/bionic/libm/include \ + -I$(TCROOTPATH)/bionic/libm/include/arm \ + -I$(TCROOTPATH)/bionic/libthread_db/include \ + -I$(TCROOTPATH)/bionic/libm/arm \ + -I$(TCROOTPATH)/bionic/libm \ + -I$(TCROOTPATH)/frameworks/base/include/android_runtime + #-I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/SHARED_LIBRARIES/libm_intermediates + +CCTCFLAGS:=-msoft-float -mthumb-interwork -fno-exceptions -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fmessage-length=0 -finline-functions -finline-limit=600 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -fstrict-aliasing -funswitch-loops +#-fwide-exec-charset=charset=UTF-32 + +# for target exe +TELDFLAGS:=-nostdlib -Bdynamic -Wl,-T,$(TCROOTPATH)/build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,--no-undefined -Wl,-rpath-link=$(CCTLIB) -L$(CCTLIB) + +VOTEDEPS:=$(CCTLIB)/crtbegin_dynamic.o $(CCTLIB)/crtend_android.o $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a -lc -lm + +# for target lib +TLLDFLAGS:=-nostdlib -Wl,-T,$(TCROOTPATH)/build/core/armelf.xsc -Wl,--gc-sections -Wl,-shared,-Bsymbolic -L$(CCTLIB) -Wl,--no-whole-archive -Wl,--no-undefined $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a + +VOTLDEPS:=-lm -lc + + +ifeq ($(VOTT), v4) +VOCFLAGS:=-mtune=arm9tdmi -march=armv4t +VOASFLAGS:=-march=armv4t -mfpu=softfpa +endif + +ifeq ($(VOTT), v5) +VOCFLAGS:=-march=armv5te +VOASFLAGS:=-march=armv5te -mfpu=vfp +endif + +ifeq ($(VOTT), v5x) +VOCFLAGS:=-march=armv5te -mtune=xscale +VOASFLAGS:=-march=armv5te -mfpu=vfp +endif + +ifeq ($(VOTT), v6) +#VOCFLAGS:=-march=armv6 -mtune=arm1136jf-s +#VOASFLAGS:=-march=armv6 +VOCFLAGS:=-march=armv6j -mtune=arm1136jf-s -mfpu=vfp -mfloat-abi=softfp -mapcs -mtpcs-leaf-frame -mlong-calls +VOASFLAGS:=-march=armv6j -mcpu=arm1136jf-s -mfpu=arm1136jf-s -mfloat-abi=softfp -mapcs-float -mapcs-reentrant +endif + +# +# global link options +VOLDFLAGS:=-Wl,-x,-X,--as-needed + + +ifeq ($(VOTT), v7) +VOCFLAGS+=-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp +VOASFLAGS+=-march=armv7-a -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp +VOLDFLAGS+=-Wl,--fix-cortex-a8 +endif + +#global compiling options for ARM target +ifneq ($(VOTT), pc) +VOASFLAGS+=--strip-local-absolute -R +endif + + +ifeq ($(VODBG), yes) +VOCFLAGS+=-D_DEBUG -g +else +VOCFLAGS+=-DNDEBUG -O3 +endif + +VOCFLAGS+=$(VOPREDEF) $(VOMM) -Wall -fsigned-char -fomit-frame-pointer -fno-leading-underscore -fpic -fPIC -pipe -ftracer -fforce-addr -fno-bounds-check #-fvisibility=hidden #-fvisibility-inlines-hidden ##-ftree-loop-linear -mthumb -nostdinc -dD -fprefetch-loop-arrays + + +ifneq ($(VOTT), pc) +VOCFLAGS+=$(CCTCFLAGS) $(CCTINC) +VOCPPFLAGS:=-fno-rtti $(VOCFLAGS) + +ifeq ($(VOMT), exe) +VOLDFLAGS+=$(TELDFLAGS) +endif + +ifeq ($(VOMT), lib) +VOLDFLAGS+=$(TLLDFLAGS) +endif +else +VOCPPFLAGS:=$(VOCFLAGS) +ifeq ($(VOMT), lib) +VOLDFLAGS+=-shared +endif +endif + +ifeq ($(VODBG), yes) +#VOLDFLAGS:= +endif + +# where to place object files +OBJDIR=obj + diff --git a/media/libstagefright/codecs/aacenc/basic_op/basic_op.h b/media/libstagefright/codecs/aacenc/basic_op/basic_op.h new file mode 100644 index 0000000000000000000000000000000000000000..5457f3356dab699c5e697fb45ef83ac16d5144e3 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/basic_op/basic_op.h @@ -0,0 +1,1166 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: basicop2.h + + Content: Constants , Globals and Basic arithmetic operators. + +*******************************************************************************/ + +#ifndef __BASIC_OP_H +#define __BASIC_OP_H + +#include "typedef.h" + +#define MAX_32 (Word32)0x7fffffffL +#define MIN_32 (Word32)0x80000000L + +#define MAX_16 (Word16)0x7fff +#define MIN_16 (Word16)0x8000 +#define ABS(a) ((a) >= 0) ? (a) : (-(a)) + +/* Short abs, 1 */ +#define abs_s(x) ((Word16)(((x) != MIN_16) ? (((x) >= 0) ? (x) : (-(x))) : MAX_16)) + +/* 16 bit var1 -> MSB, 2 */ +#define L_deposit_h(x) (((Word32)(x)) << 16) + + +/* 16 bit var1 -> LSB, 2 */ +#define L_deposit_l(x) ((Word32)(x)) + + +/* Long abs, 3 */ +#define L_abs(x) (((x) != MIN_32) ? (((x) >= 0) ? (x) : (-(x))) : MAX_32) + + +/* Short negate, 1 */ +#define negate(var1) ((Word16)(((var1) == MIN_16) ? MAX_16 : (-(var1)))) + + +/* Long negate, 2 */ +#define L_negate(L_var1) (((L_var1) == (MIN_32)) ? (MAX_32) : (-(L_var1))) + + +#define MULHIGH(A,B) (int)(((Word64)(A)*(Word64)(B)) >> 32) +#define fixmul(a, b) (int)((((Word64)(a)*(Word64)(b)) >> 32) << 1) + + +#if (SATRUATE_IS_INLINE) +__inline Word16 saturate(Word32 L_var1); +#else +Word16 saturate(Word32 L_var1); +#endif + +/* Short shift left, 1 */ +#if (SHL_IS_INLINE) +__inline Word16 shl (Word16 var1, Word16 var2); +#else +Word16 shl (Word16 var1, Word16 var2); +#endif + +/* Short shift right, 1 */ +#if (SHR_IS_INLINE) +__inline Word16 shr (Word16 var1, Word16 var2); +#else +Word16 shr (Word16 var1, Word16 var2); +#endif + +#if (L_MULT_IS_INLINE) +__inline Word32 L_mult(Word16 var1, Word16 var2); +#else +Word32 L_mult(Word16 var1, Word16 var2); +#endif + +/* Msu, 1 */ +#if (L_MSU_IS_INLINE) +__inline Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2); +#else +Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2); +#endif + +/* Long sub, 2 */ +#if (L_SUB_IS_INLINE) +__inline Word32 L_sub(Word32 L_var1, Word32 L_var2); +#else +Word32 L_sub(Word32 L_var1, Word32 L_var2); +#endif + +/* Long shift left, 2 */ +#if (L_SHL_IS_INLINE) +__inline Word32 L_shl (Word32 L_var1, Word16 var2); +#else +Word32 L_shl (Word32 L_var1, Word16 var2); +#endif + +/* Long shift right, 2*/ +#if (L_SHR_IS_INLINE) +__inline Word32 L_shr (Word32 L_var1, Word16 var2); +#else +Word32 L_shr (Word32 L_var1, Word16 var2); +#endif + +/* Short add, 1 */ +#if (ADD_IS_INLINE) +__inline Word16 add (Word16 var1, Word16 var2); +#else +Word16 add (Word16 var1, Word16 var2); +#endif + +/* Short sub, 1 */ +#if (SUB_IS_INLINE) +__inline Word16 sub(Word16 var1, Word16 var2); +#else +Word16 sub(Word16 var1, Word16 var2); +#endif + +/* Short division, 18 */ +#if (DIV_S_IS_INLINE) +__inline Word16 div_s (Word16 var1, Word16 var2); +#else +Word16 div_s (Word16 var1, Word16 var2); +#endif + +/* Short mult, 1 */ +#if (MULT_IS_INLINE) +__inline Word16 mult (Word16 var1, Word16 var2); +#else +Word16 mult (Word16 var1, Word16 var2); +#endif + +/* Short norm, 15 */ +#if (NORM_S_IS_INLINE) +__inline Word16 norm_s (Word16 var1); +#else +Word16 norm_s (Word16 var1); +#endif + +/* Long norm, 30 */ +#if (NORM_L_IS_INLINE) +__inline Word16 norm_l (Word32 L_var1); +#else +Word16 norm_l (Word32 L_var1); +#endif + +/* Round, 1 */ +#if (ROUND_IS_INLINE) +__inline Word16 round16(Word32 L_var1); +#else +Word16 round16(Word32 L_var1); +#endif + +/* Mac, 1 */ +#if (L_MAC_IS_INLINE) +__inline Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2); +#else +Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2); +#endif + +#if (L_ADD_IS_INLINE) +__inline Word32 L_add (Word32 L_var1, Word32 L_var2); +#else +Word32 L_add (Word32 L_var1, Word32 L_var2); +#endif + +/* Extract high, 1 */ +#if (EXTRACT_H_IS_INLINE) +__inline Word16 extract_h (Word32 L_var1); +#else +Word16 extract_h (Word32 L_var1); +#endif + +/* Extract low, 1 */ +#if (EXTRACT_L_IS_INLINE) +__inline Word16 extract_l(Word32 L_var1); +#else +Word16 extract_l(Word32 L_var1); +#endif + +/* Mult with round, 2 */ +#if (MULT_R_IS_INLINE) +__inline Word16 mult_r(Word16 var1, Word16 var2); +#else +Word16 mult_r(Word16 var1, Word16 var2); +#endif + +/* Shift right with round, 2 */ +#if (SHR_R_IS_INLINE) +__inline Word16 shr_r (Word16 var1, Word16 var2); +#else +Word16 shr_r (Word16 var1, Word16 var2); +#endif + +/* Mac with rounding,2 */ +#if (MAC_R_IS_INLINE) +__inline Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2); +#else +Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2); +#endif + +/* Msu with rounding,2 */ +#if (MSU_R_IS_INLINE) +__inline Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2); +#else +Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2); +#endif + +/* Long shift right with round, 3 */ +#if (L_SHR_R_IS_INLINE) +__inline Word32 L_shr_r (Word32 L_var1, Word16 var2); +#else +Word32 L_shr_r (Word32 L_var1, Word16 var2); +#endif + +#if ARMV4_INASM +__inline Word32 ASM_L_shr(Word32 L_var1, Word16 var2) +{ + Word32 result; + asm volatile( + "MOV %[result], %[L_var1], ASR %[var2] \n" + :[result]"=r"(result) + :[L_var1]"r"(L_var1), [var2]"r"(var2) + ); + return result; +} + +__inline Word32 ASM_L_shl(Word32 L_var1, Word16 var2) +{ + Word32 result; + asm volatile( + "MOV r2, %[L_var1] \n" + "MOV r3, #0x7fffffff\n" + "MOV %[result], %[L_var1], ASL %[var2] \n" + "TEQ r2, %[result], ASR %[var2]\n" + "EORNE %[result],r3,r2,ASR#31\n" + :[result]"+r"(result) + :[L_var1]"r"(L_var1), [var2]"r"(var2) + :"r2", "r3" + ); + return result; +} + +__inline Word32 ASM_shr(Word32 L_var1, Word16 var2) +{ + Word32 result; + asm volatile( + "CMP %[var2], #15\n" + "MOVGE %[var2], #15\n" + "MOV %[result], %[L_var1], ASR %[var2]\n" + :[result]"=r"(result) + :[L_var1]"r"(L_var1), [var2]"r"(var2) + ); + return result; +} + +__inline Word32 ASM_shl(Word32 L_var1, Word16 var2) +{ + Word32 result; + asm volatile( + "CMP %[var2], #16\n" + "MOVGE %[var2], #16\n" + "MOV %[result], %[L_var1], ASL %[var2]\n" + "MOV r3, #1\n" + "MOV r2, %[result], ASR #15\n" + "RSB r3,r3,r3,LSL #15 \n" + "TEQ r2, %[result], ASR #31 \n" + "EORNE %[result], r3, %[result],ASR #31" + :[result]"+r"(result) + :[L_var1]"r"(L_var1), [var2]"r"(var2) + :"r2", "r3" + ); + return result; +} +#endif + +/*___________________________________________________________________________ + | | + | definitions for inline basic arithmetic operators | + |___________________________________________________________________________| +*/ +#if (SATRUATE_IS_INLINE) +__inline Word16 saturate(Word32 L_var1) +{ +#if ARMV5TE_SAT + Word16 result; + asm volatile ( + "MOV %[result], %[L_var1]\n" + "MOV r3, #1\n" + "MOV r2,%[L_var1],ASR#15\n" + "RSB r3, r3, r3, LSL #15\n" + "TEQ r2,%[L_var1],ASR#31\n" + "EORNE %[result],r3,%[L_var1],ASR#31\n" + :[result]"+r"(result) + :[L_var1]"r"(L_var1) + :"r2", "r3" + ); + + return result; +#else + Word16 var_out; + + //var_out = (L_var1 > (Word32)0X00007fffL) ? (MAX_16) : ((L_var1 < (Word32)0xffff8000L) ? (MIN_16) : ((Word16)L_var1)); + + if (L_var1 > 0X00007fffL) + { + var_out = MAX_16; + } + else if (L_var1 < (Word32) 0xffff8000L) + { + var_out = MIN_16; + } + else + { + var_out = extract_l(L_var1); + } + + return (var_out); +#endif +} +#endif + +/* Short shift left, 1 */ +#if (SHL_IS_INLINE) +__inline Word16 shl (Word16 var1, Word16 var2) +{ +#if ARMV5TE_SHL + if(var2>=0) + { + return ASM_shl( var1, var2); + } + else + { + return ASM_shr( var1, -var2); + } +#else + Word16 var_out; + Word32 result; + + if (var2 < 0) + { + var_out = shr (var1, (Word16)-var2); + } + else + { + result = (Word32) var1 *((Word32) 1 << var2); + + if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result))) + { + var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16); + } + else + { + var_out = extract_l(result); + } + } + return (var_out); +#endif +} +#endif + +/* Short shift right, 1 */ +#if (SHR_IS_INLINE) +__inline Word16 shr (Word16 var1, Word16 var2) +{ +#if ARMV5TE_SHR + if(var2>=0) + { + return ASM_shr( var1, var2); + } + else + { + return ASM_shl( var1, -var2); + } +#else + Word16 var_out; + + if (var2 < 0) + { + var_out = shl (var1, (Word16)-var2); + } + else + { + if (var2 >= 15) + { + var_out = (Word16)((var1 < 0) ? -1 : 0); + } + else + { + if (var1 < 0) + { + var_out = (Word16)(~((~var1) >> var2)); + } + else + { + var_out = (Word16)(var1 >> var2); + } + } + } + + return (var_out); +#endif +} +#endif + + +#if (L_MULT_IS_INLINE) +__inline Word32 L_mult(Word16 var1, Word16 var2) +{ +#if ARMV5TE_L_MULT + Word32 result; + asm volatile( + "SMULBB %[result], %[var1], %[var2] \n" + "QADD %[result], %[result], %[result] \n" + :[result]"+r"(result) + :[var1]"r"(var1), [var2]"r"(var2) + ); + return result; +#else + Word32 L_var_out; + + L_var_out = (Word32) var1 *(Word32) var2; + + if (L_var_out != (Word32) 0x40000000L) + { + L_var_out <<= 1; + } + else + { + L_var_out = MAX_32; + } + return (L_var_out); +#endif +} +#endif + +#if (L_MSU_IS_INLINE) +__inline Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2) +{ +#if ARMV5TE_L_MSU + Word32 result; + asm volatile( + "SMULBB %[result], %[var1], %[var2] \n" + "QADD %[result], %[result], %[result] \n" + "QSUB %[result], %[L_var3], %[result]\n" + :[result]"+r"(result) + :[L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2) + ); + return result; +#else + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult(var1, var2); + L_var_out = L_sub(L_var3, L_product); + return (L_var_out); +#endif +} +#endif + +#if (L_SUB_IS_INLINE) +__inline Word32 L_sub(Word32 L_var1, Word32 L_var2) +{ +#if ARMV5TE_L_SUB + Word32 result; + asm volatile( + "QSUB %[result], %[L_var1], %[L_var2]\n" + :[result]"+r"(result) + :[L_var1]"r"(L_var1), [L_var2]"r"(L_var2) + ); + return result; +#else + Word32 L_var_out; + + L_var_out = L_var1 - L_var2; + + if (((L_var1 ^ L_var2) & MIN_32) != 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32; + } + } + + return (L_var_out); +#endif +} +#endif + +#if (L_SHL_IS_INLINE) +__inline Word32 L_shl(Word32 L_var1, Word16 var2) +{ +#if ARMV5TE_L_SHL + if(var2>=0) + { + return ASM_L_shl( L_var1, var2); + } + else + { + return ASM_L_shr( L_var1, -var2); + } +#else + Word32 L_var_out = 0L; + + if (var2 <= 0) + { + L_var1 = L_shr(L_var1, (Word16)-var2); + } + else + { + for (; var2 > 0; var2--) + { + if (L_var1 > (Word32) 0X3fffffffL) + { + return MAX_32; + } + else + { + if (L_var1 < (Word32) 0xc0000000L) + { + return MIN_32; + } + } + L_var1 <<= 1; + L_var_out = L_var1; + } + } + return (L_var1); +#endif +} +#endif + +#if (L_SHR_IS_INLINE) +__inline Word32 L_shr (Word32 L_var1, Word16 var2) +{ +#if ARMV5TE_L_SHR + if(var2>=0) + { + return ASM_L_shr( L_var1, var2); + } + else + { + return ASM_L_shl( L_var1, -var2); + } +#else + Word32 L_var_out; + + if (var2 < 0) + { + L_var_out = L_shl (L_var1, (Word16)-var2); + } + else + { + if (var2 >= 31) + { + L_var_out = (L_var1 < 0L) ? -1 : 0; + } + else + { + if (L_var1 < 0) + { + L_var_out = ~((~L_var1) >> var2); + } + else + { + L_var_out = L_var1 >> var2; + } + } + } + return (L_var_out); +#endif +} +#endif + +/* Short add, 1 */ +#if (ADD_IS_INLINE) +__inline Word16 add (Word16 var1, Word16 var2) +{ +#if ARMV5TE_ADD + Word32 result; + asm volatile( + "ADD %[result], %[var1], %[var2] \n" + "MOV r3, #0x1\n" + "MOV r2, %[result], ASR #15\n" + "RSB r3, r3, r3, LSL, #15\n" + "TEQ r2, %[result], ASR #31\n" + "EORNE %[result], r3, %[result], ASR #31" + :[result]"+r"(result) + :[var1]"r"(var1), [var2]"r"(var2) + :"r2", "r3" + ); + return result; +#else + Word16 var_out; + Word32 L_sum; + + L_sum = (Word32) var1 + var2; + var_out = saturate(L_sum); + + return (var_out); +#endif +} +#endif + +/* Short sub, 1 */ +#if (SUB_IS_INLINE) +__inline Word16 sub(Word16 var1, Word16 var2) +{ +#if ARMV5TE_SUB + Word32 result; + asm volatile( + "MOV r3, #1\n" + "SUB %[result], %[var1], %[var2] \n" + "RSB r3,r3,r3,LSL#15\n" + "MOV r2, %[var1], ASR #15 \n" + "TEQ r2, %[var1], ASR #31 \n" + "EORNE %[result], r3, %[result], ASR #31 \n" + :[result]"+r"(result) + :[var1]"r"(var1), [var2]"r"(var2) + :"r2", "r3" + ); + return result; +#else + Word16 var_out; + Word32 L_diff; + + L_diff = (Word32) var1 - var2; + var_out = saturate(L_diff); + + return (var_out); +#endif +} +#endif + +/* Short division, 18 */ +#if (DIV_S_IS_INLINE) +__inline Word16 div_s (Word16 var1, Word16 var2) +{ + Word16 var_out = 0; + Word16 iteration; + Word32 L_num; + Word32 L_denom; + + var_out = MAX_16; + if (var1!= var2)//var1!= var2 + { + var_out = 0; + L_num = (Word32) var1; + + L_denom = (Word32) var2; + + //return (L_num<<15)/var2; + + for (iteration = 0; iteration < 15; iteration++) + { + var_out <<= 1; + L_num <<= 1; + + if (L_num >= L_denom) + { + L_num -= L_denom; + var_out++; + } + } + } + return (var_out); +} +#endif + +/* Short mult, 1 */ +#if (MULT_IS_INLINE) +__inline Word16 mult (Word16 var1, Word16 var2) +{ +#if ARMV5TE_MULT + Word32 result; + asm volatile( + "SMULBB r2, %[var1], %[var2] \n" + "MOV r3, #1\n" + "MOV %[result], r2, ASR #15\n" + "RSB r3, r3, r3, LSL #15\n" + "MOV r2, %[result], ASR #15\n" + "TEQ r2, %[result], ASR #31\n" + "EORNE %[result], r3, %[result], ASR #31 \n" + :[result]"+r"(result) + :[var1]"r"(var1), [var2]"r"(var2) + :"r2", "r3" + ); + return result; +#else + Word16 var_out; + Word32 L_product; + + L_product = (Word32) var1 *(Word32) var2; + L_product = (L_product & (Word32) 0xffff8000L) >> 15; + if (L_product & (Word32) 0x00010000L) + L_product = L_product | (Word32) 0xffff0000L; + var_out = saturate(L_product); + + return (var_out); +#endif +} +#endif + + +/* Short norm, 15 */ +#if (NORM_S_IS_INLINE) +__inline Word16 norm_s (Word16 var1) +{ +#if ARMV5TE_NORM_S + Word16 result; + asm volatile( + "MOV r2,%[var1] \n" + "CMP r2, #0\n" + "RSBLT %[var1], %[var1], #0 \n" + "CLZNE %[result], %[var1]\n" + "SUBNE %[result], %[result], #17\n" + "MOVEQ %[result], #0\n" + "CMP r2, #-1\n" + "MOVEQ %[result], #15\n" + :[result]"+r"(result) + :[var1]"r"(var1) + :"r2" + ); + return result; +#else + Word16 var_out; + + if (var1 == 0) + { + var_out = 0; + } + else + { + if (var1 == -1) + { + var_out = 15; + } + else + { + if (var1 < 0) + { + var1 = (Word16)~var1; + } + for (var_out = 0; var1 < 0x4000; var_out++) + { + var1 <<= 1; + } + } + } + return (var_out); +#endif +} +#endif + +/* Long norm, 30 */ +#if (NORM_L_IS_INLINE) +__inline Word16 norm_l (Word32 L_var1) +{ +#if ARMV5TE_NORM_L + Word16 result; + asm volatile( + "CMP %[L_var1], #0\n" + "CLZNE %[result], %[L_var1]\n" + "SUBNE %[result], %[result], #1\n" + "MOVEQ %[result], #0\n" + :[result]"+r"(result) + :[L_var1]"r"(L_var1) + ); + return result; +#else + //Word16 var_out; + + //if (L_var1 == 0) + //{ + // var_out = 0; + //} + //else + //{ + // if (L_var1 == (Word32) 0xffffffffL) + // { + // var_out = 31; + // } + // else + // { + // if (L_var1 < 0) + // { + // L_var1 = ~L_var1; + // } + // for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++) + // { + // L_var1 <<= 1; + // } + // } + //} + //return (var_out); + Word16 a16; + Word16 r = 0 ; + + + if ( L_var1 < 0 ) { + L_var1 = ~L_var1; + } + + if (0 == (L_var1 & 0x7fff8000)) { + a16 = extract_l(L_var1); + r += 16; + + if (0 == (a16 & 0x7f80)) { + r += 8; + + if (0 == (a16 & 0x0078)) { + r += 4; + + if (0 == (a16 & 0x0006)) { + r += 2; + + if (0 == (a16 & 0x0001)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0004)) { + r += 1; + } + } + } + else { + + if (0 == (a16 & 0x0060)) { + r += 2; + + if (0 == (a16 & 0x0010)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0040)) { + r += 1; + } + } + } + } + else { + + if (0 == (a16 & 0x7800)) { + r += 4; + + if (0 == (a16 & 0x0600)) { + r += 2; + + if (0 == (a16 & 0x0100)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0400)) { + r += 1; + } + } + } + else { + + if (0 == (a16 & 0x6000)) { + r += 2; + + if (0 == (a16 & 0x1000)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x4000)) { + r += 1; + } + } + } + } + } + else { + a16 = extract_h(L_var1); + + if (0 == (a16 & 0x7f80)) { + r += 8; + + if (0 == (a16 & 0x0078)) { + r += 4 ; + + if (0 == (a16 & 0x0006)) { + r += 2; + + if (0 == (a16 & 0x0001)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0004)) { + r += 1; + } + } + } + else { + + if (0 == (a16 & 0x0060)) { + r += 2; + + if (0 == (a16 & 0x0010)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0040)) { + r += 1; + } + } + } + } + else { + + if (0 == (a16 & 0x7800)) { + r += 4; + + if (0 == (a16 & 0x0600)) { + r += 2; + + if (0 == (a16 & 0x0100)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x0400)) { + r += 1; + } + } + } + else { + + if (0 == (a16 & 0x6000)) { + r += 2; + + if (0 == (a16 & 0x1000)) { + r += 1; + } + } + else { + + if (0 == (a16 & 0x4000)) { + return 1; + } + } + } + } + } + + return r ; +#endif +} +#endif + +/* Round, 1 */ +#if (ROUND_IS_INLINE) +__inline Word16 round16(Word32 L_var1) +{ +#if ARMV5TE_ROUND + Word16 result; + asm volatile( + "MOV r1,#0x00008000\n" + "QADD %[result], %[L_var1], r1\n" + "MOV %[result], %[result], ASR #16 \n" + :[result]"+r"(result) + :[L_var1]"r"(L_var1) + :"r1" + ); + return result; +#else + Word16 var_out; + Word32 L_rounded; + + L_rounded = L_add (L_var1, (Word32) 0x00008000L); + var_out = extract_h (L_rounded); + return (var_out); +#endif +} +#endif + +/* Mac, 1 */ +#if (L_MAC_IS_INLINE) +__inline Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2) +{ +#if ARMV5TE_L_MAC + Word32 result; + asm volatile( + "SMULBB %[result], %[var1], %[var2]\n" + "QADD %[result], %[result], %[result]\n" + "QADD %[result], %[result], %[L_var3]\n" + :[result]"+r"(result) + : [L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2) + ); + return result; +#else + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult(var1, var2); + L_var_out = L_add (L_var3, L_product); + return (L_var_out); +#endif +} +#endif + +#if (L_ADD_IS_INLINE) +__inline Word32 L_add (Word32 L_var1, Word32 L_var2) +{ +#if ARMV5TE_L_ADD + Word32 result; + asm volatile( + "QADD %[result], %[L_var1], %[L_var2]\n" + :[result]"+r"(result) + :[L_var1]"r"(L_var1), [L_var2]"r"(L_var2) + ); + return result; +#else + Word32 L_var_out; + + L_var_out = L_var1 + L_var2; + if (((L_var1 ^ L_var2) & MIN_32) == 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32; + } + } + return (L_var_out); +#endif +} +#endif + + + +#if (MULT_R_IS_INLINE) +__inline Word16 mult_r (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_product_arr; + + L_product_arr = (Word32)var1 *(Word32)var2; /* product */ + L_product_arr += (Word32)0x00004000L; /* round */ + L_product_arr >>= 15; /* shift */ + + var_out = saturate(L_product_arr); + + return (var_out); +} +#endif + +#if (SHR_R_IS_INLINE) +__inline Word16 shr_r (Word16 var1, Word16 var2) +{ + Word16 var_out; + + if (var2 > 15) + { + var_out = 0; + } + else + { + var_out = shr(var1, var2); + + if (var2 > 0) + { + if ((var1 & ((Word16) 1 << (var2 - 1))) != 0) + { + var_out++; + } + } + } + + return (var_out); +} +#endif + +#if (MAC_R_IS_INLINE) +__inline Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word16 var_out; + + L_var3 = L_mac (L_var3, var1, var2); + var_out = (Word16)((L_var3 + 0x8000L) >> 16); + + return (var_out); +} +#endif + +#if (MSU_R_IS_INLINE) +__inline Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word16 var_out; + + L_var3 = L_msu (L_var3, var1, var2); + var_out = (Word16)((L_var3 + 0x8000L) >> 16); + + return (var_out); +} +#endif + +#if (L_SHR_R_IS_INLINE) +__inline Word32 L_shr_r (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out; + + if (var2 > 31) + { + L_var_out = 0; + } + else + { + L_var_out = L_shr(L_var1, var2); + + if (var2 > 0) + { + if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0) + { + L_var_out++; + } + } + } + + return (L_var_out); +} +#endif + +#if (EXTRACT_H_IS_INLINE) +__inline Word16 extract_h (Word32 L_var1) +{ + Word16 var_out; + + var_out = (Word16) (L_var1 >> 16); + + return (var_out); +} +#endif + +#if (EXTRACT_L_IS_INLINE) +__inline Word16 extract_l(Word32 L_var1) +{ + return (Word16) L_var1; +} +#endif + +#endif diff --git a/media/libstagefright/codecs/aacenc/basic_op/basicop2.c b/media/libstagefright/codecs/aacenc/basic_op/basicop2.c new file mode 100644 index 0000000000000000000000000000000000000000..a0d5dba66d8922a1e80e83f5550a85b613fb3d1b --- /dev/null +++ b/media/libstagefright/codecs/aacenc/basic_op/basicop2.c @@ -0,0 +1,1624 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: basicop2.c + + Content: Basic arithmetic operators. + +*******************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + + +/*___________________________________________________________________________ + | | + | Functions | + |___________________________________________________________________________| +*/ + +/*___________________________________________________________________________ + | | + | Function Name : saturate | + | | + | Purpose : | + | | + | Limit the 32 bit input to the range of a 16 bit word. | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +#if (!SATRUATE_IS_INLINE) +Word16 saturate(Word32 L_var1) +{ + Word16 var_out; + + if (L_var1 > 0X00007fffL) + { + var_out = MAX_16; + } + else if (L_var1 < (Word32) 0xffff8000L) + { + var_out = MIN_16; + } + else + { + var_out = extract_l(L_var1); + } + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : add | + | | + | Purpose : | + | | + | Performs the addition (var1+var2) with overflow control and saturation;| + | the 16 bit result is set at +32767 when overflow occurs or at -32768 | + | when underflow occurs. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +#if (!ADD_IS_INLINE) +Word16 add (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_sum; + + L_sum = (Word32)var1 + (Word32)var2; + var_out = saturate(L_sum); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : sub | + | | + | Purpose : | + | | + | Performs the subtraction (var1+var2) with overflow control and satu- | + | ration; the 16 bit result is set at +32767 when overflow occurs or at | + | -32768 when underflow occurs. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!SUB_IS_INLINE) +Word16 sub(Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_diff; + + L_diff = (Word32) var1 - var2; + var_out = saturate(L_diff); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : abs_s | + | | + | Purpose : | + | | + | Absolute value of var1; abs_s(-32768) = 32767. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +//Word16 abs_s (Word16 var1) +//{ +// Word16 var_out; +// +// if (var1 == MIN_16) +// { +// var_out = MAX_16; +// } +// else +// { +// if (var1 < 0) +// { +// var_out = (Word16)-var1; +// } +// else +// { +// var_out = var1; +// } +// } +// +// return (var_out); +//} + + +/*___________________________________________________________________________ + | | + | Function Name : shl | + | | + | Purpose : | + | | + | Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill| + | the var2 LSB of the result. If var2 is negative, arithmetically shift | + | var1 right by -var2 with sign extension. Saturate the result in case of | + | underflows or overflows. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +#if (!SHL_IS_INLINE) +Word16 shl (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 result; + + if (var2 < 0) + { + if (var2 < -16) + var2 = -16; + var_out = shr (var1, (Word16)-var2); + } + else + { + result = (Word32) var1 *((Word32) 1 << var2); + + if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result))) + { + //Overflow = 1; + var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16); + } + else + { + var_out = extract_l(result); + } + } + + return (var_out); +} +#endif +// end + +/*___________________________________________________________________________ + | | + | Function Name : shr | + | | + | Purpose : | + | | + | Arithmetically shift the 16 bit input var1 right var2 positions with | + | sign extension. If var2 is negative, arithmetically shift var1 left by | + | -var2 with sign extension. Saturate the result in case of underflows or | + | overflows. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +#if (!SHR_IS_INLINE) +Word16 shr (Word16 var1, Word16 var2) +{ + Word16 var_out; + + if (var2 < 0) + { + if (var2 < -16) + var2 = -16; + var_out = shl (var1, (Word16)-var2); + } + else + { + if (var2 >= 15) + { + var_out = (Word16)((var1 < 0) ? -1 : 0); + } + else + { + if (var1 < 0) + { + var_out = (Word16)(~((~var1) >> var2)); + } + else + { + var_out = (Word16)(var1 >> var2); + } + } + } + + return (var_out); +} +#endif + + +/*___________________________________________________________________________ + | | + | Function Name : mult | + | | + | Purpose : | + | | + | Performs the multiplication of var1 by var2 and gives a 16 bit result | + | which is scaled i.e.: | + | mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and | + | mult(-32768,-32768) = 32767. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!MULT_IS_INLINE) +Word16 mult (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_product; + + L_product = (Word32) var1 *(Word32) var2; + + L_product = (L_product & (Word32) 0xffff8000L) >> 15; + + if (L_product & (Word32) 0x00010000L) + L_product = L_product | (Word32) 0xffff0000L; + + var_out = saturate(L_product); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_mult | + | | + | Purpose : | + | | + | L_mult is the 32 bit result of the multiplication of var1 times var2 | + | with one shift left i.e.: | + | L_mult(var1,var2) = L_shl((var1 times var2),1) and | + | L_mult(-32768,-32768) = 2147483647. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +#if (!L_MULT_IS_INLINE) +Word32 L_mult(Word16 var1, Word16 var2) +{ + Word32 L_var_out; + + L_var_out = (Word32) var1 *(Word32) var2; + + if (L_var_out != (Word32) 0x40000000L) + { + L_var_out <<= 1; + } + else + { + L_var_out = MAX_32; + } + + return (L_var_out); +} +#endif +// end + +/*___________________________________________________________________________ + | | + | Function Name : negate | + | | + | Purpose : | + | | + | Negate var1 with saturation, saturate in the case where input is -32768:| + | negate(var1) = sub(0,var1). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +//Word16 negate (Word16 var1) +//{ +// Word16 var_out; +// +// var_out = (Word16)((var1 == MIN_16) ? MAX_16 : -var1); +// +// return (var_out); +//} + + +/*___________________________________________________________________________ + | | + | Function Name : extract_h | + | | + | Purpose : | + | | + | Return the 16 MSB of L_var1. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!EXTRACT_H_IS_INLINE) +Word16 extract_h (Word32 L_var1) +{ + Word16 var_out; + + var_out = (Word16) (L_var1 >> 16); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : extract_l | + | | + | Purpose : | + | | + | Return the 16 LSB of L_var1. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!EXTRACT_L_IS_INLINE) +Word16 extract_l(Word32 L_var1) +{ + Word16 var_out; + + var_out = (Word16) L_var1; + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : round | + | | + | Purpose : | + | | + | Round the lower 16 bits of the 32 bit input number into the MS 16 bits | + | with saturation. Shift the resulting bits right by 16 and return the 16 | + | bit number: | + | round(L_var1) = extract_h(L_add(L_var1,32768)) | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +#if (!ROUND_IS_INLINE) +Word16 round16(Word32 L_var1) +{ + Word16 var_out; + Word32 L_rounded; + + L_rounded = L_add (L_var1, (Word32) 0x00008000L); + var_out = extract_h (L_rounded); + + return (var_out); +} +#endif +// end + +/*___________________________________________________________________________ + | | + | Function Name : L_mac | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | + | result to L_var3 with saturation, return a 32 bit result: | + | L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +#if (!L_MSU_IS_INLINE) +Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult(var1, var2); + L_var_out = L_add (L_var3, L_product); + + return (L_var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_msu | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | + | bit result to L_var3 with saturation, return a 32 bit result: | + | L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +#if (!L_MSU_IS_INLINE) +Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult(var1, var2); + L_var_out = L_sub (L_var3, L_product); + + return (L_var_out); +} +#endif + + +/*___________________________________________________________________________ + | | + | Function Name : L_add | + | | + | Purpose : | + | | + | 32 bits addition of the two 32 bits variables (L_var1+L_var2) with | + | overflow control and saturation; the result is set at +2147483647 when | + | overflow occurs or at -2147483648 when underflow occurs. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +#if (!L_ADD_IS_INLINE) +Word32 L_add (Word32 L_var1, Word32 L_var2) +{ + Word32 L_var_out; + + L_var_out = L_var1 + L_var2; + + if (((L_var1 ^ L_var2) & MIN_32) == 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32; + //Overflow = 1; + } + } + + return (L_var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_sub | + | | + | Purpose : | + | | + | 32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with | + | overflow control and saturation; the result is set at +2147483647 when | + | overflow occurs or at -2147483648 when underflow occurs. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +#if (!L_SUB_IS_INLINE) +Word32 L_sub(Word32 L_var1, Word32 L_var2) +{ + Word32 L_var_out; + + L_var_out = L_var1 - L_var2; + + if (((L_var1 ^ L_var2) & MIN_32) != 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32; + //Overflow = 1; + } + } + + return (L_var_out); +} +#endif + + +/*___________________________________________________________________________ + | | + | Function Name : L_negate | + | | + | Purpose : | + | | + | Negate the 32 bit variable L_var1 with saturation; saturate in the case | + | where input is -2147483648 (0x8000 0000). | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +//Word32 L_negate (Word32 L_var1) +//{ +// Word32 L_var_out; +// +// L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1; +// +// return (L_var_out); +//} + + +/*___________________________________________________________________________ + | | + | Function Name : mult_r | + | | + | Purpose : | + | | + | Same as mult with rounding, i.e.: | + | mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and | + | mult_r(-32768,-32768) = 32767. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!MULT_R_IS_INLINE) +Word16 mult_r (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_product_arr; + + L_product_arr = (Word32) var1 *(Word32) var2; /* product */ + L_product_arr += (Word32) 0x00004000L; /* round */ + L_product_arr &= (Word32) 0xffff8000L; + L_product_arr >>= 15; /* shift */ + + if (L_product_arr & (Word32) 0x00010000L) /* sign extend when necessary */ + { + L_product_arr |= (Word32) 0xffff0000L; + } + var_out = saturate(L_product_arr); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_shl | + | | + | Purpose : | + | | + | Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero | + | fill the var2 LSB of the result. If var2 is negative, arithmetically | + | shift L_var1 right by -var2 with sign extension. Saturate the result in | + | case of underflows or overflows. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +#if (!L_SHL_IS_INLINE) +Word32 L_shl (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out = 0L; + + if (var2 <= 0) + { + L_var1 = L_shr(L_var1, (Word16)-var2); + } + else + { + for (; var2 > 0; var2--) + { + if (L_var1 > (Word32) 0X3fffffffL) + { + return MAX_32; + } + else + { + if (L_var1 < (Word32) 0xc0000000L) + { + return MIN_32; + } + } + L_var1 <<= 1; + } + } + return (L_var1); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_shr | + | | + | Purpose : | + | | + | Arithmetically shift the 32 bit input L_var1 right var2 positions with | + | sign extension. If var2 is negative, arithmetically shift L_var1 left | + | by -var2 and zero fill the -var2 LSB of the result. Saturate the result | + | in case of underflows or overflows. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +#if (!L_SHR_IS_INLINE) +Word32 L_shr (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out; + + if (var2 < 0) + { + L_var_out = L_shl (L_var1, (Word16)-var2); + } + else + { + if (var2 >= 31) + { + L_var_out = (L_var1 < 0L) ? -1 : 0; + } + else + { + if (L_var1 < 0) + { + L_var_out = ~((~L_var1) >> var2); + } + else + { + L_var_out = L_var1 >> var2; + } + } + } + return (L_var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : shr_r | + | | + | Purpose : | + | | + | Same as shr(var1,var2) but with rounding. Saturate the result in case of| + | underflows or overflows : | + | - If var2 is greater than zero : | + | if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1)))) | + | is equal to zero | + | then | + | shr_r(var1,var2) = shr(var1,var2) | + | else | + | shr_r(var1,var2) = add(shr(var1,var2),1) | + | - If var2 is less than or equal to zero : | + | shr_r(var1,var2) = shr(var1,var2). | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!SHR_R_IS_INLINE) +Word16 shr_r (Word16 var1, Word16 var2) +{ + Word16 var_out; + + if (var2 > 15) + { + var_out = 0; + } + else + { + var_out = shr (var1, var2); + + if (var2 > 0) + { + if ((var1 & ((Word16) 1 << (var2 - 1))) != 0) + { + var_out++; + } + } + } + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : mac_r | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | + | result to L_var3 with saturation. Round the LS 16 bits of the result | + | into the MS 16 bits with saturation and shift the result right by 16. | + | Return a 16 bit result. | + | mac_r(L_var3,var1,var2) = round(L_mac(L_var3,var1,var2)) | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!MAC_R_IS_INLINE) +Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word16 var_out; + + L_var3 = L_mac (L_var3, var1, var2); + L_var3 = L_add (L_var3, (Word32) 0x00008000L); + var_out = extract_h (L_var3); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : msu_r | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | + | bit result to L_var3 with saturation. Round the LS 16 bits of the res- | + | ult into the MS 16 bits with saturation and shift the result right by | + | 16. Return a 16 bit result. | + | msu_r(L_var3,var1,var2) = round(L_msu(L_var3,var1,var2)) | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +#if (!MSU_R_IS_INLINE) +Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word16 var_out; + + L_var3 = L_msu (L_var3, var1, var2); + L_var3 = L_add (L_var3, (Word32) 0x00008000L); + var_out = extract_h (L_var3); + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_deposit_h | + | | + | Purpose : | + | | + | Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The | + | 16 LS bits of the output are zeroed. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var_out <= 0x7fff 0000. | + |___________________________________________________________________________| +*/ +//Word32 L_deposit_h (Word16 var1) +//{ +// Word32 L_var_out; +// +// L_var_out = (Word32) var1 << 16; +// +// return (L_var_out); +//} + + +/*___________________________________________________________________________ + | | + | Function Name : L_deposit_l | + | | + | Purpose : | + | | + | Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The | + | 16 MS bits of the output are sign extended. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0xFFFF 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +//Word32 L_deposit_l (Word16 var1) +//{ +// Word32 L_var_out; +// +// L_var_out = (Word32) var1; +// +// return (L_var_out); +//} + + +/*___________________________________________________________________________ + | | + | Function Name : L_shr_r | + | | + | Purpose : | + | | + | Same as L_shr(L_var1,var2) but with rounding. Saturate the result in | + | case of underflows or overflows : | + | - If var2 is greater than zero : | + | if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))| + | is equal to zero | + | then | + | L_shr_r(L_var1,var2) = L_shr(L_var1,var2) | + | else | + | L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1) | + | - If var2 is less than or equal to zero : | + | L_shr_r(L_var1,var2) = L_shr(L_var1,var2). | + | | + | Complexity weight : 3 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +#if (!L_SHR_R_IS_INLINE) +Word32 L_shr_r (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out; + + if (var2 > 31) + { + L_var_out = 0; + } + else + { + L_var_out = L_shr (L_var1, var2); + + if (var2 > 0) + { + if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0) + { + L_var_out++; + } + } + } + + return (L_var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : L_abs | + | | + | Purpose : | + | | + | Absolute value of L_var1; Saturate in case where the input is | + | -214783648 | + | | + | Complexity weight : 3 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +//Word32 L_abs (Word32 L_var1) +//{ +// Word32 L_var_out; +// +// if (L_var1 == MIN_32) +// { +// L_var_out = MAX_32; +// } +// else +// { +// if (L_var1 < 0) +// { +// L_var_out = -L_var1; +// } +// else +// { +// L_var_out = L_var1; +// } +// } +// +// return (L_var_out); +//} + +/*___________________________________________________________________________ + | | + | Function Name : norm_s | + | | + | Purpose : | + | | + | Produces the number of left shift needed to normalize the 16 bit varia- | + | ble var1 for positive values on the interval with minimum of 16384 and | + | maximum of 32767, and for negative values on the interval with minimum | + | of -32768 and maximum of -16384; in order to normalize the result, the | + | following operation must be done : | + | norm_var1 = shl(var1,norm_s(var1)). | + | | + | Complexity weight : 15 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 000f. | + |___________________________________________________________________________| +*/ + +#if (!NORM_S_IS_INLINE) +Word16 norm_s (Word16 var1) +{ + Word16 var_out; + + if (var1 == 0) + { + var_out = 0; + } + else + { + if (var1 == -1) + { + var_out = 15; + } + else + { + if (var1 < 0) + { + var1 = (Word16)~var1; + } + for (var_out = 0; var1 < 0x4000; var_out++) + { + var1 <<= 1; + } + } + } + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : div_s | + | | + | Purpose : | + | | + | Produces a result which is the fractional integer division of var1 by | + | var2; var1 and var2 must be positive and var2 must be greater or equal | + | to var1; the result is positive (leading bit equal to 0) and truncated | + | to 16 bits. | + | If var1 = var2 then div(var1,var2) = 32767. | + | | + | Complexity weight : 18 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var1 <= var2 and var2 != 0. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : var1 <= var2 <= 0x0000 7fff and var2 != 0. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 7fff. | + | It's a Q15 value (point between b15 and b14). | + |___________________________________________________________________________| +*/ + +#if (!DIV_S_IS_INLINE) +Word16 div_s (Word16 var1, Word16 var2) +{ + Word16 var_out = 0; + Word16 iteration; + Word32 L_num; + Word32 L_denom; + + if (var1 == 0) + { + var_out = 0; + } + else + { + if (var1 == var2) + { + var_out = MAX_16; + } + else + { + L_num = L_deposit_l (var1); + L_denom = L_deposit_l (var2); + + for (iteration = 0; iteration < 15; iteration++) + { + var_out <<= 1; + L_num <<= 1; + + if (L_num >= L_denom) + { + L_num = L_sub(L_num, L_denom); + var_out = add (var_out, 1); + } + } + } + } + + return (var_out); +} +#endif + +/*___________________________________________________________________________ + | | + | Function Name : norm_l | + | | + | Purpose : | + | | + | Produces the number of left shifts needed to normalize the 32 bit varia-| + | ble L_var1 for positive values on the interval with minimum of | + | 1073741824 and maximum of 2147483647, and for negative values on the in-| + | terval with minimum of -2147483648 and maximum of -1073741824; in order | + | to normalize the result, the following operation must be done : | + | norm_L_var1 = L_shl(L_var1,norm_l(L_var1)). | + | | + | Complexity weight : 30 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 001f. | + |___________________________________________________________________________| +*/ + +#if (!NORM_L_IS_INLINE) +Word16 norm_l (Word32 L_var1) +{ + Word16 var_out; + + if (L_var1 == 0) + { + var_out = 0; + } + else + { + if (L_var1 == (Word32) 0xffffffffL) + { + var_out = 31; + } + else + { + if (L_var1 < 0) + { + L_var1 = ~L_var1; + } + for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++) + { + L_var1 <<= 1; + } + } + } + + return (var_out); +} +#endif + diff --git a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c new file mode 100644 index 0000000000000000000000000000000000000000..906a9df15f1579b1a8eba2f29545738a7830faad --- /dev/null +++ b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c @@ -0,0 +1,361 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: oper_32b.c + + Content: This file contains operations in double precision. + +*******************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" + +/***************************************************************************** + * * + * Function L_Extract() * + * * + * Extract from a 32 bit integer two 16 bit DPF. * + * * + * Arguments: * + * * + * L_32 : 32 bit integer. * + * 0x8000 0000 <= L_32 <= 0x7fff ffff. * + * hi : b16 to b31 of L_32 * + * lo : (L_32 - hi<<16)>>1 * + ***************************************************************************** +*/ + +void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo) +{ + *hi = extract_h (L_32); + *lo = extract_l (L_msu (L_shr (L_32, 1), *hi, 16384)); + return; +} + +/***************************************************************************** + * * + * Function L_Comp() * + * * + * Compose from two 16 bit DPF a 32 bit integer. * + * * + * L_32 = hi<<16 + lo<<1 * + * * + * Arguments: * + * * + * hi msb * + * lo lsf (with sign) * + * * + * Return Value : * + * * + * 32 bit long signed integer (Word32) whose value falls in the * + * range : 0x8000 0000 <= L_32 <= 0x7fff fff0. * + * * + ***************************************************************************** +*/ + +Word32 L_Comp (Word16 hi, Word16 lo) +{ + Word32 L_32; + + L_32 = L_deposit_h (hi); + return (L_mac (L_32, lo, 1)); /* = hi<<16 + lo<<1 */ +} + +/***************************************************************************** + * Function Mpy_32() * + * * + * Multiply two 32 bit integers (DPF). The result is divided by 2**31 * + * * + * L_32 = (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1 * + * * + * This operation can also be viewed as the multiplication of two Q31 * + * number and the result is also in Q31. * + * * + * Arguments: * + * * + * hi1 hi part of first number * + * lo1 lo part of first number * + * hi2 hi part of second number * + * lo2 lo part of second number * + * * + ***************************************************************************** +*/ + +Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2) +{ + Word32 L_32; + + L_32 = L_mult (hi1, hi2); + L_32 = L_mac (L_32, mult (hi1, lo2), 1); + L_32 = L_mac (L_32, mult (lo1, hi2), 1); + + return (L_32); +} + +/***************************************************************************** + * Function Mpy_32_16() * + * * + * Multiply a 16 bit integer by a 32 bit (DPF). The result is divided * + * by 2**15 * + * * + * * + * L_32 = (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 * + * * + * Arguments: * + * * + * hi hi part of 32 bit number. * + * lo lo part of 32 bit number. * + * n 16 bit number. * + * * + ***************************************************************************** +*/ + +Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n) +{ + Word32 L_32; + + L_32 = L_mult (hi, n); + L_32 = L_mac (L_32, mult (lo, n), 1); + + return (L_32); +} + +/***************************************************************************** + * * + * Function Name : Div_32 * + * * + * Purpose : * + * Fractional integer division of two 32 bit numbers. * + * L_num / L_denom. * + * L_num and L_denom must be positive and L_num < L_denom. * + * L_denom = denom_hi<<16 + denom_lo<<1 * + * denom_hi is a normalize number. * + * * + * Inputs : * + * * + * L_num * + * 32 bit long signed integer (Word32) whose value falls in the * + * range : 0x0000 0000 < L_num < L_denom * + * * + * L_denom = denom_hi<<16 + denom_lo<<1 (DPF) * + * * + * denom_hi * + * 16 bit positive normalized integer whose value falls in the * + * range : 0x4000 < hi < 0x7fff * + * denom_lo * + * 16 bit positive integer whose value falls in the * + * range : 0 < lo < 0x7fff * + * * + * Return Value : * + * * + * L_div * + * 32 bit long signed integer (Word32) whose value falls in the * + * range : 0x0000 0000 <= L_div <= 0x7fff ffff. * + * * + * Algorithm: * + * * + * - find = 1/L_denom. * + * First approximation: approx = 1 / denom_hi * + * 1/L_denom = approx * (2.0 - L_denom * approx ) * + * * + * - result = L_num * (1/L_denom) * + ***************************************************************************** +*/ + +Word32 Div_32 (Word32 L_num, Word32 denom) +{ + Word16 approx; + Word32 L_32; + /* First approximation: 1 / L_denom = 1/denom_hi */ + + approx = div_s ((Word16) 0x3fff, denom >> 16); + + /* 1/L_denom = approx * (2.0 - L_denom * approx) */ + + L_32 = L_mpy_ls (denom, approx); + + L_32 = L_sub ((Word32) 0x7fffffffL, L_32); + + L_32 = L_mpy_ls (L_32, approx); + /* L_num * (1/L_denom) */ + + L_32 = MULHIGH(L_32, L_num); + L_32 = L_shl (L_32, 3); + + return (L_32); +} + +/*! + + \brief calculates the log dualis times 4 of argument + iLog4(x) = (Word32)(4 * log(value)/log(2.0)) + + \return ilog4 value + +*/ +Word16 iLog4(Word32 value) +{ + Word16 iLog4; + + if(value != 0){ + Word32 tmp; + Word16 tmp16; + iLog4 = norm_l(value); + tmp = (value << iLog4); + tmp16 = round16(tmp); + tmp = L_mult(tmp16, tmp16); + tmp16 = round16(tmp); + tmp = L_mult(tmp16, tmp16); + tmp16 = round16(tmp); + + iLog4 = (-(iLog4 << 2) - norm_s(tmp16)) - 1; + } + else { + iLog4 = -128; /* -(INT_BITS*4); */ + } + + return iLog4; +} + +#define step(shift) \ + if ((0x40000000l >> shift) + root <= value) \ + { \ + value -= (0x40000000l >> shift) + root; \ + root = (root >> 1) | (0x40000000l >> shift); \ + } else { \ + root = root >> 1; \ + } + +Word32 rsqrt(Word32 value, /*!< Operand to square root (0.0 ... 1) */ + Word32 accuracy) /*!< Number of valid bits that will be calculated */ +{ + Word32 root = 0; + Word32 scale; + + if(value < 0) + return 0; + + scale = norm_l(value); + if(scale & 1) scale--; + + value <<= scale; + + step( 0); step( 2); step( 4); step( 6); + step( 8); step(10); step(12); step(14); + step(16); step(18); step(20); step(22); + step(24); step(26); step(28); step(30); + + scale >>= 1; + if (root < value) + ++root; + + root >>= scale; + return root* 46334; +} + +static const Word32 pow2Table[POW2_TABLE_SIZE] = { +0x7fffffff, 0x7fa765ad, 0x7f4f08ae, 0x7ef6e8da, +0x7e9f0606, 0x7e476009, 0x7deff6b6, 0x7d98c9e6, +0x7d41d96e, 0x7ceb2523, 0x7c94acde, 0x7c3e7073, +0x7be86fb9, 0x7b92aa88, 0x7b3d20b6, 0x7ae7d21a, +0x7a92be8b, 0x7a3de5df, 0x79e947ef, 0x7994e492, +0x7940bb9e, 0x78ecccec, 0x78991854, 0x78459dac, +0x77f25cce, 0x779f5591, 0x774c87cc, 0x76f9f359, +0x76a7980f, 0x765575c8, 0x76038c5b, 0x75b1dba2, +0x75606374, 0x750f23ab, 0x74be1c20, 0x746d4cac, +0x741cb528, 0x73cc556d, 0x737c2d55, 0x732c3cba, +0x72dc8374, 0x728d015d, 0x723db650, 0x71eea226, +0x719fc4b9, 0x71511de4, 0x7102ad80, 0x70b47368, +0x70666f76, 0x7018a185, 0x6fcb096f, 0x6f7da710, +0x6f307a41, 0x6ee382de, 0x6e96c0c3, 0x6e4a33c9, +0x6dfddbcc, 0x6db1b8a8, 0x6d65ca38, 0x6d1a1057, +0x6cce8ae1, 0x6c8339b2, 0x6c381ca6, 0x6bed3398, +0x6ba27e66, 0x6b57fce9, 0x6b0daeff, 0x6ac39485, +0x6a79ad56, 0x6a2ff94f, 0x69e6784d, 0x699d2a2c, +0x69540ec9, 0x690b2601, 0x68c26fb1, 0x6879ebb6, +0x683199ed, 0x67e97a34, 0x67a18c68, 0x6759d065, +0x6712460b, 0x66caed35, 0x6683c5c3, 0x663ccf92, +0x65f60a80, 0x65af766a, 0x6569132f, 0x6522e0ad, +0x64dcdec3, 0x64970d4f, 0x64516c2e, 0x640bfb41, +0x63c6ba64, 0x6381a978, 0x633cc85b, 0x62f816eb, +0x62b39509, 0x626f4292, 0x622b1f66, 0x61e72b65, +0x61a3666d, 0x615fd05f, 0x611c6919, 0x60d9307b, +0x60962665, 0x60534ab7, 0x60109d51, 0x5fce1e12, +0x5f8bccdb, 0x5f49a98c, 0x5f07b405, 0x5ec5ec26, +0x5e8451d0, 0x5e42e4e3, 0x5e01a540, 0x5dc092c7, +0x5d7fad59, 0x5d3ef4d7, 0x5cfe6923, 0x5cbe0a1c, +0x5c7dd7a4, 0x5c3dd19c, 0x5bfdf7e5, 0x5bbe4a61, +0x5b7ec8f2, 0x5b3f7377, 0x5b0049d4, 0x5ac14bea, +0x5a82799a, 0x5a43d2c6, 0x5a055751, 0x59c7071c, +0x5988e209, 0x594ae7fb, 0x590d18d3, 0x58cf7474, +0x5891fac1, 0x5854ab9b, 0x581786e6, 0x57da8c83, +0x579dbc57, 0x57611642, 0x57249a29, 0x56e847ef, +0x56ac1f75, 0x567020a0, 0x56344b52, 0x55f89f70, +0x55bd1cdb, 0x5581c378, 0x55469329, 0x550b8bd4, +0x54d0ad5b, 0x5495f7a1, 0x545b6a8b, 0x542105fd, +0x53e6c9db, 0x53acb607, 0x5372ca68, 0x533906e0, +0x52ff6b55, 0x52c5f7aa, 0x528cabc3, 0x52538786, +0x521a8ad7, 0x51e1b59a, 0x51a907b4, 0x5170810b, +0x51382182, 0x50ffe8fe, 0x50c7d765, 0x508fec9c, +0x50582888, 0x50208b0e, 0x4fe91413, 0x4fb1c37c, +0x4f7a9930, 0x4f439514, 0x4f0cb70c, 0x4ed5ff00, +0x4e9f6cd4, 0x4e69006e, 0x4e32b9b4, 0x4dfc988c, +0x4dc69cdd, 0x4d90c68b, 0x4d5b157e, 0x4d25899c, +0x4cf022ca, 0x4cbae0ef, 0x4c85c3f1, 0x4c50cbb8, +0x4c1bf829, 0x4be7492b, 0x4bb2bea5, 0x4b7e587d, +0x4b4a169c, 0x4b15f8e6, 0x4ae1ff43, 0x4aae299b, +0x4a7a77d5, 0x4a46e9d6, 0x4a137f88, 0x49e038d0, +0x49ad1598, 0x497a15c4, 0x4947393f, 0x49147fee, +0x48e1e9ba, 0x48af768a, 0x487d2646, 0x484af8d6, +0x4818ee22, 0x47e70611, 0x47b5408c, 0x47839d7b, +0x47521cc6, 0x4720be55, 0x46ef8210, 0x46be67e0, +0x468d6fae, 0x465c9961, 0x462be4e2, 0x45fb521a, +0x45cae0f2, 0x459a9152, 0x456a6323, 0x453a564d, +0x450a6abb, 0x44daa054, 0x44aaf702, 0x447b6ead, +0x444c0740, 0x441cc0a3, 0x43ed9ac0, 0x43be9580, +0x438fb0cb, 0x4360ec8d, 0x433248ae, 0x4303c517, +0x42d561b4, 0x42a71e6c, 0x4278fb2b, 0x424af7da, +0x421d1462, 0x41ef50ae, 0x41c1aca8, 0x41942839, +0x4166c34c, 0x41397dcc, 0x410c57a2, 0x40df50b8, +0x40b268fa, 0x4085a051, 0x4058f6a8, 0x402c6be9 +}; + +/*! + + \brief calculates 2 ^ (x/y) for x<=0, y > 0, x <= 32768 * y + + avoids integer division + + \return +*/ +Word32 pow2_xy(Word32 x, Word32 y) +{ + Word32 iPart; + Word32 fPart; + Word32 res; + Word32 tmp, tmp2; + Word32 shift, shift2; + + tmp2 = -x; + iPart = tmp2 / y; + fPart = tmp2 - iPart*y; + iPart = min(iPart,INT_BITS-1); + + res = pow2Table[(POW2_TABLE_SIZE*fPart)/y] >> iPart; + + return(res); +} \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h new file mode 100644 index 0000000000000000000000000000000000000000..4119bc350477c8be7ca1f7438948f989bccfd1ee --- /dev/null +++ b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h @@ -0,0 +1,89 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: oper_32b.h + + Content: Double precision operations + +*******************************************************************************/ + +#ifndef __OPER_32b_H +#define __OPER_32b_H + +#include "typedef.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define POW2_TABLE_BITS 8 +#define POW2_TABLE_SIZE (1<> 16); + + l_var_out = (long)swLow1 * (long)var1 >> 15; + + l_var_out += swHigh1 * var1 << 1; + + return(l_var_out); +} + +__inline Word32 L_mpy_wx(Word32 L_var2, Word16 var1) +{ +#if ARMV5TE_L_MPY_LS + Word32 result; + asm volatile( + "SMULWB %[result], %[L_var2], %[var1] \n" + :[result]"+r"(result) + :[L_var2]"r"(L_var2), [var1]"r"(var1) + ); + return result; +#else + unsigned short swLow1; + Word16 swHigh1; + Word32 l_var_out; + + swLow1 = (unsigned short)(L_var2); + swHigh1 = (Word16)(L_var2 >> 16); + + l_var_out = (long)swLow1 * (long)var1 >> 16; + l_var_out += swHigh1 * var1; + + return(l_var_out); +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/media/libstagefright/codecs/aacenc/basic_op/typedef.h b/media/libstagefright/codecs/aacenc/basic_op/typedef.h new file mode 100644 index 0000000000000000000000000000000000000000..d3a626a21a327ceec007a1342bfff644aa3d7a7c --- /dev/null +++ b/media/libstagefright/codecs/aacenc/basic_op/typedef.h @@ -0,0 +1,63 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: typedef.h + + Content: type defined for defferent paltform + +*******************************************************************************/ + +#ifndef typedef_h +#define typedef_h "$Id $" + +#undef ORIGINAL_TYPEDEF_H /* define to get "original" ETSI version + of typedef.h */ + +#ifdef ORIGINAL_TYPEDEF_H +/* + * this is the original code from the ETSI file typedef.h + */ + +#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__) +typedef signed char Word8; +typedef short Word16; +typedef long Word32; +typedef int Flag; + +#elif defined(__sun) +typedef signed char Word8; +typedef short Word16; +typedef long Word32; +typedef int Flag; + +#elif defined(__unix__) || defined(__unix) +typedef signed char Word8; +typedef short Word16; +typedef int Word32; +typedef int Flag; + +#endif +#else /* not original typedef.h */ + +/* + * use (improved) type definition file typdefs.h and add a "Flag" type + */ +#include "typedefs.h" +typedef int Flag; + +#endif + +#endif diff --git a/media/libstagefright/codecs/aacenc/basic_op/typedefs.h b/media/libstagefright/codecs/aacenc/basic_op/typedefs.h new file mode 100644 index 0000000000000000000000000000000000000000..7d16fca3297f0c3dcf4b0b48a1cc5a28ffc3a1c7 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/basic_op/typedefs.h @@ -0,0 +1,179 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: typedefs.h + + Content: type defined or const defined + +*******************************************************************************/ + +#ifndef typedefs_h +#define typedefs_h "$Id $" + +#ifndef CHAR_BIT +#define CHAR_BIT 8 /* number of bits in a char */ +#endif + +#ifndef VOAAC_SHRT_MAX +#define VOAAC_SHRT_MAX (32767) /* maximum (signed) short value */ +#endif + +#ifndef VOAAC_SHRT_MIN +#define VOAAC_SHRT_MIN (-32768) /* minimum (signed) short value */ +#endif + +/* Define NULL pointer value */ +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#ifndef assert +#define assert(_Expression) ((void)0) +#endif + +#ifdef LINUX +#define __inline static __inline__ +#endif + +#define INT_BITS 32 +/* +******************************************************************************** +* DEFINITION OF CONSTANTS +******************************************************************************** +*/ +/* + ********* define char type + */ +typedef char Char; + +/* + ********* define 8 bit signed/unsigned types & constants + */ +typedef signed char Word8; +typedef unsigned char UWord8; +/* + ********* define 16 bit signed/unsigned types & constants + */ +typedef short Word16; +typedef unsigned short UWord16; + +/* + ********* define 32 bit signed/unsigned types & constants + */ +typedef long Word32; +typedef unsigned long UWord32; + + + +#ifdef LINUX +typedef long long Word64; +typedef unsigned long long UWord64; +#else +typedef __int64 Word64; +typedef unsigned __int64 UWord64; +#endif + +#ifndef min +#define min(a,b) ( a < b ? a : b) +#endif + +#ifndef max +#define max(a,b) ( a > b ? a : b) +#endif + +#ifdef ARM_INASM +#ifdef ARMV5_INASM +#define ARMV5E_INASM 1 +#endif +#define ARMV4_INASM 1 +#endif + +#if ARMV4_INASM + #define ARMV5TE_SAT 1 + #define ARMV5TE_ADD 1 + #define ARMV5TE_SUB 1 + #define ARMV5TE_SHL 1 + #define ARMV5TE_SHR 1 + #define ARMV5TE_L_SHL 1 + #define ARMV5TE_L_SHR 1 +#endif//ARMV4 +#if ARMV5E_INASM + #define ARMV5TE_L_ADD 1 + #define ARMV5TE_L_SUB 1 + #define ARMV5TE_L_MULT 1 + #define ARMV5TE_L_MAC 1 + #define ARMV5TE_L_MSU 1 + + + #define ARMV5TE_DIV_S 1 + #define ARMV5TE_ROUND 1 + #define ARMV5TE_MULT 1 + + #define ARMV5TE_NORM_S 1 + #define ARMV5TE_NORM_L 1 + #define ARMV5TE_L_MPY_LS 1 +#endif + +//basic operation functions optimization flags +#define SATRUATE_IS_INLINE 1 //define saturate as inline function +#define SHL_IS_INLINE 1 //define shl as inline function +#define SHR_IS_INLINE 1 //define shr as inline function +#define L_MULT_IS_INLINE 1 //define L_mult as inline function +#define L_MSU_IS_INLINE 1 //define L_msu as inline function +#define L_SUB_IS_INLINE 1 //define L_sub as inline function +#define L_SHL_IS_INLINE 1 //define L_shl as inline function +#define L_SHR_IS_INLINE 1 //define L_shr as inline function +#define ADD_IS_INLINE 1 //define add as inline function //add, inline is the best +#define SUB_IS_INLINE 1 //define sub as inline function //sub, inline is the best +#define DIV_S_IS_INLINE 1 //define div_s as inline function +#define MULT_IS_INLINE 1 //define mult as inline function +#define NORM_S_IS_INLINE 1 //define norm_s as inline function +#define NORM_L_IS_INLINE 1 //define norm_l as inline function +#define ROUND_IS_INLINE 1 //define round as inline function +#define L_MAC_IS_INLINE 1 //define L_mac as inline function +#define L_ADD_IS_INLINE 1 //define L_add as inline function +#define EXTRACT_H_IS_INLINE 1 //define extract_h as inline function +#define EXTRACT_L_IS_INLINE 1 //define extract_l as inline function //??? +#define MULT_R_IS_INLINE 1 //define mult_r as inline function +#define SHR_R_IS_INLINE 1 //define shr_r as inline function +#define MAC_R_IS_INLINE 1 //define mac_r as inline function +#define MSU_R_IS_INLINE 1 //define msu_r as inline function +#define L_SHR_R_IS_INLINE 1 //define L_shr_r as inline function + +#define PREFIX voAACEnc +#define LINK0(x, y, z) LINK1(x,y,z) +#define LINK1(x,y,z) x##y##z +#define ADD_PREFIX(func) LINK0(PREFIX, _, func) + +#define L_Extract ADD_PREFIX(L_Extract) +#define L_Comp ADD_PREFIX(L_Comp) +#define Mpy_32 ADD_PREFIX(Mpy_32) +#define Mpy_32_16 ADD_PREFIX(Mpy_32_16) +#define Div_32 ADD_PREFIX(Div_32) +#define iLog4 ADD_PREFIX(iLog4) +#define rsqrt ADD_PREFIX(rsqrt) +#define pow2_xy ADD_PREFIX(pow2_xy) +#define L_mpy_ls ADD_PREFIX(L_mpy_ls) +#define L_mpy_wx ADD_PREFIX(L_mpy_wx) + +#define mem_malloc ADD_PREFIX(mem_malloc) +#define mem_free ADD_PREFIX(mem_free) + +#endif diff --git a/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile b/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b4f63af2b30304045185de54ee345a8fdc617c69 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile @@ -0,0 +1,55 @@ +#/* +#** Copyright 2003-2010, VisualOn, Inc. +#** +#** 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. +#*/ + +# target6 +# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon) +VOTT:= v5 + + +# module type +# please specify the type of your module: lib or exe +VOMT:= lib + + +# module macros +# please append the additional macro definitions here for your module if necessary. +# e.g. -DVISUALON, macro VISUALON defined for your module +VOMM:= -DARMV5E -DARM_INASM -DARMV5_INASM + + + +# please specify the name of your module +VOTARGET:=libvoAACEncv5 + + +# please modify here to be sure to see the g1.mk +include ../../../../../Tools/eclair.mk + +# dependent libraries. +VODEPLIBS:=#-ldl -lstdc++ + +# module source +# please modify here to be sure to see the ms.mk which specifies all source info of your module +include ../../ms.mk + + +# please specify where is the voRelease on your PC, relative path is suggested +VORELDIR:=../../../../../../Release + + +# please modify here to be sure to see the doit.mk +include ../../../../../Tools/doit.mk + diff --git a/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile b/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..cdce2c1dcc7d68f44f293a0255429e7deb4d7165 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile @@ -0,0 +1,55 @@ +#/* +#** Copyright 2003-2010, VisualOn, Inc. +#** +#** 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. +#*/ + +# target6 +# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon) +VOTT:= v7 + + +# module type +# please specify the type of your module: lib or exe +VOMT:= lib + + +# module macros +# please append the additional macro definitions here for your module if necessary. +# e.g. -DVISUALON, macro VISUALON defined for your module +VOMM:= -DARMV5E -DARMV7Neon -DARM_INASM -DARMV5_INASM + + + +# please specify the name of your module +VOTARGET:=libvoAACEncv7 + + +# please modify here to be sure to see the g1.mk +include ../../../../../Tools/eclair.mk + +# dependent libraries. +VODEPLIBS:=#-ldl -lstdc++ + +# module source +# please modify here to be sure to see the ms.mk which specifies all source info of your module +include ../../ms.mk + + +# please specify where is the voRelease on your PC, relative path is suggested +VORELDIR:=../../../../../../Release + + +# please modify here to be sure to see the doit.mk +include ../../../../../Tools/doit.mk + diff --git a/media/libstagefright/codecs/aacenc/build/eclair/makefile b/media/libstagefright/codecs/aacenc/build/eclair/makefile new file mode 100644 index 0000000000000000000000000000000000000000..6bb3c13a47a0dc6ce622ec22e64ff369523ef639 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/build/eclair/makefile @@ -0,0 +1,40 @@ +#/* +#** Copyright 2003-2010, VisualOn, Inc. +#** +#** 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. +#*/ + +# Just acting as Father Makefile of Modules +# please keep the name 'makefile' unchanged + +# Module Subdirs +VOMSD:=$(dir $(shell find . -name 'Makefile')) + +all: + for dir in $(VOMSD); \ + do \ + $(MAKE) -C $$dir; \ + done + +.PHONY:clean devel +clean: + for dir in $(VOMSD); \ + do \ + $(MAKE) -C $$dir clean; \ + done + +devel: + for dir in $(VOMSD); \ + do \ + $(MAKE) -C $$dir devel; \ + done diff --git a/media/libstagefright/codecs/aacenc/build/ms.mk b/media/libstagefright/codecs/aacenc/build/ms.mk new file mode 100644 index 0000000000000000000000000000000000000000..b67efbcf0b09deaf5d8d75ac3a898d275911e74f --- /dev/null +++ b/media/libstagefright/codecs/aacenc/build/ms.mk @@ -0,0 +1,42 @@ +#/* +#** Copyright 2003-2010, VisualOn, Inc. +#** +#** 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. +#*/ + + +# please list all objects needed by your target here +OBJS:=basicop2.o oper_32b.o aac_rom.o aacenc.o aacenc_core.o adj_thr.o \ + band_nrg.o bit_cnt.o bitbuffer.o bitenc.o block_switch.o channel_map.o \ + dyn_bits.o grp_data.o interface.o line_pe.o memalign.o ms_stereo.o \ + pre_echo_control.o psy_configuration.o psy_main.o qc_main.o quantize.o sf_estim.o \ + spreading.o stat_bits.o tns.o transform.o + +# please list all directories that all source files relative with your module(.h .c .cpp) locate +VOSRCDIR:=../../../src \ + ../../../inc \ + ../../../basic_op\ + ../../../../../Include + +ifeq ($(VOTT), v5) +OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \ + PrePostMDCT_v5.o R4R8First_v5.o Radix4FFT_v5.o +VOSRCDIR+= ../../../src/asm/ARMV5E/ +endif + +ifeq ($(VOTT), v7) +OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \ + PrePostMDCT_v7.o R4R8First_v7.o Radix4FFT_v7.o +VOSRCDIR+= ../../../src/asm/ARMV5E/ +VOSRCDIR+= ../../../src/asm/ARMV7/ +endif \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/doc/voAACEncoderSDK.pdf b/media/libstagefright/codecs/aacenc/doc/voAACEncoderSDK.pdf new file mode 100644 index 0000000000000000000000000000000000000000..874d0f7fc267bf8b0536dab24e366089c54ecbbd Binary files /dev/null and b/media/libstagefright/codecs/aacenc/doc/voAACEncoderSDK.pdf differ diff --git a/media/libstagefright/codecs/aacenc/inc/aac_rom.h b/media/libstagefright/codecs/aacenc/inc/aac_rom.h new file mode 100644 index 0000000000000000000000000000000000000000..b0429fccfc5a6d56c2c6bc6ee4ba9e7bdc38ed5c --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/aac_rom.h @@ -0,0 +1,117 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: aac_rom.h + + Content: constant tables + +*******************************************************************************/ + +#ifndef ROM_H +#define ROM_H + +#include "config.h" +#include "psy_const.h" +#include "tns_param.h" + +/* + mdct +*/ +extern const int ShortWindowSine[FRAME_LEN_SHORT/2]; +extern const int LongWindowKBD[FRAME_LEN_LONG/2]; + +extern const unsigned char bitrevTab[17 + 129]; +extern const int cossintab[128 + 1024]; + +#if defined (ARMV5E) && !defined (ARMV7Neon) +extern const int twidTab64[(4*6 + 16*6)/2]; +extern const int twidTab512[(8*6 + 32*6 + 128*6)/2]; +#else +extern const int twidTab64[4*6 + 16*6]; +extern const int twidTab512[8*6 + 32*6 + 128*6]; +#endif + +/* + form factor +*/ +extern const Word32 formfac_sqrttable[96]; + +/* + quantizer +*/ +extern const Word32 mTab_3_4[512]; +extern const Word32 mTab_4_3[512]; +/*! $2^{-\frac{n}{16}}$ table */ +extern const Word16 pow2tominusNover16[17] ; + +extern Word32 specExpMantTableComb_enc[4][14]; +extern const UWord8 specExpTableComb_enc[4][14]; + +extern const Word16 quantBorders[4][4]; +//extern const Word16 quantRecon[3][4]; +extern const Word16 quantRecon[4][3]; + +/* + huffman +*/ +extern const UWord16 huff_ltab1_2[3][3][3][3]; +extern const UWord16 huff_ltab3_4[3][3][3][3]; +extern const UWord16 huff_ltab5_6[9][9]; +extern const UWord16 huff_ltab7_8[8][8]; +extern const UWord16 huff_ltab9_10[13][13]; +extern const UWord16 huff_ltab11[17][17]; +extern const UWord16 huff_ltabscf[121]; +extern const UWord16 huff_ctab1[3][3][3][3]; +extern const UWord16 huff_ctab2[3][3][3][3]; +extern const UWord16 huff_ctab3[3][3][3][3]; +extern const UWord16 huff_ctab4[3][3][3][3]; +extern const UWord16 huff_ctab5[9][9]; +extern const UWord16 huff_ctab6[9][9]; +extern const UWord16 huff_ctab7[8][8]; +extern const UWord16 huff_ctab8[8][8]; +extern const UWord16 huff_ctab9[13][13]; +extern const UWord16 huff_ctab10[13][13]; +extern const UWord16 huff_ctab11[17][17]; +extern const UWord32 huff_ctabscf[121]; + + + +/* + misc +*/ +extern const int sampRateTab[NUM_SAMPLE_RATES]; +extern const int BandwithCoefTab[8][NUM_SAMPLE_RATES]; +extern const int rates[8]; +extern const UWord8 sfBandTotalShort[NUM_SAMPLE_RATES]; +extern const UWord8 sfBandTotalLong[NUM_SAMPLE_RATES]; +extern const int sfBandTabShortOffset[NUM_SAMPLE_RATES]; +extern const short sfBandTabShort[76]; +extern const int sfBandTabLongOffset[NUM_SAMPLE_RATES]; +extern const short sfBandTabLong[325]; + +extern const Word32 m_log2_table[INT_BITS]; + +/* + TNS +*/ +extern const Word32 tnsCoeff3[8]; +extern const Word32 tnsCoeff3Borders[8]; +extern const Word32 tnsCoeff4[16]; +extern const Word32 tnsCoeff4Borders[16]; +extern const Word32 invSBF[24]; +extern const Word16 sideInfoTabLong[MAX_SFB_LONG + 1]; +extern const Word16 sideInfoTabShort[MAX_SFB_SHORT + 1]; +#endif diff --git a/media/libstagefright/codecs/aacenc/inc/aacenc_core.h b/media/libstagefright/codecs/aacenc/inc/aacenc_core.h new file mode 100644 index 0000000000000000000000000000000000000000..faa1d20c6a37dd89b684e9ba5885d82ad9685447 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/aacenc_core.h @@ -0,0 +1,117 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: aacenc_core.h + + Content: aac encoder interface functions + +*******************************************************************************/ + +#ifndef _aacenc_core_h_ +#define _aacenc_core_h_ + + +#include "typedef.h" +#include "config.h" +#include "bitenc.h" + +#include "psy_configuration.h" +#include "psy_main.h" +#include "qc_main.h" +#include "psy_main.h" +/*-------------------------- defines --------------------------------------*/ + + +/*-------------------- structure definitions ------------------------------*/ +typedef struct { + Word32 sampleRate; /* audio file sample rate */ + Word32 bitRate; /* encoder bit rate in bits/sec */ + Word16 nChannelsIn; /* number of channels on input (1,2) */ + Word16 nChannelsOut; /* number of channels on output (1,2) */ + Word16 bandWidth; /* targeted audio bandwidth in Hz */ + Word16 adtsUsed; /* whether write adts header */ +} AACENC_CONFIG; + + +typedef struct { + + AACENC_CONFIG config; /* Word16 size: 8 */ + + ELEMENT_INFO elInfo; /* Word16 size: 4 */ + + QC_STATE qcKernel; /* Word16 size: 6 + 5(PADDING) + 7(ELEMENT_BITS) + 54(ADJ_THR_STATE) = 72 */ + QC_OUT qcOut; /* Word16 size: MAX_CHANNELS*920(QC_OUT_CHANNEL) + 5(QC_OUT_ELEMENT) + 7 = 932 / 1852 */ + + PSY_OUT psyOut; /* Word16 size: MAX_CHANNELS*186 + 2 = 188 / 374 */ + PSY_KERNEL psyKernel; /* Word16 size: 2587 / 4491 */ + + struct BITSTREAMENCODER_INIT bseInit; /* Word16 size: 6 */ + struct BIT_BUF bitStream; /* Word16 size: 8 */ + HANDLE_BIT_BUF hBitStream; + int initOK; + + short *intbuf; + short *encbuf; + short *inbuf; + int enclen; + int inlen; + int intlen; + int uselength; + + void *hCheck; + VO_MEM_OPERATOR *voMemop; + VO_MEM_OPERATOR voMemoprator; + +}AAC_ENCODER; /* Word16 size: 3809 / 6851 */ + +/*----------------------------------------------------------------------------- + +functionname: AacInitDefaultConfig +description: gives reasonable default configuration +returns: --- + +------------------------------------------------------------------------------*/ +void AacInitDefaultConfig(AACENC_CONFIG *config); + +/*--------------------------------------------------------------------------- + +functionname:AacEncOpen +description: allocate and initialize a new encoder instance +returns: AACENC_OK if success + +---------------------------------------------------------------------------*/ + +Word16 AacEncOpen (AAC_ENCODER *hAacEnc, /* pointer to an encoder handle, initialized on return */ + const AACENC_CONFIG config); /* pre-initialized config struct */ + +Word16 AacEncEncode(AAC_ENCODER *hAacEnc, + Word16 *timeSignal, + const UWord8 *ancBytes, /*!< pointer to ancillary data bytes */ + Word16 *numAncBytes, /*!< number of ancillary Data Bytes, send as fill element */ + UWord8 *outBytes, /*!< pointer to output buffer */ + Word32 *numOutBytes /*!< number of bytes in output buffer */ + ); + +/*--------------------------------------------------------------------------- + +functionname:AacEncClose +description: deallocate an encoder instance + +---------------------------------------------------------------------------*/ + +void AacEncClose (AAC_ENCODER* hAacEnc, VO_MEM_OPERATOR *pMemOP); /* an encoder handle */ + +#endif /* _aacenc_h_ */ diff --git a/media/libstagefright/codecs/aacenc/inc/adj_thr.h b/media/libstagefright/codecs/aacenc/inc/adj_thr.h new file mode 100644 index 0000000000000000000000000000000000000000..4057cbe96c1a3776eb0f323f15473f133044664d --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/adj_thr.h @@ -0,0 +1,57 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: adj_thr.h + + Content: Threshold compensation function + +*******************************************************************************/ + +#ifndef __ADJ_THR_H +#define __ADJ_THR_H + +#include "adj_thr_data.h" +#include "qc_data.h" +#include "interface.h" + +Word16 bits2pe(const Word16 bits); + +Word32 AdjThrNew(ADJ_THR_STATE** phAdjThr, + Word32 nElements); + +void AdjThrDelete(ADJ_THR_STATE *hAdjThr); + +void AdjThrInit(ADJ_THR_STATE *hAdjThr, + const Word32 peMean, + Word32 chBitrate); + +void AdjustThresholds(ADJ_THR_STATE *adjThrState, + ATS_ELEMENT* AdjThrStateElement, + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT *psyOutElement, + Word16 *chBitDistribution, + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], + Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB], + QC_OUT_ELEMENT* qcOE, + ELEMENT_BITS* elBits, + const Word16 nChannels, + const Word16 maxBitFac); + +void AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement, + const Word16 dynBitsUsed); + + +#endif diff --git a/media/libstagefright/codecs/aacenc/inc/adj_thr_data.h b/media/libstagefright/codecs/aacenc/inc/adj_thr_data.h new file mode 100644 index 0000000000000000000000000000000000000000..25dd43738f3c7a4e4edd29edd62f16b4e804a156 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/adj_thr_data.h @@ -0,0 +1,69 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: adj_thr_data.h + + Content: Threshold compensation parameter + +*******************************************************************************/ + +#ifndef __ADJ_THR_DATA_H +#define __ADJ_THR_DATA_H + +#include "typedef.h" +#include "psy_const.h" +#include "line_pe.h" + +typedef struct { + Word16 clipSaveLow, clipSaveHigh; + Word16 minBitSave, maxBitSave; + Word16 clipSpendLow, clipSpendHigh; + Word16 minBitSpend, maxBitSpend; +} BRES_PARAM; + +typedef struct { + UWord8 modifyMinSnr; + Word16 startSfbL, startSfbS; +} AH_PARAM; + +typedef struct { + Word32 maxRed; + Word32 startRatio, maxRatio; + Word32 redRatioFac; + Word32 redOffs; +} MINSNR_ADAPT_PARAM; + +typedef struct { + /* parameters for bitreservoir control */ + Word16 peMin, peMax; + /* constant offset to pe */ + Word16 peOffset; + /* avoid hole parameters */ + AH_PARAM ahParam; + /* paramters for adaptation of minSnr */ + MINSNR_ADAPT_PARAM minSnrAdaptParam; + /* values for correction of pe */ + Word16 peLast; + Word16 dynBitsLast; + Word16 peCorrectionFactor; +} ATS_ELEMENT; + +typedef struct { + BRES_PARAM bresParamLong, bresParamShort; /* Word16 size: 2*8 */ + ATS_ELEMENT adjThrStateElem; /* Word16 size: 19 */ +} ADJ_THR_STATE; + +#endif diff --git a/media/libstagefright/codecs/aacenc/inc/band_nrg.h b/media/libstagefright/codecs/aacenc/inc/band_nrg.h new file mode 100644 index 0000000000000000000000000000000000000000..68509da34b31af4b379fd13c91838509db71f60a --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/band_nrg.h @@ -0,0 +1,46 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: band_nrg.h + + Content: Band/Line energy calculations functions + +*******************************************************************************/ + + +#ifndef _BAND_NRG_H +#define _BAND_NRG_H + +#include "typedef.h" + + +void CalcBandEnergy(const Word32 *mdctSpectrum, + const Word16 *bandOffset, + const Word16 numBands, + Word32 *bandEnergy, + Word32 *bandEnergySum); + + +void CalcBandEnergyMS(const Word32 *mdctSpectrumLeft, + const Word32 *mdctSpectrumRight, + const Word16 *bandOffset, + const Word16 numBands, + Word32 *bandEnergyMid, + Word32 *bandEnergyMidSum, + Word32 *bandEnergySide, + Word32 *bandEnergySideSum); + +#endif diff --git a/media/libstagefright/codecs/aacenc/inc/bit_cnt.h b/media/libstagefright/codecs/aacenc/inc/bit_cnt.h new file mode 100644 index 0000000000000000000000000000000000000000..808319e989290adc37ff657c24d9c7c1f4c63776 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/bit_cnt.h @@ -0,0 +1,106 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: bit_cnt.h + + Content: Huffman Bitcounter & coder structure and functions + +*******************************************************************************/ + +#ifndef __BITCOUNT_H +#define __BITCOUNT_H + +#include "bitbuffer.h" +#include "basic_op.h" +#define INVALID_BITCOUNT (MAX_16/4) + +/* + code book number table +*/ + +enum codeBookNo{ + CODE_BOOK_ZERO_NO= 0, + CODE_BOOK_1_NO= 1, + CODE_BOOK_2_NO= 2, + CODE_BOOK_3_NO= 3, + CODE_BOOK_4_NO= 4, + CODE_BOOK_5_NO= 5, + CODE_BOOK_6_NO= 6, + CODE_BOOK_7_NO= 7, + CODE_BOOK_8_NO= 8, + CODE_BOOK_9_NO= 9, + CODE_BOOK_10_NO= 10, + CODE_BOOK_ESC_NO= 11, + CODE_BOOK_RES_NO= 12, + CODE_BOOK_PNS_NO= 13 +}; + +/* + code book index table +*/ + +enum codeBookNdx{ + CODE_BOOK_ZERO_NDX=0, + CODE_BOOK_1_NDX, + CODE_BOOK_2_NDX, + CODE_BOOK_3_NDX, + CODE_BOOK_4_NDX, + CODE_BOOK_5_NDX, + CODE_BOOK_6_NDX, + CODE_BOOK_7_NDX, + CODE_BOOK_8_NDX, + CODE_BOOK_9_NDX, + CODE_BOOK_10_NDX, + CODE_BOOK_ESC_NDX, + CODE_BOOK_RES_NDX, + CODE_BOOK_PNS_NDX, + NUMBER_OF_CODE_BOOKS +}; + +/* + code book lav table +*/ + +enum codeBookLav{ + CODE_BOOK_ZERO_LAV=0, + CODE_BOOK_1_LAV=1, + CODE_BOOK_2_LAV=1, + CODE_BOOK_3_LAV=2, + CODE_BOOK_4_LAV=2, + CODE_BOOK_5_LAV=4, + CODE_BOOK_6_LAV=4, + CODE_BOOK_7_LAV=7, + CODE_BOOK_8_LAV=7, + CODE_BOOK_9_LAV=12, + CODE_BOOK_10_LAV=12, + CODE_BOOK_ESC_LAV=16, + CODE_BOOK_SCF_LAV=60, + CODE_BOOK_PNS_LAV=60 +}; + +Word16 bitCount(const Word16 *aQuantSpectrum, + const Word16 noOfSpecLines, + Word16 maxVal, + Word16 *bitCountLut); + +Word16 codeValues(Word16 *values, Word16 width, Word16 codeBook, HANDLE_BIT_BUF hBitstream); + +Word16 bitCountScalefactorDelta(Word16 delta); +Word16 codeScalefactorDelta(Word16 scalefactor, HANDLE_BIT_BUF hBitstream); + + + +#endif diff --git a/media/libstagefright/codecs/aacenc/inc/bitbuffer.h b/media/libstagefright/codecs/aacenc/inc/bitbuffer.h new file mode 100644 index 0000000000000000000000000000000000000000..cb850c98bd02e91b2a51238141d7987aa1679c9a --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/bitbuffer.h @@ -0,0 +1,89 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: bitbuffer.h + + Content: Bit Buffer Management structure and functions + +*******************************************************************************/ + +#ifndef BITBUFFER_H +#define BITBUFFER_H + +#include "typedef.h" + + +enum direction +{ + forwardDirection, + backwardDirection +}; + + +/*! + The pointer 'pReadNext' points to the next available word, where bits can be read from. The pointer + 'pWriteNext' points to the next available word, where bits can be written to. The pointer pBitBufBase + points to the start of the bitstream buffer and the pointer pBitBufEnd points to the end of the bitstream + buffer. The two pointers are used as lower-bound respectively upper-bound address for the modulo addressing + mode. + + The element cntBits contains the currently available bits in the bit buffer. It will be incremented when + bits are written to the bitstream buffer and decremented when bits are read from the bitstream buffer. +*/ +struct BIT_BUF +{ + UWord8 *pBitBufBase; /*!< pointer points to first position in bitstream buffer */ + UWord8 *pBitBufEnd; /*!< pointer points to last position in bitstream buffer */ + + UWord8 *pWriteNext; /*!< pointer points to next available word in bitstream buffer to write */ + + UWord32 cache; + + Word16 wBitPos; /*!< 31<=wBitPos<=0*/ + Word16 cntBits; /*!< number of available bits in the bitstream buffer + write bits to bitstream buffer => increment cntBits + read bits from bitstream buffer => decrement cntBits */ + Word16 size; /*!< size of bitbuffer in bits */ + Word16 isValid; /*!< indicates whether the instance has been initialized */ +}; /* size Word16: 8 */ + +/*! Define pointer to bit buffer structure */ +typedef struct BIT_BUF *HANDLE_BIT_BUF; + + +HANDLE_BIT_BUF CreateBitBuffer(HANDLE_BIT_BUF hBitBuf, + UWord8 *pBitBufBase, + Word16 bitBufSize); + + +void DeleteBitBuffer(HANDLE_BIT_BUF *hBitBuf); + + +Word16 GetBitsAvail(HANDLE_BIT_BUF hBitBuf); + + +Word16 WriteBits(HANDLE_BIT_BUF hBitBuf, + Word32 writeValue, + Word16 noBitsToWrite); + +void ResetBitBuf(HANDLE_BIT_BUF hBitBuf, + UWord8 *pBitBufBase, + Word16 bitBufSize); + +#define GetNrBitsAvailable(hBitBuf) ( (hBitBuf)->cntBits) +#define GetNrBitsRead(hBitBuf) ((hBitBuf)->size-(hBitBuf)->cntBits) + +#endif /* BITBUFFER_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/bitenc.h b/media/libstagefright/codecs/aacenc/inc/bitenc.h new file mode 100644 index 0000000000000000000000000000000000000000..1151057a7ad7cb2aed3a9412f4ae4971a0330233 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/bitenc.h @@ -0,0 +1,50 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: bitenc.h + + Content: Bitstream encoder structure and functions + +*******************************************************************************/ + +#ifndef _BITENC_H +#define _BITENC_H + +#include "qc_data.h" +#include "tns.h" +#include "channel_map.h" +#include "interface.h" + +struct BITSTREAMENCODER_INIT +{ + Word16 nChannels; + Word32 bitrate; + Word32 sampleRate; + Word16 profile; +}; + + + +Word16 WriteBitstream (HANDLE_BIT_BUF hBitstream, + ELEMENT_INFO elInfo, + QC_OUT *qcOut, + PSY_OUT *psyOut, + Word16 *globUsedBits, + const UWord8 *ancBytes, + Word16 samplerate + ); + +#endif /* _BITENC_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/block_switch.h b/media/libstagefright/codecs/aacenc/inc/block_switch.h new file mode 100644 index 0000000000000000000000000000000000000000..3e35819887a9830bb472e17eadfc775815e7eb92 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/block_switch.h @@ -0,0 +1,72 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: block_switch.h + + Content: Block switching structure and functions + +*******************************************************************************/ + +#ifndef _BLOCK_SWITCH_H +#define _BLOCK_SWITCH_H + +#include "typedef.h" + + +/****************** Defines ******************************/ +#define BLOCK_SWITCHING_IIR_LEN 2 /* Length of HighPass-FIR-Filter for Attack-Detection */ +#define BLOCK_SWITCH_WINDOWS TRANS_FAC /* number of windows for energy calculation */ +#define BLOCK_SWITCH_WINDOW_LEN FRAME_LEN_SHORT /* minimal granularity of energy calculation */ + + + +/****************** Structures ***************************/ +typedef struct{ + Word32 invAttackRatio; + Word16 windowSequence; + Word16 nextwindowSequence; + Flag attack; + Flag lastattack; + Word16 attackIndex; + Word16 lastAttackIndex; + Word16 noOfGroups; + Word16 groupLen[TRANS_FAC]; + Word32 windowNrg[2][BLOCK_SWITCH_WINDOWS]; /* time signal energy in Subwindows (last and current) */ + Word32 windowNrgF[2][BLOCK_SWITCH_WINDOWS]; /* filtered time signal energy in segments (last and current) */ + Word32 iirStates[BLOCK_SWITCHING_IIR_LEN]; /* filter delay-line */ + Word32 maxWindowNrg; /* max energy in subwindows */ + Word32 accWindowNrg; /* recursively accumulated windowNrgF */ +}BLOCK_SWITCHING_CONTROL; + + + + + +Word16 InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, + const Word32 bitRate, const Word16 nChannels); + +Word16 BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, + Word16 *timeSignal, + Word32 sampleRate, + Word16 chIncrement); + +Word16 SyncBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, + BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, + const Word16 noOfChannels); + + + +#endif /* #ifndef _BLOCK_SWITCH_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/channel_map.h b/media/libstagefright/codecs/aacenc/inc/channel_map.h new file mode 100644 index 0000000000000000000000000000000000000000..e3aa8dc14a3d246805c79943100e56af3d09e5a6 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/channel_map.h @@ -0,0 +1,37 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: channel_map.h + + Content: channel mapping functions + +*******************************************************************************/ + +#ifndef _CHANNEL_MAP_H +#define _CHANNEL_MAP_H + +#include "psy_const.h" +#include "qc_data.h" + +Word16 InitElementInfo (Word16 nChannels, ELEMENT_INFO* elInfo); + +Word16 InitElementBits(ELEMENT_BITS *elementBits, + ELEMENT_INFO elInfo, + Word32 bitrateTot, + Word16 averageBitsTot, + Word16 staticBitsTot); + +#endif /* CHANNEL_MAP_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/config.h b/media/libstagefright/codecs/aacenc/inc/config.h new file mode 100644 index 0000000000000000000000000000000000000000..6211c8f0fcbe2d89d1fe03fc217c1c2084d49605 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/config.h @@ -0,0 +1,36 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: config.h + + Content: aac encoder parameter + +*******************************************************************************/ + +#ifndef _AACENC_CONFIG_H_ +#define _AACENC_CONFIG_H_ + +#define MAX_CHANNELS 2 + +#define AACENC_BLOCKSIZE 1024 /*! encoder only takes BLOCKSIZE samples at a time */ +#define AACENC_TRANS_FAC 8 /*! encoder short long ratio */ + + +#define MAXBITS_COEF 6144 +#define MINBITS_COEF 744 + + +#endif \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/inc/dyn_bits.h b/media/libstagefright/codecs/aacenc/inc/dyn_bits.h new file mode 100644 index 0000000000000000000000000000000000000000..0468fa2bd84a05b525d2b9934b9aaf8af4aa6045 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/dyn_bits.h @@ -0,0 +1,82 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: dyn_bits.h + + Content: Noiseless coder module structure and functions + +*******************************************************************************/ + +#ifndef __DYN_BITS_H +#define __DYN_BITS_H + +#include "psy_const.h" +#include "tns.h" +#include "bit_cnt.h" + + + +#define MAX_SECTIONS MAX_GROUPED_SFB +#define SECT_ESC_VAL_LONG 31 +#define SECT_ESC_VAL_SHORT 7 +#define CODE_BOOK_BITS 4 +#define SECT_BITS_LONG 5 +#define SECT_BITS_SHORT 3 + +typedef struct +{ + Word16 codeBook; + Word16 sfbStart; + Word16 sfbCnt; + Word16 sectionBits; +} +SECTION_INFO; + + + + +typedef struct +{ + Word16 blockType; + Word16 noOfGroups; + Word16 sfbCnt; + Word16 maxSfbPerGroup; + Word16 sfbPerGroup; + Word16 noOfSections; + SECTION_INFO sectionInfo[MAX_SECTIONS]; + Word16 sideInfoBits; /* sectioning bits */ + Word16 huffmanBits; /* huffman coded bits */ + Word16 scalefacBits; /* scalefac coded bits */ + Word16 firstScf; /* first scf to be coded */ + Word16 bitLookUp[MAX_SFB_LONG*(CODE_BOOK_ESC_NDX+1)]; + Word16 mergeGainLookUp[MAX_SFB_LONG]; +} +SECTION_DATA; /* Word16 size: 10 + 60(MAX_SECTIONS)*4(SECTION_INFO) + 51(MAX_SFB_LONG)*12(CODE_BOOK_ESC_NDX+1) + 51(MAX_SFB_LONG) = 913 */ + + +Word16 BCInit(void); + +Word16 dynBitCount(const Word16 *quantSpectrum, + const UWord16 *maxValueInSfb, + const Word16 *scalefac, + const Word16 blockType, + const Word16 sfbCnt, + const Word16 maxSfbPerGroup, + const Word16 sfbPerGroup, + const Word16 *sfbOffset, + SECTION_DATA *sectionData); + +#endif diff --git a/media/libstagefright/codecs/aacenc/inc/grp_data.h b/media/libstagefright/codecs/aacenc/inc/grp_data.h new file mode 100644 index 0000000000000000000000000000000000000000..96665772a21882b76aab2783a8b00a7359a99736 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/grp_data.h @@ -0,0 +1,44 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: grp_data.h + + Content: Short block grouping function + +*******************************************************************************/ + +#ifndef __GRP_DATA_H__ +#define __GRP_DATA_H__ +#include "psy_data.h" +#include "typedefs.h" + +void +groupShortData(Word32 *mdctSpectrum, + Word32 *tmpSpectrum, + SFB_THRESHOLD *sfbThreshold, + SFB_ENERGY *sfbEnergy, + SFB_ENERGY *sfbEnergyMS, + SFB_ENERGY *sfbSpreadedEnergy, + const Word16 sfbCnt, + const Word16 *sfbOffset, + const Word16 *sfbMinSnr, + Word16 *groupedSfbOffset, + Word16 *maxSfbPerGroup, + Word16 *groupedSfbMinSnr, + const Word16 noOfGroups, + const Word16 *groupLen); + +#endif /* _INTERFACE_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/interface.h b/media/libstagefright/codecs/aacenc/inc/interface.h new file mode 100644 index 0000000000000000000000000000000000000000..b84334abb60ed643c00043455a25fff1f49f5af2 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/interface.h @@ -0,0 +1,106 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: interface.h + + Content: psychoaccoustic/quantizer structures and interface + +*******************************************************************************/ + +#ifndef _INTERFACE_H +#define _INTERFACE_H + +#include "config.h" +#include "psy_const.h" +#include "psy_data.h" +#include "typedefs.h" + + +enum +{ + MS_NONE = 0, + MS_SOME = 1, + MS_ALL = 2 +}; + +enum +{ + MS_ON = 1 +}; + +struct TOOLSINFO { + Word16 msDigest; + Word16 msMask[MAX_GROUPED_SFB]; +}; + + +typedef struct { + Word16 sfbCnt; + Word16 sfbPerGroup; + Word16 maxSfbPerGroup; + Word16 windowSequence; + Word16 windowShape; + Word16 groupingMask; + Word16 sfbOffsets[MAX_GROUPED_SFB+1]; + Word16 mdctScale; + Word32 *sfbEnergy; + Word32 *sfbSpreadedEnergy; + Word32 *sfbThreshold; + Word32 *mdctSpectrum; + Word32 sfbEnSumLR; + Word32 sfbEnSumMS; + Word32 sfbDist[MAX_GROUPED_SFB]; + Word32 sfbDistNew[MAX_GROUPED_SFB]; + Word16 sfbMinSnr[MAX_GROUPED_SFB]; + Word16 minSfMaxQuant[MAX_GROUPED_SFB]; + Word16 minScfCalculated[MAX_GROUPED_SFB]; + Word16 prevScfLast[MAX_GROUPED_SFB]; + Word16 prevScfNext[MAX_GROUPED_SFB]; + Word16 deltaPeLast[MAX_GROUPED_SFB]; + TNS_INFO tnsInfo; +} PSY_OUT_CHANNEL; /* Word16 size: 14 + 60(MAX_GROUPED_SFB) + 112(TNS_INFO) = 186 */ + +typedef struct { + struct TOOLSINFO toolsInfo; + Word16 groupedSfbOffset[MAX_CHANNELS][MAX_GROUPED_SFB+1]; /* plus one for last dummy offset ! */ + Word16 groupedSfbMinSnr[MAX_CHANNELS][MAX_GROUPED_SFB]; +} PSY_OUT_ELEMENT; + +typedef struct { + /* information shared by both channels */ + PSY_OUT_ELEMENT psyOutElement; + /* information specific to each channel */ + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS]; +}PSY_OUT; + +void BuildInterface(Word32 *mdctSpectrum, + const Word16 mdctScale, + SFB_THRESHOLD *sfbThreshold, + SFB_ENERGY *sfbEnergy, + SFB_ENERGY *sfbSpreadedEnergy, + const SFB_ENERGY_SUM sfbEnergySumLR, + const SFB_ENERGY_SUM sfbEnergySumMS, + const Word16 windowSequence, + const Word16 windowShape, + const Word16 sfbCnt, + const Word16 *sfbOffset, + const Word16 maxSfbPerGroup, + const Word16 *groupedSfbMinSnr, + const Word16 noOfGroups, + const Word16 *groupLen, + PSY_OUT_CHANNEL *psyOutCh); + +#endif /* _INTERFACE_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/line_pe.h b/media/libstagefright/codecs/aacenc/inc/line_pe.h new file mode 100644 index 0000000000000000000000000000000000000000..fed938be459efd396f399ae0391274120fc140b1 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/line_pe.h @@ -0,0 +1,75 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: line_pe.h + + Content: Perceptual entropie module structure and functions + +*******************************************************************************/ + +#ifndef __LINE_PE_H +#define __LINE_PE_H + + +#include "psy_const.h" +#include "interface.h" + + +typedef struct { + Word16 sfbLdEnergy[MAX_GROUPED_SFB]; /* 4*log(sfbEnergy)/log(2) */ + Word16 sfbNLines4[MAX_GROUPED_SFB]; /* 4*number of relevant lines in sfb */ + Word16 sfbPe[MAX_GROUPED_SFB]; /* pe for each sfb */ + Word16 sfbConstPart[MAX_GROUPED_SFB]; /* constant part for each sfb */ + Word16 sfbNActiveLines[MAX_GROUPED_SFB]; /* number of active lines in sfb */ + Word16 pe; /* sum of sfbPe */ + Word16 constPart; /* sum of sfbConstPart */ + Word16 nActiveLines; /* sum of sfbNActiveLines */ +} PE_CHANNEL_DATA; /* size Word16: 303 */ + + +typedef struct { + PE_CHANNEL_DATA peChannelData[MAX_CHANNELS]; + Word16 pe; + Word16 constPart; + Word16 nActiveLines; + Word16 offset; + Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB]; + Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB]; + Word32 sfbPeFactors[MAX_CHANNELS][MAX_GROUPED_SFB]; +} PE_DATA; /* size Word16: 303 + 4 + 120 + 240 = 667 */ + + + + +void prepareSfbPe(PE_DATA *peData, + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], + Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB], + const Word16 nChannels, + const Word16 peOffset); + + + + + +void calcSfbPe(PE_DATA *peData, + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + const Word16 nChannels); + + + + +#endif diff --git a/media/libstagefright/codecs/aacenc/inc/memalign.h b/media/libstagefright/codecs/aacenc/inc/memalign.h new file mode 100644 index 0000000000000000000000000000000000000000..3b302a792eb66c7ad9d2f5e1cf6d0f643f818554 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/memalign.h @@ -0,0 +1,35 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: memalign.h + + Content: Memory alloc alignments functions + +*******************************************************************************/ + +#ifndef __VO_AACENC_MEM_ALIGN_H__ +#define __VO_AACENC_MEM_ALIGN_H__ + +#include "voMem.h" +#include "typedef.h" + +extern void *mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID); +extern void mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID); + +#endif /* __VO_MEM_ALIGN_H__ */ + + + diff --git a/media/libstagefright/codecs/aacenc/inc/ms_stereo.h b/media/libstagefright/codecs/aacenc/inc/ms_stereo.h new file mode 100644 index 0000000000000000000000000000000000000000..6d43dec80a164f248300c6b10c5ed4f126e75316 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/ms_stereo.h @@ -0,0 +1,45 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: ms_stereo.h + + Content: Declaration MS stereo processing structure and functions + +*******************************************************************************/ + +#ifndef __MS_STEREO_H__ +#define __MS_STEREO_H__ +#include "typedef.h" + +void MsStereoProcessing(Word32 *sfbEnergyLeft, + Word32 *sfbEnergyRight, + const Word32 *sfbEnergyMid, + const Word32 *sfbEnergySide, + Word32 *mdctSpectrumLeft, + Word32 *mdctSpectrumRight, + Word32 *sfbThresholdLeft, + Word32 *sfbThresholdRight, + Word32 *sfbSpreadedEnLeft, + Word32 *sfbSpreadedEnRight, + Word16 *msDigest, + Word16 *msMask, + const Word16 sfbCnt, + const Word16 sfbPerGroup, + const Word16 maxSfbPerGroup, + const Word16 *sfbOffset); + + +#endif diff --git a/media/libstagefright/codecs/aacenc/inc/pre_echo_control.h b/media/libstagefright/codecs/aacenc/inc/pre_echo_control.h new file mode 100644 index 0000000000000000000000000000000000000000..35f36e8fc2733042967dc83eb4281b1cdcb22506 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/pre_echo_control.h @@ -0,0 +1,42 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: pre_echo_control.h + + Content: Pre echo control functions + +*******************************************************************************/ + +#ifndef __PRE_ECHO_CONTROL_H +#define __PRE_ECHO_CONTROL_H + +#include "typedefs.h" + +void InitPreEchoControl(Word32 *pbThresholdnm1, + Word16 numPb, + Word32 *pbThresholdQuiet); + + +void PreEchoControl(Word32 *pbThresholdNm1, + Word16 numPb, + Word32 maxAllowedIncreaseFactor, + Word16 minRemainingThresholdFactor, + Word32 *pbThreshold, + Word16 mdctScale, + Word16 mdctScalenm1); + +#endif + diff --git a/media/libstagefright/codecs/aacenc/inc/psy_configuration.h b/media/libstagefright/codecs/aacenc/inc/psy_configuration.h new file mode 100644 index 0000000000000000000000000000000000000000..53cf25b24af7da3d007e1aac1bc351b8f919db3a --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/psy_configuration.h @@ -0,0 +1,107 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: psy_configuration.h + + Content: Psychoaccoustic configuration structure and functions + +*******************************************************************************/ + +#ifndef _PSY_CONFIGURATION_H +#define _PSY_CONFIGURATION_H + +#include "typedefs.h" +#include "psy_const.h" +#include "tns.h" + +typedef struct{ + + Word16 sfbCnt; + Word16 sfbActive; /* number of sf bands containing energy after lowpass */ + Word16 *sfbOffset; + + Word32 sfbThresholdQuiet[MAX_SFB_LONG]; + + Word16 maxAllowedIncreaseFactor; /* preecho control */ + Word16 minRemainingThresholdFactor; + + Word16 lowpassLine; + Word16 sampRateIdx; + Word32 clipEnergy; /* for level dependend tmn */ + + Word16 ratio; + Word16 sfbMaskLowFactor[MAX_SFB_LONG]; + Word16 sfbMaskHighFactor[MAX_SFB_LONG]; + + Word16 sfbMaskLowFactorSprEn[MAX_SFB_LONG]; + Word16 sfbMaskHighFactorSprEn[MAX_SFB_LONG]; + + + Word16 sfbMinSnr[MAX_SFB_LONG]; /* minimum snr (formerly known as bmax) */ + + TNS_CONFIG tnsConf; + +}PSY_CONFIGURATION_LONG; /*Word16 size: 8 + 52 + 102 + 51 + 51 + 51 + 51 + 47 = 515 */ + + +typedef struct{ + + Word16 sfbCnt; + Word16 sfbActive; /* number of sf bands containing energy after lowpass */ + Word16 *sfbOffset; + + Word32 sfbThresholdQuiet[MAX_SFB_SHORT]; + + Word16 maxAllowedIncreaseFactor; /* preecho control */ + Word16 minRemainingThresholdFactor; + + Word16 lowpassLine; + Word16 sampRateIdx; + Word32 clipEnergy; /* for level dependend tmn */ + + Word16 ratio; + Word16 sfbMaskLowFactor[MAX_SFB_SHORT]; + Word16 sfbMaskHighFactor[MAX_SFB_SHORT]; + + Word16 sfbMaskLowFactorSprEn[MAX_SFB_SHORT]; + Word16 sfbMaskHighFactorSprEn[MAX_SFB_SHORT]; + + + Word16 sfbMinSnr[MAX_SFB_SHORT]; /* minimum snr (formerly known as bmax) */ + + TNS_CONFIG tnsConf; + +}PSY_CONFIGURATION_SHORT; /*Word16 size: 8 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 47 = 167 */ + + +/* Returns the sample rate index */ +Word32 GetSRIndex(Word32 sampleRate); + + +Word16 InitPsyConfigurationLong(Word32 bitrate, + Word32 samplerate, + Word16 bandwidth, + PSY_CONFIGURATION_LONG *psyConf); + +Word16 InitPsyConfigurationShort(Word32 bitrate, + Word32 samplerate, + Word16 bandwidth, + PSY_CONFIGURATION_SHORT *psyConf); + +#endif /* _PSY_CONFIGURATION_H */ + + + diff --git a/media/libstagefright/codecs/aacenc/inc/psy_const.h b/media/libstagefright/codecs/aacenc/inc/psy_const.h new file mode 100644 index 0000000000000000000000000000000000000000..5455ab11c5204cc1a62b88d3262543c5eb06fc9a --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/psy_const.h @@ -0,0 +1,80 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: psy_const.h + + Content: Global psychoacoustic constants structures + +*******************************************************************************/ + +#ifndef _PSYCONST_H +#define _PSYCONST_H + +#include "config.h" + +#define TRUE 1 +#define FALSE 0 + +#define FRAME_LEN_LONG AACENC_BLOCKSIZE +#define TRANS_FAC 8 +#define FRAME_LEN_SHORT (FRAME_LEN_LONG/TRANS_FAC) + + + +/* Block types */ +enum +{ + LONG_WINDOW = 0, + START_WINDOW, + SHORT_WINDOW, + STOP_WINDOW +}; + +/* Window shapes */ +enum +{ + SINE_WINDOW = 0, + KBD_WINDOW = 1 +}; + +/* + MS stuff +*/ +enum +{ + SI_MS_MASK_NONE = 0, + SI_MS_MASK_SOME = 1, + SI_MS_MASK_ALL = 2 +}; + +#define MAX_NO_OF_GROUPS 4 +#define MAX_SFB_SHORT 15 /* 15 for a memory optimized implementation, maybe 16 for convenient debugging */ +#define MAX_SFB_LONG 51 /* 51 for a memory optimized implementation, maybe 64 for convenient debugging */ +#define MAX_SFB (MAX_SFB_SHORT > MAX_SFB_LONG ? MAX_SFB_SHORT : MAX_SFB_LONG) /* = MAX_SFB_LONG */ +#define MAX_GROUPED_SFB (MAX_NO_OF_GROUPS*MAX_SFB_SHORT > MAX_SFB_LONG ? \ + MAX_NO_OF_GROUPS*MAX_SFB_SHORT : MAX_SFB_LONG) + +#define BLOCK_SWITCHING_OFFSET (1*1024+3*128+64+128) +#define BLOCK_SWITCHING_DATA_SIZE FRAME_LEN_LONG + +#define TRANSFORM_OFFSET_LONG 0 +#define TRANSFORM_OFFSET_SHORT 448 + +#define LOG_NORM_PCM -15 + +#define NUM_SAMPLE_RATES 12 + +#endif /* _PSYCONST_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/psy_data.h b/media/libstagefright/codecs/aacenc/inc/psy_data.h new file mode 100644 index 0000000000000000000000000000000000000000..1412d532e412f964e41da220f1212204ccf62815 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/psy_data.h @@ -0,0 +1,66 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: psy_data.h + + Content: Psychoacoustic data and structures + +*******************************************************************************/ + +#ifndef _PSY_DATA_H +#define _PSY_DATA_H + +#include "block_switch.h" +#include "tns.h" + +/* + the structs can be implemented as unions +*/ + +typedef struct{ + Word32 sfbLong[MAX_GROUPED_SFB]; + Word32 sfbShort[TRANS_FAC][MAX_SFB_SHORT]; +}SFB_THRESHOLD; /* Word16 size: 260 */ + +typedef struct{ + Word32 sfbLong[MAX_GROUPED_SFB]; + Word32 sfbShort[TRANS_FAC][MAX_SFB_SHORT]; +}SFB_ENERGY; /* Word16 size: 260 */ + +typedef struct{ + Word32 sfbLong; + Word32 sfbShort[TRANS_FAC]; +}SFB_ENERGY_SUM; /* Word16 size: 18 */ + + +typedef struct{ + BLOCK_SWITCHING_CONTROL blockSwitchingControl; /* block switching */ + Word16 *mdctDelayBuffer; /* mdct delay buffer [BLOCK_SWITCHING_OFFSET]*/ + Word32 sfbThresholdnm1[MAX_SFB]; /* PreEchoControl */ + Word16 mdctScalenm1; /* scale of last block's mdct (PreEchoControl) */ + + SFB_THRESHOLD sfbThreshold; /* adapt */ + SFB_ENERGY sfbEnergy; /* sfb Energy */ + SFB_ENERGY sfbEnergyMS; + SFB_ENERGY_SUM sfbEnergySum; + SFB_ENERGY_SUM sfbEnergySumMS; + SFB_ENERGY sfbSpreadedEnergy; + + Word32 *mdctSpectrum; /* mdct spectrum [FRAME_LEN_LONG] */ + Word16 mdctScale; /* scale of mdct */ +}PSY_DATA; /* Word16 size: 4 + 87 + 102 + 360 + 360 + 360 + 18 + 18 + 360 = 1669 */ + +#endif /* _PSY_DATA_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/psy_main.h b/media/libstagefright/codecs/aacenc/inc/psy_main.h new file mode 100644 index 0000000000000000000000000000000000000000..ab0b8b1313a430a22a2f2d2f84ad9f65e1168d97 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/psy_main.h @@ -0,0 +1,69 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: psy_main.h + + Content: Psychoacoustic major function block + +*******************************************************************************/ + +#ifndef _PSYMAIN_H +#define _PSYMAIN_H + +#include "psy_configuration.h" +#include "qc_data.h" +#include "memalign.h" + +/* + psy kernel +*/ +typedef struct { + PSY_CONFIGURATION_LONG psyConfLong; /* Word16 size: 515 */ + PSY_CONFIGURATION_SHORT psyConfShort; /* Word16 size: 167 */ + PSY_DATA psyData[MAX_CHANNELS]; /* Word16 size: MAX_CHANNELS*1669*/ + TNS_DATA tnsData[MAX_CHANNELS]; /* Word16 size: MAX_CHANNELS*235 */ + Word32* pScratchTns; + Word16 sampleRateIdx; +}PSY_KERNEL; /* Word16 size: 2587 / 4491 */ + + +Word16 PsyNew( PSY_KERNEL *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP); +Word16 PsyDelete( PSY_KERNEL *hPsy, VO_MEM_OPERATOR *pMemOP); + +Word16 PsyOutNew( PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP); +Word16 PsyOutDelete( PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP); + +Word16 psyMainInit( PSY_KERNEL *hPsy, + Word32 sampleRate, + Word32 bitRate, + Word16 channels, + Word16 tnsMask, + Word16 bandwidth); + + +Word16 psyMain(Word16 nChannels, /*!< total number of channels */ + ELEMENT_INFO *elemInfo, + Word16 *timeSignal, /*!< interleaved time signal */ + PSY_DATA psyData[MAX_CHANNELS], + TNS_DATA tnsData[MAX_CHANNELS], + PSY_CONFIGURATION_LONG* psyConfLong, + PSY_CONFIGURATION_SHORT* psyConfShort, + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT *psyOutElement, + Word32 *pScratchTns, + Word32 sampleRate); + +#endif /* _PSYMAIN_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/qc_data.h b/media/libstagefright/codecs/aacenc/inc/qc_data.h new file mode 100644 index 0000000000000000000000000000000000000000..81d4051572f62ffa8ae284a2a38352132b64bb6d --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/qc_data.h @@ -0,0 +1,143 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: qc_data.h + + Content: Quantizing & coding structures + +*******************************************************************************/ + +#ifndef _QC_DATA_H +#define _QC_DATA_H + +#include "psy_const.h" +#include "dyn_bits.h" +#include "adj_thr_data.h" + + +#define MAX_MODES 10 + +typedef enum { + MODE_INVALID = 0, + MODE_1, /* mono */ + MODE_1_1, /* dual mono */ + MODE_2 /* stereo */ +} ENCODER_MODE; + +typedef enum { + ID_SCE=0, /* Single Channel Element */ + ID_CPE=1, /* Channel Pair Element */ + ID_CCE=2, /* Coupling Channel Element */ + ID_LFE=3, /* LFE Channel Element */ + ID_DSE=4, /* current one DSE element for ancillary is supported */ + ID_PCE=5, + ID_FIL=6, + ID_END=7 +}ELEMENT_TYPE; + +typedef struct { + ELEMENT_TYPE elType; + Word16 instanceTag; + Word16 nChannelsInEl; + Word16 ChannelIndex[MAX_CHANNELS]; +} ELEMENT_INFO; + +typedef struct { + Word32 paddingRest; +} PADDING; + + +/* Quantizing & coding stage */ + +struct QC_INIT{ + ELEMENT_INFO *elInfo; + Word16 maxBits; /* maximum number of bits in reservoir */ + Word16 averageBits; /* average number of bits we should use */ + Word16 bitRes; + Word16 meanPe; + Word32 chBitrate; + Word16 maxBitFac; + Word32 bitrate; + + PADDING padding; +}; + +typedef struct +{ + Word16 *quantSpec; /* [FRAME_LEN_LONG]; */ + UWord16 *maxValueInSfb; /* [MAX_GROUPED_SFB]; */ + Word16 *scf; /* [MAX_GROUPED_SFB]; */ + Word16 globalGain; + Word16 mdctScale; + Word16 groupingMask; + SECTION_DATA sectionData; + Word16 windowShape; +} QC_OUT_CHANNEL; + +typedef struct +{ + Word16 adtsUsed; + Word16 staticBitsUsed; /* for verification purposes */ + Word16 dynBitsUsed; /* for verification purposes */ + Word16 pe; + Word16 ancBitsUsed; + Word16 fillBits; +} QC_OUT_ELEMENT; + +typedef struct +{ + QC_OUT_CHANNEL qcChannel[MAX_CHANNELS]; + QC_OUT_ELEMENT qcElement; + Word16 totStaticBitsUsed; /* for verification purposes */ + Word16 totDynBitsUsed; /* for verification purposes */ + Word16 totAncBitsUsed; /* for verification purposes */ + Word16 totFillBits; + Word16 alignBits; + Word16 bitResTot; + Word16 averageBitsTot; +} QC_OUT; + +typedef struct { + Word32 chBitrate; + Word16 averageBits; /* brutto -> look ancillary.h */ + Word16 maxBits; + Word16 bitResLevel; + Word16 maxBitResBits; + Word16 relativeBits; /* Bits relative to total Bits scaled down by 2 */ +} ELEMENT_BITS; + +typedef struct +{ + /* this is basically struct QC_INIT */ + Word16 averageBitsTot; + Word16 maxBitsTot; + Word16 globStatBits; + Word16 nChannels; + Word16 bitResTot; + + Word16 maxBitFac; + + PADDING padding; + + ELEMENT_BITS elementBits; + ADJ_THR_STATE adjThr; + + Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB]; + Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB]; + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB]; +} QC_STATE; + +#endif /* _QC_DATA_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/qc_main.h b/media/libstagefright/codecs/aacenc/inc/qc_main.h new file mode 100644 index 0000000000000000000000000000000000000000..e1138b26d12c0cdfe983380a735ec7d6812bf6ad --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/qc_main.h @@ -0,0 +1,64 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: qc_main.h + + Content: Quantizing & coding functions + +*******************************************************************************/ + +#ifndef _QC_MAIN_H +#define _QC_MAIN_H + +#include "qc_data.h" +#include "interface.h" +#include "memalign.h" + +/* Quantizing & coding stage */ + +Word16 QCOutNew(QC_OUT *hQC, Word16 nChannels, VO_MEM_OPERATOR *pMemOP); + +void QCOutDelete(QC_OUT *hQC, VO_MEM_OPERATOR *pMemOP); + +Word16 QCNew(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP); + +Word16 QCInit(QC_STATE *hQC, + struct QC_INIT *init); + +void QCDelete(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP); + + +Word16 QCMain(QC_STATE *hQC, + ELEMENT_BITS* elBits, + ATS_ELEMENT* adjThrStateElement, + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], /* may be modified in-place */ + PSY_OUT_ELEMENT* psyOutElement, + QC_OUT_CHANNEL qcOutChannel[MAX_CHANNELS], /* out */ + QC_OUT_ELEMENT* qcOutElement, + Word16 nChannels, + Word16 ancillaryDataBytes); /* returns error code */ + +void updateBitres(QC_STATE* qcKernel, + QC_OUT* qcOut); + +Word16 FinalizeBitConsumption(QC_STATE *hQC, + QC_OUT* qcOut); + +Word16 AdjustBitrate(QC_STATE *hQC, + Word32 bitRate, + Word32 sampleRate); + +#endif /* _QC_MAIN_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/quantize.h b/media/libstagefright/codecs/aacenc/inc/quantize.h new file mode 100644 index 0000000000000000000000000000000000000000..88a95e15ae82fede26caf30f67a279d420b1a1e8 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/quantize.h @@ -0,0 +1,42 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: quantize.h + + Content: Quantization functions + +*******************************************************************************/ + +#ifndef _QUANTIZE_H_ +#define _QUANTIZE_H_ +#include "typedefs.h" + +/* quantizing */ + +#define MAX_QUANT 8191 + +void QuantizeSpectrum(Word16 sfbCnt, + Word16 maxSfbPerGroup, + Word16 sfbPerGroup, + Word16 *sfbOffset, Word32 *mdctSpectrum, + Word16 globalGain, Word16 *scalefactors, + Word16 *quantizedSpectrum); + +Word32 calcSfbDist(const Word32 *spec, + Word16 sfbWidth, + Word16 gain); + +#endif /* _QUANTIZE_H_ */ diff --git a/media/libstagefright/codecs/aacenc/inc/sf_estim.h b/media/libstagefright/codecs/aacenc/inc/sf_estim.h new file mode 100644 index 0000000000000000000000000000000000000000..b25ec3c2bb6753713d8e1c9115b410d0a8d1a4aa --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/sf_estim.h @@ -0,0 +1,46 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: sf_estim.h + + Content: Scale factor estimation functions + +*******************************************************************************/ + +#ifndef __SF_ESTIM_H__ +#define __SF_ESTIM_H__ +/* + Scale factor estimation + */ +#include "psy_const.h" +#include "interface.h" +#include "qc_data.h" + +void +CalcFormFactor(Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB], + Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB], + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + const Word16 nChannels); + +void +EstimateScaleFactors(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + QC_OUT_CHANNEL qcOutChannel[MAX_CHANNELS], + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], + Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB], + Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB], + const Word16 nChannels); +#endif \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/inc/spreading.h b/media/libstagefright/codecs/aacenc/inc/spreading.h new file mode 100644 index 0000000000000000000000000000000000000000..29cf63d16e0c90c5c7389cbb87d198465ee951b5 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/spreading.h @@ -0,0 +1,33 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: spreading.h + + Content: Spreading of energy functions + +*******************************************************************************/ + +#ifndef _SPREADING_H +#define _SPREADING_H +#include "typedefs.h" + + +void SpreadingMax(const Word16 pbCnt, + const Word16 *maskLowFactor, + const Word16 *maskHighFactor, + Word32 *pbSpreadedEnergy); + +#endif /* #ifndef _SPREADING_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/stat_bits.h b/media/libstagefright/codecs/aacenc/inc/stat_bits.h new file mode 100644 index 0000000000000000000000000000000000000000..6e90b9c76fcd3cdd69054d3f948d8d1ff191d22f --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/stat_bits.h @@ -0,0 +1,34 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: stat_bits.h + + Content: Static bit counter functions + +*******************************************************************************/ + +#ifndef __STAT_BITS_H +#define __STAT_BITS_H + +#include "psy_const.h" +#include "interface.h" + +Word16 countStaticBitdemand(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT *psyOutElement, + Word16 nChannels, + Word16 adtsUsed); + +#endif /* __STAT_BITS_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/tns.h b/media/libstagefright/codecs/aacenc/inc/tns.h new file mode 100644 index 0000000000000000000000000000000000000000..9ffcce93c903509748d4af22bf1e43034050b4a3 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/tns.h @@ -0,0 +1,108 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: tns.h + + Content: TNS structures + +*******************************************************************************/ + +#ifndef _TNS_H +#define _TNS_H + +#include "typedef.h" +#include "psy_const.h" + + + +#define TNS_MAX_ORDER 12 +#define TNS_MAX_ORDER_SHORT 5 + +#define FILTER_DIRECTION 0 + +typedef struct{ /*stuff that is tabulated dependent on bitrate etc. */ + Word16 threshOn; /* min. prediction gain for using tns TABUL * 100*/ + Word32 lpcStartFreq; /* lowest freq for lpc TABUL*/ + Word32 lpcStopFreq; /* TABUL */ + Word32 tnsTimeResolution; +}TNS_CONFIG_TABULATED; + + +typedef struct { /*assigned at InitTime*/ + Word16 tnsActive; + Word16 tnsMaxSfb; + + Word16 maxOrder; /* max. order of tns filter */ + Word16 tnsStartFreq; /* lowest freq. for tns filtering */ + Word16 coefRes; + + TNS_CONFIG_TABULATED confTab; + + Word32 acfWindow[TNS_MAX_ORDER+1]; + + Word16 tnsStartBand; + Word16 tnsStartLine; + + Word16 tnsStopBand; + Word16 tnsStopLine; + + Word16 lpcStartBand; + Word16 lpcStartLine; + + Word16 lpcStopBand; + Word16 lpcStopLine; + + Word16 tnsRatioPatchLowestCb; + Word16 tnsModifyBeginCb; + + Word16 threshold; /* min. prediction gain for using tns TABUL * 100 */ + +}TNS_CONFIG; + + +typedef struct { + Word16 tnsActive; + Word32 parcor[TNS_MAX_ORDER]; + Word16 predictionGain; +} TNS_SUBBLOCK_INFO; /* Word16 size: 26 */ + +typedef struct{ + TNS_SUBBLOCK_INFO subBlockInfo[TRANS_FAC]; +} TNS_DATA_SHORT; + +typedef struct{ + TNS_SUBBLOCK_INFO subBlockInfo; +} TNS_DATA_LONG; + +typedef struct{ + TNS_DATA_LONG tnsLong; + TNS_DATA_SHORT tnsShort; +}TNS_DATA_RAW; + +typedef struct{ + Word16 numOfSubblocks; + TNS_DATA_RAW dataRaw; +}TNS_DATA; /* Word16 size: 1 + 8*26 + 26 = 235 */ + +typedef struct{ + Word16 tnsActive[TRANS_FAC]; + Word16 coefRes[TRANS_FAC]; + Word16 length[TRANS_FAC]; + Word16 order[TRANS_FAC]; + Word16 coef[TRANS_FAC*TNS_MAX_ORDER_SHORT]; +}TNS_INFO; /* Word16 size: 72 */ + +#endif /* _TNS_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/tns_func.h b/media/libstagefright/codecs/aacenc/inc/tns_func.h new file mode 100644 index 0000000000000000000000000000000000000000..58b75b6605c59acefb9c8cfb6f2ee455b9db0015 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/tns_func.h @@ -0,0 +1,75 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: tns_func.h + + Content: TNS functions + +*******************************************************************************/ + +/* + Temporal noise shaping + */ +#ifndef _TNS_FUNC_H +#define _TNS_FUNC_H +#include "typedef.h" +#include "psy_configuration.h" + +Word16 InitTnsConfigurationLong(Word32 bitrate, + Word32 samplerate, + Word16 channels, + TNS_CONFIG *tnsConfig, + PSY_CONFIGURATION_LONG *psyConfig, + Word16 active); + +Word16 InitTnsConfigurationShort(Word32 bitrate, + Word32 samplerate, + Word16 channels, + TNS_CONFIG *tnsConfig, + PSY_CONFIGURATION_SHORT *psyConfig, + Word16 active); + +Word32 TnsDetect(TNS_DATA* tnsData, + TNS_CONFIG tC, + Word32* pScratchTns, + const Word16 sfbOffset[], + Word32* spectrum, + Word16 subBlockNumber, + Word16 blockType, + Word32 * sfbEnergy); + +void TnsSync(TNS_DATA *tnsDataDest, + const TNS_DATA *tnsDataSrc, + const TNS_CONFIG tC, + const Word16 subBlockNumber, + const Word16 blockType); + +Word16 TnsEncode(TNS_INFO* tnsInfo, + TNS_DATA* tnsData, + Word16 numOfSfb, + TNS_CONFIG tC, + Word16 lowPassLine, + Word32* spectrum, + Word16 subBlockNumber, + Word16 blockType); + +void ApplyTnsMultTableToRatios(Word16 startCb, + Word16 stopCb, + TNS_SUBBLOCK_INFO subInfo, + Word32 *thresholds); + + +#endif /* _TNS_FUNC_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/tns_param.h b/media/libstagefright/codecs/aacenc/inc/tns_param.h new file mode 100644 index 0000000000000000000000000000000000000000..26266acca057d4203e3f2d6f54e470344c7e3782 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/tns_param.h @@ -0,0 +1,52 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: tns_param.h + + Content: TNS parameters + +*******************************************************************************/ + +/* + TNS parameters + */ +#ifndef _TNS_PARAM_H +#define _TNS_PARAM_H + +#include "tns.h" + +typedef struct{ + Word32 samplingRate; + Word16 maxBandLong; + Word16 maxBandShort; +}TNS_MAX_TAB_ENTRY; + +typedef struct{ + Word32 bitRateFrom; + Word32 bitRateTo; + const TNS_CONFIG_TABULATED *paramMono_Long; /* contains TNS parameters */ + const TNS_CONFIG_TABULATED *paramMono_Short; + const TNS_CONFIG_TABULATED *paramStereo_Long; + const TNS_CONFIG_TABULATED *paramStereo_Short; +}TNS_INFO_TAB; + + +void GetTnsParam(TNS_CONFIG_TABULATED *tnsConfigTab, + Word32 bitRate, Word16 channels, Word16 blockType); + +void GetTnsMaxBands(Word32 samplingRate, Word16 blockType, Word16* tnsMaxSfb); + +#endif /* _TNS_PARAM_H */ diff --git a/media/libstagefright/codecs/aacenc/inc/transform.h b/media/libstagefright/codecs/aacenc/inc/transform.h new file mode 100644 index 0000000000000000000000000000000000000000..2666914716a344ba094d614d3074a1da81de6497 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/inc/transform.h @@ -0,0 +1,36 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: transform.h + + Content: MDCT Transform functions + +*******************************************************************************/ + +#ifndef __TRANSFORM_H__ +#define __TRANSFORM_H__ + +#include "typedef.h" + +void Transform_Real(Word16 *mdctDelayBuffer, + Word16 *timeSignal, + Word16 chIncrement, /*! channel increment */ + Word32 *realOut, + Word16 *mdctScale, + Word16 windowSequence + ); + +#endif \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/patent_disclaimer.txt b/media/libstagefright/codecs/aacenc/patent_disclaimer.txt new file mode 100644 index 0000000000000000000000000000000000000000..b4bf11d4ab14011ba28ce5ff6090529d2b7b587f --- /dev/null +++ b/media/libstagefright/codecs/aacenc/patent_disclaimer.txt @@ -0,0 +1,9 @@ + +THIS IS NOT A GRANT OF PATENT RIGHTS. + +Google makes no representation or warranty that the codecs for which +source code is made available hereunder are unencumbered by +third-party patents. Those intending to use this source code in +hardware or software products are advised that implementations of +these codecs, including in open source software or shareware, may +require patent licenses from the relevant patent holders. diff --git a/media/libstagefright/codecs/aacenc/src/aac_rom.c b/media/libstagefright/codecs/aacenc/src/aac_rom.c new file mode 100644 index 0000000000000000000000000000000000000000..2ce0352ed5d0346fdb73fde8e831b2771e0ee17a --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/aac_rom.c @@ -0,0 +1,2363 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: aac_rom.c + + Content: constant tables + +*******************************************************************************/ + +#include "aac_rom.h" + +#if defined (ARMV5E) && !defined (ARMV7Neon) + +/* + * Q30 for 128 and 1024 + * + * for (i = 0; i < num/4; i++) { + * angle = (i + 0.125) * M_PI / num; + * x = cos(angle) * (1 << 30); + * x = sin(angle) * (1 << 30); + * + * angle = (num/2 - 1 - i + 0.125) * M_PI / num; + * x = cos(angle) * (1 << 30); + * x = sin(angle) * (1 << 30); + * } + */ +const int cossintab[128 + 1024] = { + /* 128 */ + 0x3fffec43, 0x003243f1, 0x015fd4d2, 0x3ffc38d1, 0x3ff9c13a, 0x01c454f5, 0x02f1b755, 0x3feea776, + 0x3fe9b8a9, 0x03562038, 0x0483259d, 0x3fd73a4a, 0x3fcfd50b, 0x04e767c5, 0x0613e1c5, 0x3fb5f4ea, + 0x3fac1a5b, 0x0677edbb, 0x07a3adff, 0x3f8adc77, 0x3f7e8e1e, 0x08077457, 0x09324ca7, 0x3f55f796, + 0x3f473759, 0x0995bdfd, 0x0abf8043, 0x3f174e70, 0x3f061e95, 0x0b228d42, 0x0c4b0b94, 0x3eceeaad, + 0x3ebb4ddb, 0x0cada4f5, 0x0dd4b19a, 0x3e7cd778, 0x3e66d0b4, 0x0e36c82a, 0x0f5c35a3, 0x3e212179, + 0x3e08b42a, 0x0fbdba40, 0x10e15b4e, 0x3dbbd6d4, 0x3da106bd, 0x11423ef0, 0x1263e699, 0x3d4d0728, + 0x3d2fd86c, 0x12c41a4f, 0x13e39be9, 0x3cd4c38b, 0x3cb53aaa, 0x144310dd, 0x15604013, 0x3c531e88, + 0x3c314060, 0x15bee78c, 0x16d99864, 0x3bc82c1f, 0x3ba3fde7, 0x173763c9, 0x184f6aab, 0x3b3401bb, + 0x3b0d8909, 0x18ac4b87, 0x19c17d44, 0x3a96b636, 0x3a6df8f8, 0x1a1d6544, 0x1b2f971e, 0x39f061d2, + 0x39c5664f, 0x1b8a7815, 0x1c997fc4, 0x39411e33, 0x3913eb0e, 0x1cf34baf, 0x1dfeff67, 0x38890663, + 0x3859a292, 0x1e57a86d, 0x1f5fdee6, 0x37c836c2, 0x3796a996, 0x1fb7575c, 0x20bbe7d8, 0x36fecd0e, + 0x36cb1e2a, 0x21122240, 0x2212e492, 0x362ce855, 0x35f71fb1, 0x2267d3a0, 0x2364a02e, 0x3552a8f4, + 0x351acedd, 0x23b836ca, 0x24b0e699, 0x34703095, 0x34364da6, 0x250317df, 0x25f78497, 0x3385a222, + 0x3349bf48, 0x264843d9, 0x273847c8, 0x329321c7, 0x32554840, 0x27878893, 0x2872feb6, 0x3198d4ea, + 0x31590e3e, 0x28c0b4d2, 0x29a778db, 0x3096e223, 0x30553828, 0x29f3984c, 0x2ad586a3, 0x2f8d713a, + 0x2f49ee0f, 0x2b2003ac, 0x2bfcf97c, 0x2e7cab1c, 0x2e37592c, 0x2c45c8a0, 0x2d1da3d5, 0x2d64b9da, + /* 1024 */ + 0x3fffffb1, 0x0006487f, 0x002bfb74, 0x3ffff0e3, 0x3fffe705, 0x00388c6e, 0x005e3f4c, 0x3fffba9b, + 0x3fffa6de, 0x006ad03b, 0x009082ea, 0x3fff5cd8, 0x3fff3f3c, 0x009d13c5, 0x00c2c62f, 0x3ffed79b, + 0x3ffeb021, 0x00cf56ef, 0x00f508fc, 0x3ffe2ae5, 0x3ffdf98c, 0x01019998, 0x01274b31, 0x3ffd56b5, + 0x3ffd1b7e, 0x0133dba3, 0x01598cb1, 0x3ffc5b0c, 0x3ffc15f7, 0x01661cf0, 0x018bcd5b, 0x3ffb37ec, + 0x3ffae8f9, 0x01985d60, 0x01be0d11, 0x3ff9ed53, 0x3ff99483, 0x01ca9cd4, 0x01f04bb4, 0x3ff87b44, + 0x3ff81896, 0x01fcdb2e, 0x02228924, 0x3ff6e1bf, 0x3ff67534, 0x022f184d, 0x0254c544, 0x3ff520c5, + 0x3ff4aa5d, 0x02615414, 0x0286fff3, 0x3ff33858, 0x3ff2b813, 0x02938e62, 0x02b93914, 0x3ff12878, + 0x3ff09e56, 0x02c5c71a, 0x02eb7086, 0x3feef126, 0x3fee5d28, 0x02f7fe1c, 0x031da62b, 0x3fec9265, + 0x3febf48b, 0x032a3349, 0x034fd9e5, 0x3fea0c35, 0x3fe96480, 0x035c6682, 0x03820b93, 0x3fe75e98, + 0x3fe6ad08, 0x038e97a9, 0x03b43b17, 0x3fe48990, 0x3fe3ce26, 0x03c0c69e, 0x03e66852, 0x3fe18d1f, + 0x3fe0c7da, 0x03f2f342, 0x04189326, 0x3fde6945, 0x3fdd9a27, 0x04251d77, 0x044abb73, 0x3fdb1e06, + 0x3fda450f, 0x0457451d, 0x047ce11a, 0x3fd7ab64, 0x3fd6c894, 0x04896a16, 0x04af03fc, 0x3fd4115f, + 0x3fd324b7, 0x04bb8c42, 0x04e123fa, 0x3fd04ffc, 0x3fcf597c, 0x04edab83, 0x051340f6, 0x3fcc673b, + 0x3fcb66e4, 0x051fc7b9, 0x05455ad1, 0x3fc8571f, 0x3fc74cf3, 0x0551e0c7, 0x0577716b, 0x3fc41fac, + 0x3fc30baa, 0x0583f68c, 0x05a984a6, 0x3fbfc0e3, 0x3fbea30c, 0x05b608eb, 0x05db9463, 0x3fbb3ac7, + 0x3fba131b, 0x05e817c3, 0x060da083, 0x3fb68d5b, 0x3fb55bdc, 0x061a22f7, 0x063fa8e7, 0x3fb1b8a2, + 0x3fb07d50, 0x064c2a67, 0x0671ad71, 0x3facbc9f, 0x3fab777b, 0x067e2df5, 0x06a3ae00, 0x3fa79954, + 0x3fa64a5f, 0x06b02d81, 0x06d5aa77, 0x3fa24ec6, 0x3fa0f600, 0x06e228ee, 0x0707a2b7, 0x3f9cdcf7, + 0x3f9b7a62, 0x0714201b, 0x073996a1, 0x3f9743eb, 0x3f95d787, 0x074612eb, 0x076b8616, 0x3f9183a5, + 0x3f900d72, 0x0778013d, 0x079d70f7, 0x3f8b9c28, 0x3f8a1c29, 0x07a9eaf5, 0x07cf5726, 0x3f858d79, + 0x3f8403ae, 0x07dbcff2, 0x08013883, 0x3f7f579b, 0x3f7dc405, 0x080db016, 0x083314f1, 0x3f78fa92, + 0x3f775d31, 0x083f8b43, 0x0864ec4f, 0x3f727661, 0x3f70cf38, 0x08716159, 0x0896be80, 0x3f6bcb0e, + 0x3f6a1a1c, 0x08a3323a, 0x08c88b65, 0x3f64f89b, 0x3f633de2, 0x08d4fdc6, 0x08fa52de, 0x3f5dff0e, + 0x3f5c3a8f, 0x0906c3e0, 0x092c14ce, 0x3f56de6a, 0x3f551026, 0x09388469, 0x095dd116, 0x3f4f96b4, + 0x3f4dbeac, 0x096a3f42, 0x098f8796, 0x3f4827f0, 0x3f464626, 0x099bf44c, 0x09c13831, 0x3f409223, + 0x3f3ea697, 0x09cda368, 0x09f2e2c7, 0x3f38d552, 0x3f36e006, 0x09ff4c78, 0x0a24873a, 0x3f30f181, + 0x3f2ef276, 0x0a30ef5e, 0x0a56256c, 0x3f28e6b6, 0x3f26ddec, 0x0a628bfa, 0x0a87bd3d, 0x3f20b4f5, + 0x3f1ea26e, 0x0a94222f, 0x0ab94e8f, 0x3f185c43, 0x3f164001, 0x0ac5b1dc, 0x0aead944, 0x3f0fdca5, + 0x3f0db6a9, 0x0af73ae5, 0x0b1c5d3d, 0x3f073621, 0x3f05066d, 0x0b28bd2a, 0x0b4dda5c, 0x3efe68bc, + 0x3efc2f50, 0x0b5a388d, 0x0b7f5081, 0x3ef5747b, 0x3ef3315a, 0x0b8bacf0, 0x0bb0bf8f, 0x3eec5965, + 0x3eea0c8e, 0x0bbd1a33, 0x0be22766, 0x3ee3177e, 0x3ee0c0f4, 0x0bee8038, 0x0c1387e9, 0x3ed9aecc, + 0x3ed74e91, 0x0c1fdee1, 0x0c44e0f9, 0x3ed01f55, 0x3ecdb56a, 0x0c513610, 0x0c763278, 0x3ec66920, + 0x3ec3f585, 0x0c8285a5, 0x0ca77c47, 0x3ebc8c31, 0x3eba0ee9, 0x0cb3cd84, 0x0cd8be47, 0x3eb2888f, + 0x3eb0019c, 0x0ce50d8c, 0x0d09f85b, 0x3ea85e41, 0x3ea5cda3, 0x0d1645a0, 0x0d3b2a64, 0x3e9e0d4c, + 0x3e9b7306, 0x0d4775a1, 0x0d6c5443, 0x3e9395b7, 0x3e90f1ca, 0x0d789d71, 0x0d9d75db, 0x3e88f788, + 0x3e8649f5, 0x0da9bcf2, 0x0dce8f0d, 0x3e7e32c6, 0x3e7b7b90, 0x0ddad406, 0x0dff9fba, 0x3e734778, + 0x3e70869f, 0x0e0be28e, 0x0e30a7c5, 0x3e6835a4, 0x3e656b2b, 0x0e3ce86b, 0x0e61a70f, 0x3e5cfd51, + 0x3e5a2939, 0x0e6de580, 0x0e929d7a, 0x3e519e86, 0x3e4ec0d1, 0x0e9ed9af, 0x0ec38ae8, 0x3e46194a, + 0x3e4331fa, 0x0ecfc4d9, 0x0ef46f3b, 0x3e3a6da4, 0x3e377cbb, 0x0f00a6df, 0x0f254a53, 0x3e2e9b9c, + 0x3e2ba11b, 0x0f317fa5, 0x0f561c15, 0x3e22a338, 0x3e1f9f21, 0x0f624f0c, 0x0f86e460, 0x3e168480, + 0x3e1376d5, 0x0f9314f5, 0x0fb7a317, 0x3e0a3f7b, 0x3e07283f, 0x0fc3d143, 0x0fe8581d, 0x3dfdd432, + 0x3dfab365, 0x0ff483d7, 0x10190352, 0x3df142ab, 0x3dee1851, 0x10252c94, 0x1049a49a, 0x3de48aef, + 0x3de15708, 0x1055cb5b, 0x107a3bd5, 0x3dd7ad05, 0x3dd46f94, 0x1086600e, 0x10aac8e6, 0x3dcaa8f5, + 0x3dc761fc, 0x10b6ea90, 0x10db4baf, 0x3dbd7ec7, 0x3dba2e48, 0x10e76ac3, 0x110bc413, 0x3db02e84, + 0x3dacd481, 0x1117e088, 0x113c31f3, 0x3da2b834, 0x3d9f54af, 0x11484bc2, 0x116c9531, 0x3d951bde, + 0x3d91aed9, 0x1178ac53, 0x119cedaf, 0x3d87598c, 0x3d83e309, 0x11a9021d, 0x11cd3b50, 0x3d797145, + 0x3d75f147, 0x11d94d02, 0x11fd7df6, 0x3d6b6313, 0x3d67d99b, 0x12098ce5, 0x122db583, 0x3d5d2efe, + 0x3d599c0e, 0x1239c1a7, 0x125de1da, 0x3d4ed50f, 0x3d4b38aa, 0x1269eb2b, 0x128e02dc, 0x3d40554e, + 0x3d3caf76, 0x129a0954, 0x12be186c, 0x3d31afc5, 0x3d2e007c, 0x12ca1c03, 0x12ee226c, 0x3d22e47c, + 0x3d1f2bc5, 0x12fa231b, 0x131e20c0, 0x3d13f37e, 0x3d10315a, 0x132a1e7e, 0x134e1348, 0x3d04dcd2, + 0x3d011145, 0x135a0e0e, 0x137df9e7, 0x3cf5a082, 0x3cf1cb8e, 0x1389f1af, 0x13add481, 0x3ce63e98, + 0x3ce2603f, 0x13b9c943, 0x13dda2f7, 0x3cd6b71e, 0x3cd2cf62, 0x13e994ab, 0x140d652c, 0x3cc70a1c, + 0x3cc318ff, 0x141953cb, 0x143d1b02, 0x3cb7379c, 0x3cb33d22, 0x14490685, 0x146cc45c, 0x3ca73fa9, + 0x3ca33bd3, 0x1478acbc, 0x149c611d, 0x3c97224c, 0x3c93151d, 0x14a84652, 0x14cbf127, 0x3c86df8e, + 0x3c82c909, 0x14d7d32a, 0x14fb745e, 0x3c76777b, 0x3c7257a2, 0x15075327, 0x152aeaa3, 0x3c65ea1c, + 0x3c61c0f1, 0x1536c62b, 0x155a53d9, 0x3c55377b, 0x3c510501, 0x15662c18, 0x1589afe3, 0x3c445fa2, + 0x3c4023dd, 0x159584d3, 0x15b8fea4, 0x3c33629d, 0x3c2f1d8e, 0x15c4d03e, 0x15e83fff, 0x3c224075, + 0x3c1df21f, 0x15f40e3a, 0x161773d6, 0x3c10f935, 0x3c0ca19b, 0x16233eac, 0x16469a0d, 0x3bff8ce8, + 0x3bfb2c0c, 0x16526176, 0x1675b286, 0x3bedfb99, 0x3be9917e, 0x1681767c, 0x16a4bd25, 0x3bdc4552, + 0x3bd7d1fa, 0x16b07d9f, 0x16d3b9cc, 0x3bca6a1d, 0x3bc5ed8d, 0x16df76c3, 0x1702a85e, 0x3bb86a08, + 0x3bb3e440, 0x170e61cc, 0x173188be, 0x3ba6451b, 0x3ba1b620, 0x173d3e9b, 0x17605ad0, 0x3b93fb63, + 0x3b8f6337, 0x176c0d15, 0x178f1e76, 0x3b818ceb, 0x3b7ceb90, 0x179acd1c, 0x17bdd394, 0x3b6ef9be, + 0x3b6a4f38, 0x17c97e93, 0x17ec7a0d, 0x3b5c41e8, 0x3b578e39, 0x17f8215e, 0x181b11c4, 0x3b496574, + 0x3b44a8a0, 0x1826b561, 0x18499a9d, 0x3b36646e, 0x3b319e77, 0x18553a7d, 0x1878147a, 0x3b233ee1, + 0x3b1e6fca, 0x1883b097, 0x18a67f3f, 0x3b0ff4d9, 0x3b0b1ca6, 0x18b21791, 0x18d4dad0, 0x3afc8663, + 0x3af7a516, 0x18e06f50, 0x1903270f, 0x3ae8f38b, 0x3ae40926, 0x190eb7b7, 0x193163e1, 0x3ad53c5b, + 0x3ad048e3, 0x193cf0a9, 0x195f9128, 0x3ac160e1, 0x3abc6458, 0x196b1a09, 0x198daec8, 0x3aad6129, + 0x3aa85b92, 0x199933bb, 0x19bbbca6, 0x3a993d3e, 0x3a942e9d, 0x19c73da3, 0x19e9baa3, 0x3a84f52f, + 0x3a7fdd86, 0x19f537a4, 0x1a17a8a5, 0x3a708906, 0x3a6b6859, 0x1a2321a2, 0x1a45868e, 0x3a5bf8d1, + 0x3a56cf23, 0x1a50fb81, 0x1a735442, 0x3a47449c, 0x3a4211f0, 0x1a7ec524, 0x1aa111a6, 0x3a326c74, + 0x3a2d30cd, 0x1aac7e6f, 0x1acebe9d, 0x3a1d7066, 0x3a182bc8, 0x1ada2746, 0x1afc5b0a, 0x3a08507f, + 0x3a0302ed, 0x1b07bf8c, 0x1b29e6d2, 0x39f30ccc, 0x39edb649, 0x1b354727, 0x1b5761d8, 0x39dda55a, + 0x39d845e9, 0x1b62bdf8, 0x1b84cc01, 0x39c81a36, 0x39c2b1da, 0x1b9023e5, 0x1bb22530, 0x39b26b6d, + 0x39acfa2b, 0x1bbd78d2, 0x1bdf6d4a, 0x399c990d, 0x39971ee7, 0x1beabca1, 0x1c0ca432, 0x3986a324, + 0x3981201e, 0x1c17ef39, 0x1c39c9cd, 0x397089bf, 0x396afddc, 0x1c45107c, 0x1c66ddfe, 0x395a4ceb, + 0x3954b82e, 0x1c72204f, 0x1c93e0ab, 0x3943ecb6, 0x393e4f23, 0x1c9f1e96, 0x1cc0d1b6, 0x392d692f, + 0x3927c2c9, 0x1ccc0b35, 0x1cedb106, 0x3916c262, 0x3911132d, 0x1cf8e611, 0x1d1a7e7d, 0x38fff85e, + 0x38fa405e, 0x1d25af0d, 0x1d473a00, 0x38e90b31, 0x38e34a69, 0x1d52660f, 0x1d73e374, 0x38d1fae9, + 0x38cc315d, 0x1d7f0afb, 0x1da07abc, 0x38bac795, 0x38b4f547, 0x1dab9db5, 0x1dccffbf, 0x38a37142, + 0x389d9637, 0x1dd81e21, 0x1df9725f, 0x388bf7ff, 0x3886143b, 0x1e048c24, 0x1e25d282, 0x38745bdb, + 0x386e6f60, 0x1e30e7a4, 0x1e52200c, 0x385c9ce3, 0x3856a7b6, 0x1e5d3084, 0x1e7e5ae2, 0x3844bb28, + 0x383ebd4c, 0x1e8966a8, 0x1eaa82e9, 0x382cb6b7, 0x3826b030, 0x1eb589f7, 0x1ed69805, 0x38148f9f, + 0x380e8071, 0x1ee19a54, 0x1f029a1c, 0x37fc45ef, 0x37f62e1d, 0x1f0d97a5, 0x1f2e8911, 0x37e3d9b7, + 0x37ddb945, 0x1f3981ce, 0x1f5a64cb, 0x37cb4b04, 0x37c521f6, 0x1f6558b5, 0x1f862d2d, 0x37b299e7, + 0x37ac6841, 0x1f911c3d, 0x1fb1e21d, 0x3799c66f, 0x37938c34, 0x1fbccc4d, 0x1fdd8381, 0x3780d0aa, + 0x377a8ddf, 0x1fe868c8, 0x2009113c, 0x3767b8a9, 0x37616d51, 0x2013f196, 0x20348b35, 0x374e7e7b, + 0x37482a9a, 0x203f6699, 0x205ff14f, 0x3735222f, 0x372ec5c9, 0x206ac7b8, 0x208b4372, 0x371ba3d4, + 0x37153eee, 0x209614d9, 0x20b68181, 0x3702037c, 0x36fb9618, 0x20c14ddf, 0x20e1ab63, 0x36e84135, + 0x36e1cb58, 0x20ec72b1, 0x210cc0fc, 0x36ce5d10, 0x36c7debd, 0x21178334, 0x2137c232, 0x36b4571b, + 0x36add058, 0x21427f4d, 0x2162aeea, 0x369a2f69, 0x3693a038, 0x216d66e2, 0x218d870b, 0x367fe608, + 0x36794e6e, 0x219839d8, 0x21b84a79, 0x36657b08, 0x365edb09, 0x21c2f815, 0x21e2f91a, 0x364aee7b, + 0x3644461b, 0x21eda17f, 0x220d92d4, 0x36304070, 0x36298fb4, 0x221835fb, 0x2238178d, 0x361570f8, + 0x360eb7e3, 0x2242b56f, 0x22628729, 0x35fa8023, 0x35f3beba, 0x226d1fc1, 0x228ce191, 0x35df6e03, + 0x35d8a449, 0x229774d7, 0x22b726a8, 0x35c43aa7, 0x35bd68a1, 0x22c1b496, 0x22e15655, 0x35a8e621, + 0x35a20bd3, 0x22ebdee5, 0x230b707e, 0x358d7081, 0x35868def, 0x2315f3a8, 0x23357509, 0x3571d9d9, + 0x356aef08, 0x233ff2c8, 0x235f63dc, 0x35562239, 0x354f2f2c, 0x2369dc29, 0x23893cdd, 0x353a49b2, + 0x35334e6f, 0x2393afb2, 0x23b2fff3, 0x351e5056, 0x35174ce0, 0x23bd6d48, 0x23dcad03, 0x35023636, + 0x34fb2a92, 0x23e714d3, 0x240643f4, 0x34e5fb63, 0x34dee795, 0x2410a639, 0x242fc4ad, 0x34c99fef, + 0x34c283fb, 0x243a215f, 0x24592f13, 0x34ad23eb, 0x34a5ffd5, 0x2463862c, 0x2482830d, 0x34908768, + 0x34895b36, 0x248cd487, 0x24abc082, 0x3473ca79, 0x346c962f, 0x24b60c57, 0x24d4e757, 0x3456ed2f, + 0x344fb0d1, 0x24df2d81, 0x24fdf775, 0x3439ef9c, 0x3432ab2e, 0x250837ed, 0x2526f0c1, 0x341cd1d2, + 0x34158559, 0x25312b81, 0x254fd323, 0x33ff93e2, 0x33f83f62, 0x255a0823, 0x25789e80, 0x33e235df, + 0x33dad95e, 0x2582cdbc, 0x25a152c0, 0x33c4b7db, 0x33bd535c, 0x25ab7c30, 0x25c9efca, 0x33a719e8, + 0x339fad70, 0x25d41369, 0x25f27584, 0x33895c18, 0x3381e7ac, 0x25fc934b, 0x261ae3d6, 0x336b7e7e, + 0x33640223, 0x2624fbbf, 0x26433aa7, 0x334d812d, 0x3345fce6, 0x264d4cac, 0x266b79dd, 0x332f6435, + 0x3327d808, 0x267585f8, 0x2693a161, 0x331127ab, 0x3309939c, 0x269da78b, 0x26bbb119, 0x32f2cba1, + 0x32eb2fb5, 0x26c5b14c, 0x26e3a8ec, 0x32d45029, 0x32ccac64, 0x26eda322, 0x270b88c2, 0x32b5b557, + 0x32ae09be, 0x27157cf5, 0x27335082, 0x3296fb3d, 0x328f47d5, 0x273d3eac, 0x275b0014, 0x327821ee, + 0x327066bc, 0x2764e82f, 0x27829760, 0x3259297d, 0x32516686, 0x278c7965, 0x27aa164c, 0x323a11fe, + 0x32324746, 0x27b3f235, 0x27d17cc1, 0x321adb83, 0x3213090f, 0x27db5288, 0x27f8caa5, 0x31fb8620, + 0x31f3abf5, 0x28029a45, 0x281fffe2, 0x31dc11e8, 0x31d4300b, 0x2829c954, 0x28471c5e, 0x31bc7eee, + 0x31b49564, 0x2850df9d, 0x286e2002, 0x319ccd46, 0x3194dc14, 0x2877dd07, 0x28950ab6, 0x317cfd04, + 0x3175042e, 0x289ec17a, 0x28bbdc61, 0x315d0e3b, 0x31550dc6, 0x28c58cdf, 0x28e294eb, 0x313d00ff, + 0x3134f8f1, 0x28ec3f1e, 0x2909343e, 0x311cd564, 0x3114c5c0, 0x2912d81f, 0x292fba40, 0x30fc8b7d, + 0x30f47449, 0x293957c9, 0x295626da, 0x30dc235e, 0x30d404a0, 0x295fbe06, 0x297c79f5, 0x30bb9d1c, + 0x30b376d8, 0x29860abd, 0x29a2b378, 0x309af8ca, 0x3092cb05, 0x29ac3dd7, 0x29c8d34d, 0x307a367c, + 0x3072013c, 0x29d2573c, 0x29eed95b, 0x30595648, 0x30511991, 0x29f856d5, 0x2a14c58b, 0x30385840, + 0x30301418, 0x2a1e3c8a, 0x2a3a97c7, 0x30173c7a, 0x300ef0e5, 0x2a440844, 0x2a604ff5, 0x2ff6030a, + 0x2fedb00d, 0x2a69b9ec, 0x2a85ee00, 0x2fd4ac04, 0x2fcc51a5, 0x2a8f516b, 0x2aab71d0, 0x2fb3377c, + 0x2faad5c1, 0x2ab4cea9, 0x2ad0db4e, 0x2f91a589, 0x2f893c75, 0x2ada318e, 0x2af62a63, 0x2f6ff63d, + 0x2f6785d7, 0x2aff7a05, 0x2b1b5ef8, 0x2f4e29af, 0x2f45b1fb, 0x2b24a7f6, 0x2b4078f5, 0x2f2c3ff2, + 0x2f23c0f6, 0x2b49bb4a, 0x2b657844, 0x2f0a391d, 0x2f01b2de, 0x2b6eb3ea, 0x2b8a5cce, 0x2ee81543, + 0x2edf87c6, 0x2b9391c0, 0x2baf267d, 0x2ec5d479, 0x2ebd3fc4, 0x2bb854b4, 0x2bd3d53a, 0x2ea376d6, + 0x2e9adaee, 0x2bdcfcb0, 0x2bf868ed, 0x2e80fc6e, 0x2e785958, 0x2c01899e, 0x2c1ce181, 0x2e5e6556, + 0x2e55bb17, 0x2c25fb66, 0x2c413edf, 0x2e3bb1a4, 0x2e330042, 0x2c4a51f3, 0x2c6580f1, 0x2e18e16d, + 0x2e1028ed, 0x2c6e8d2e, 0x2c89a79f, 0x2df5f4c7, 0x2ded352f, 0x2c92ad01, 0x2cadb2d5, 0x2dd2ebc7, + 0x2dca251c, 0x2cb6b155, 0x2cd1a27b, 0x2dafc683, 0x2da6f8ca, 0x2cda9a14, 0x2cf5767c, 0x2d8c8510, + 0x2d83b04f, 0x2cfe6728, 0x2d192ec1, 0x2d692784, 0x2d604bc0, 0x2d22187a, 0x2d3ccb34, 0x2d45adf6 +}; + + +const int twidTab512[(8*6 + 32*6 + 128*6)/2] = { + 0x40000000, 0x40000000, 0x40000000, 0x3b20187d, + 0x3ec50c7c, 0x3536238e, 0x2d412d41, 0x3b20187d, + 0x187d3b20, 0x187d3b20, 0x3536238e, 0xf3843ec5, + 0x00004000, 0x2d412d41, 0xd2bf2d41, 0xe7833b20, + 0x238e3536, 0xc13b0c7c, 0xd2bf2d41, 0x187d3b20, + 0xc4e0e783, 0xc4e0187d, 0x0c7c3ec5, 0xdc72caca, + + 0x40000000, 0x40000000, 0x40000000, 0x3fb10645, + 0x3fec0323, 0x3f4e0964, 0x3ec50c7c, 0x3fb10645, + 0x3d3e1294, 0x3d3e1294, 0x3f4e0964, 0x39da1b5d, + 0x3b20187d, 0x3ec50c7c, 0x3536238e, 0x38711e2b, + 0x3e140f8c, 0x2f6b2afa, 0x3536238e, 0x3d3e1294, + 0x28993179, 0x31792899, 0x3c42158f, 0x20e736e5, + 0x2d412d41, 0x3b20187d, 0x187d3b20, 0x28993179, + 0x39da1b5d, 0x0f8c3e14, 0x238e3536, 0x38711e2b, + 0x06453fb1, 0x1e2b3871, 0x36e520e7, 0xfcdd3fec, + 0x187d3b20, 0x3536238e, 0xf3843ec5, 0x12943d3e, + 0x3367261f, 0xea713c42, 0x0c7c3ec5, 0x31792899, + 0xe1d53871, 0x06453fb1, 0x2f6b2afa, 0xd9e13367, + 0x00004000, 0x2d412d41, 0xd2bf2d41, 0xf9bb3fb1, + 0x2afa2f6b, 0xcc99261f, 0xf3843ec5, 0x28993179, + 0xc78f1e2b, 0xed6c3d3e, 0x261f3367, 0xc3be158f, + 0xe7833b20, 0x238e3536, 0xc13b0c7c, 0xe1d53871, + 0x20e736e5, 0xc0140323, 0xdc723536, 0x1e2b3871, + 0xc04ff9bb, 0xd7673179, 0x1b5d39da, 0xc1ecf074, + 0xd2bf2d41, 0x187d3b20, 0xc4e0e783, 0xce872899, + 0x158f3c42, 0xc91bdf19, 0xcaca238e, 0x12943d3e, + 0xce87d767, 0xc78f1e2b, 0x0f8c3e14, 0xd506d095, + 0xc4e0187d, 0x0c7c3ec5, 0xdc72caca, 0xc2c21294, + 0x09643f4e, 0xe4a3c626, 0xc13b0c7c, 0x06453fb1, + 0xed6cc2c2, 0xc04f0645, 0x03233fec, 0xf69cc0b2, + + 0x40000000, 0x40000000, 0x40000000, 0x3ffb0192, + 0x3ffe00c9, 0x3ff4025b, 0x3fec0323, 0x3ffb0192, + 0x3fd304b5, 0x3fd304b5, 0x3ff4025b, 0x3f9c070d, + 0x3fb10645, 0x3fec0323, 0x3f4e0964, 0x3f8407d5, + 0x3fe103ec, 0x3eeb0bb6, 0x3f4e0964, 0x3fd304b5, + 0x3e710e05, 0x3f0e0af1, 0x3fc3057d, 0x3de2104f, + 0x3ec50c7c, 0x3fb10645, 0x3d3e1294, 0x3e710e05, + 0x3f9c070d, 0x3c8414d1, 0x3e140f8c, 0x3f8407d5, + 0x3bb61708, 0x3dae1111, 0x3f6a089c, 0x3ad21937, + 0x3d3e1294, 0x3f4e0964, 0x39da1b5d, 0x3cc51413, + 0x3f2f0a2a, 0x38cf1d79, 0x3c42158f, 0x3f0e0af1, + 0x37af1f8b, 0x3bb61708, 0x3eeb0bb6, 0x367c2192, + 0x3b20187d, 0x3ec50c7c, 0x3536238e, 0x3a8219ef, + 0x3e9c0d41, 0x33de257d, 0x39da1b5d, 0x3e710e05, + 0x3274275f, 0x392a1cc6, 0x3e440ec9, 0x30f82934, + 0x38711e2b, 0x3e140f8c, 0x2f6b2afa, 0x37af1f8b, + 0x3de2104f, 0x2dce2cb2, 0x36e520e7, 0x3dae1111, + 0x2c212e5a, 0x3612223d, 0x3d7711d3, 0x2a652ff1, + 0x3536238e, 0x3d3e1294, 0x28993179, 0x345324da, + 0x3d021354, 0x26c032ee, 0x3367261f, 0x3cc51413, + 0x24da3453, 0x3274275f, 0x3c8414d1, 0x22e635a5, + 0x31792899, 0x3c42158f, 0x20e736e5, 0x307629cd, + 0x3bfd164c, 0x1edc3811, 0x2f6b2afa, 0x3bb61708, + 0x1cc6392a, 0x2e5a2c21, 0x3b6c17c3, 0x1aa63a2f, + 0x2d412d41, 0x3b20187d, 0x187d3b20, 0x2c212e5a, + 0x3ad21937, 0x164c3bfd, 0x2afa2f6b, 0x3a8219ef, + 0x14133cc5, 0x29cd3076, 0x3a2f1aa6, 0x11d33d77, + 0x28993179, 0x39da1b5d, 0x0f8c3e14, 0x275f3274, + 0x39831c12, 0x0d413e9c, 0x261f3367, 0x392a1cc6, + 0x0af13f0e, 0x24da3453, 0x38cf1d79, 0x089c3f6a, + 0x238e3536, 0x38711e2b, 0x06453fb1, 0x223d3612, + 0x38111edc, 0x03ec3fe1, 0x20e736e5, 0x37af1f8b, + 0x01923ffb, 0x1f8b37af, 0x374b2039, 0xff373ffe, + 0x1e2b3871, 0x36e520e7, 0xfcdd3fec, 0x1cc6392a, + 0x367c2192, 0xfa833fc3, 0x1b5d39da, 0x3612223d, + 0xf82b3f84, 0x19ef3a82, 0x35a522e6, 0xf5d63f2f, + 0x187d3b20, 0x3536238e, 0xf3843ec5, 0x17083bb6, + 0x34c62434, 0xf1373e44, 0x158f3c42, 0x345324da, + 0xeeef3dae, 0x14133cc5, 0x33de257d, 0xecac3d02, + 0x12943d3e, 0x3367261f, 0xea713c42, 0x11113dae, + 0x32ee26c0, 0xe83d3b6c, 0x0f8c3e14, 0x3274275f, + 0xe6113a82, 0x0e053e71, 0x31f727fd, 0xe3ee3983, + 0x0c7c3ec5, 0x31792899, 0xe1d53871, 0x0af13f0e, + 0x30f82934, 0xdfc7374b, 0x09643f4e, 0x307629cd, + 0xddc33612, 0x07d53f84, 0x2ff12a65, 0xdbcc34c6, + 0x06453fb1, 0x2f6b2afa, 0xd9e13367, 0x04b53fd3, + 0x2ee32b8e, 0xd80331f7, 0x03233fec, 0x2e5a2c21, + 0xd6333076, 0x01923ffb, 0x2dce2cb2, 0xd4722ee3, + 0x00004000, 0x2d412d41, 0xd2bf2d41, 0xfe6e3ffb, + 0x2cb22dce, 0xd11d2b8e, 0xfcdd3fec, 0x2c212e5a, + 0xcf8a29cd, 0xfb4b3fd3, 0x2b8e2ee3, 0xce0927fd, + 0xf9bb3fb1, 0x2afa2f6b, 0xcc99261f, 0xf82b3f84, + 0x2a652ff1, 0xcb3a2434, 0xf69c3f4e, 0x29cd3076, + 0xc9ee223d, 0xf50f3f0e, 0x293430f8, 0xc8b52039, + 0xf3843ec5, 0x28993179, 0xc78f1e2b, 0xf1fb3e71, + 0x27fd31f7, 0xc67d1c12, 0xf0743e14, 0x275f3274, + 0xc57e19ef, 0xeeef3dae, 0x26c032ee, 0xc49417c3, + 0xed6c3d3e, 0x261f3367, 0xc3be158f, 0xebed3cc5, + 0x257d33de, 0xc2fe1354, 0xea713c42, 0x24da3453, + 0xc2521111, 0xe8f83bb6, 0x243434c6, 0xc1bc0ec9, + 0xe7833b20, 0x238e3536, 0xc13b0c7c, 0xe6113a82, + 0x22e635a5, 0xc0d10a2a, 0xe4a339da, 0x223d3612, + 0xc07c07d5, 0xe33a392a, 0x2192367c, 0xc03d057d, + 0xe1d53871, 0x20e736e5, 0xc0140323, 0xe07537af, + 0x2039374b, 0xc00200c9, 0xdf1936e5, 0x1f8b37af, + 0xc005fe6e, 0xddc33612, 0x1edc3811, 0xc01ffc14, + 0xdc723536, 0x1e2b3871, 0xc04ff9bb, 0xdb263453, + 0x1d7938cf, 0xc096f764, 0xd9e13367, 0x1cc6392a, + 0xc0f2f50f, 0xd8a13274, 0x1c123983, 0xc164f2bf, + 0xd7673179, 0x1b5d39da, 0xc1ecf074, 0xd6333076, + 0x1aa63a2f, 0xc289ee2d, 0xd5062f6b, 0x19ef3a82, + 0xc33bebed, 0xd3df2e5a, 0x19373ad2, 0xc403e9b4, + 0xd2bf2d41, 0x187d3b20, 0xc4e0e783, 0xd1a62c21, + 0x17c33b6c, 0xc5d1e55a, 0xd0952afa, 0x17083bb6, + 0xc6d6e33a, 0xcf8a29cd, 0x164c3bfd, 0xc7efe124, + 0xce872899, 0x158f3c42, 0xc91bdf19, 0xcd8c275f, + 0x14d13c84, 0xca5bdd1a, 0xcc99261f, 0x14133cc5, + 0xcbaddb26, 0xcbad24da, 0x13543d02, 0xcd12d940, + 0xcaca238e, 0x12943d3e, 0xce87d767, 0xc9ee223d, + 0x11d33d77, 0xd00fd59b, 0xc91b20e7, 0x11113dae, + 0xd1a6d3df, 0xc8511f8b, 0x104f3de2, 0xd34ed232, + 0xc78f1e2b, 0x0f8c3e14, 0xd506d095, 0xc6d61cc6, + 0x0ec93e44, 0xd6cccf08, 0xc6261b5d, 0x0e053e71, + 0xd8a1cd8c, 0xc57e19ef, 0x0d413e9c, 0xda83cc22, + 0xc4e0187d, 0x0c7c3ec5, 0xdc72caca, 0xc44a1708, + 0x0bb63eeb, 0xde6ec984, 0xc3be158f, 0x0af13f0e, + 0xe075c851, 0xc33b1413, 0x0a2a3f2f, 0xe287c731, + 0xc2c21294, 0x09643f4e, 0xe4a3c626, 0xc2521111, + 0x089c3f6a, 0xe6c9c52e, 0xc1ec0f8c, 0x07d53f84, + 0xe8f8c44a, 0xc18f0e05, 0x070d3f9c, 0xeb2fc37c, + 0xc13b0c7c, 0x06453fb1, 0xed6cc2c2, 0xc0f20af1, + 0x057d3fc3, 0xefb1c21e, 0xc0b20964, 0x04b53fd3, + 0xf1fbc18f, 0xc07c07d5, 0x03ec3fe1, 0xf44ac115, + 0xc04f0645, 0x03233fec, 0xf69cc0b2, 0xc02d04b5, + 0x025b3ff4, 0xf8f3c064, 0xc0140323, 0x01923ffb, + 0xfb4bc02d, 0xc0050192, 0x00c93ffe, 0xfda5c00c +}; + +const int twidTab64[(4*6 + 16*6)/2] = { + 0x40000000, 0x40000000, 0x40000000, 0x2d412d41, + 0x3b20187d, 0x187d3b20, 0x00004000, 0x2d412d41, + 0xd2bf2d41, 0xd2bf2d41, 0x187d3b20, 0xc4e0e783, + + 0x40000000, 0x40000000, 0x40000000, 0x3ec50c7c, + 0x3fb10645, 0x3d3e1294, 0x3b20187d, 0x3ec50c7c, + 0x3536238e, 0x3536238e, 0x3d3e1294, 0x28993179, + 0x2d412d41, 0x3b20187d, 0x187d3b20, 0x238e3536, + 0x38711e2b, 0x06453fb1, 0x187d3b20, 0x3536238e, + 0xf3843ec5, 0x0c7c3ec5, 0x31792899, 0xe1d53871, + 0x00004000, 0x2d412d41, 0xd2bf2d41, 0xf3843ec5, + 0x28993179, 0xc78f1e2b, 0xe7833b20, 0x238e3536, + 0xc13b0c7c, 0xdc723536, 0x1e2b3871, 0xc04ff9bb, + 0xd2bf2d41, 0x187d3b20, 0xc4e0e783, 0xcaca238e, + 0x12943d3e, 0xce87d767, 0xc4e0187d, 0x0c7c3ec5, + 0xdc72caca, 0xc13b0c7c, 0x06453fb1, 0xed6cc2c2 +}; + +#elif defined ARMV7Neon +/* + * Q29 for 128 and 1024 + * + * for (i = 0; i < num/4; i++) { + * angle = (i + 0.125) * M_PI / num; + * x = cos(angle) * (1 << 29); + * x = sin(angle) * (1 << 29); + * + * angle = (num/2 - 1 - i + 0.125) * M_PI / num; + * x = cos(angle) * (1 << 29); + * x = sin(angle) * (1 << 29); + * } + */ +const int cossintab[128 + 1024] = { + /* 128 */ + 0x1ffff621, 0x001921f9, 0x00afea69, 0x1ffe1c68, 0x1ffce09d, 0x00e22a7a, 0x0178dbaa, 0x1ff753bb, + 0x1ff4dc55, 0x01ab101c, 0x024192cf, 0x1feb9d25, 0x1fe7ea85, 0x0273b3e2, 0x0309f0e2, 0x1fdafa75, + 0x1fd60d2e, 0x033bf6dd, 0x03d1d700, 0x1fc56e3b, 0x1fbf470f, 0x0403ba2b, 0x04992653, 0x1faafbcb, + 0x1fa39bac, 0x04cadefe, 0x055fc022, 0x1f8ba738, 0x1f830f4a, 0x059146a1, 0x062585ca, 0x1f677557, + 0x1f5da6ed, 0x0656d27a, 0x06ea58cd, 0x1f3e6bbc, 0x1f33685a, 0x071b6415, 0x07ae1ad2, 0x1f1090bd, + 0x1f045a15, 0x07dedd20, 0x0870ada7, 0x1eddeb6a, 0x1ed0835f, 0x08a11f78, 0x0931f34d, 0x1ea68394, + 0x1e97ec36, 0x09620d27, 0x09f1cdf5, 0x1e6a61c5, 0x1e5a9d55, 0x0a21886e, 0x0ab02009, 0x1e298f44, + 0x1e18a030, 0x0adf73c6, 0x0b6ccc32, 0x1de4160f, 0x1dd1fef4, 0x0b9bb1e5, 0x0c27b555, 0x1d9a00de, + 0x1d86c484, 0x0c5625c3, 0x0ce0bea2, 0x1d4b5b1b, 0x1d36fc7c, 0x0d0eb2a2, 0x0d97cb8f, 0x1cf830e9, + 0x1ce2b328, 0x0dc53c0a, 0x0e4cbfe2, 0x1ca08f1a, 0x1c89f587, 0x0e79a5d7, 0x0eff7fb3, 0x1c448331, + 0x1c2cd149, 0x0f2bd437, 0x0fafef73, 0x1be41b61, 0x1bcb54cb, 0x0fdbabae, 0x105df3ec, 0x1b7f6687, + 0x1b658f15, 0x10891120, 0x11097249, 0x1b16742a, 0x1afb8fd9, 0x1133e9d0, 0x11b25017, 0x1aa9547a, + 0x1a8d676e, 0x11dc1b65, 0x1258734d, 0x1a38184a, 0x1a1b26d3, 0x12818bef, 0x12fbc24b, 0x19c2d111, + 0x19a4dfa4, 0x132421ec, 0x139c23e4, 0x194990e4, 0x192aa420, 0x13c3c44a, 0x14397f5b, 0x18cc6a75, + 0x18ac871f, 0x14605a69, 0x14d3bc6d, 0x184b7112, 0x182a9c14, 0x14f9cc26, 0x156ac352, 0x17c6b89d, + 0x17a4f708, 0x159001d6, 0x15fe7cbe, 0x173e558e, 0x171bac96, 0x1622e450, 0x168ed1eb, 0x16b25ced, + /* 1024 */ + 0x1fffffd9, 0x0003243f, 0x0015fdba, 0x1ffff872, 0x1ffff382, 0x001c4637, 0x002f1fa6, 0x1fffdd4d, + 0x1fffd36f, 0x0035681d, 0x00484175, 0x1fffae6c, 0x1fff9f9e, 0x004e89e3, 0x00616318, 0x1fff6bce, + 0x1fff5811, 0x0067ab77, 0x007a847e, 0x1fff1572, 0x1ffefcc6, 0x0080cccc, 0x0093a599, 0x1ffeab5b, + 0x1ffe8dbf, 0x0099edd2, 0x00acc658, 0x1ffe2d86, 0x1ffe0afc, 0x00b30e78, 0x00c5e6ad, 0x1ffd9bf6, + 0x1ffd747c, 0x00cc2eb0, 0x00df0688, 0x1ffcf6aa, 0x1ffcca41, 0x00e54e6a, 0x00f825da, 0x1ffc3da2, + 0x1ffc0c4b, 0x00fe6d97, 0x01114492, 0x1ffb70e0, 0x1ffb3a9a, 0x01178c27, 0x012a62a2, 0x1ffa9063, + 0x1ffa552e, 0x0130aa0a, 0x01437ffa, 0x1ff99c2c, 0x1ff95c09, 0x0149c731, 0x015c9c8a, 0x1ff8943c, + 0x1ff84f2b, 0x0162e38d, 0x0175b843, 0x1ff77893, 0x1ff72e94, 0x017bff0e, 0x018ed316, 0x1ff64932, + 0x1ff5fa46, 0x019519a5, 0x01a7ecf2, 0x1ff5061b, 0x1ff4b240, 0x01ae3341, 0x01c105c9, 0x1ff3af4c, + 0x1ff35684, 0x01c74bd5, 0x01da1d8c, 0x1ff244c8, 0x1ff1e713, 0x01e0634f, 0x01f33429, 0x1ff0c68f, + 0x1ff063ed, 0x01f979a1, 0x020c4993, 0x1fef34a3, 0x1feecd14, 0x02128ebb, 0x02255db9, 0x1fed8f03, + 0x1fed2287, 0x022ba28f, 0x023e708d, 0x1febd5b2, 0x1feb644a, 0x0244b50b, 0x025781fe, 0x1fea08b0, + 0x1fe9925c, 0x025dc621, 0x027091fd, 0x1fe827fe, 0x1fe7acbe, 0x0276d5c1, 0x0289a07b, 0x1fe6339d, + 0x1fe5b372, 0x028fe3dd, 0x02a2ad69, 0x1fe42b90, 0x1fe3a679, 0x02a8f063, 0x02bbb8b6, 0x1fe20fd6, + 0x1fe185d5, 0x02c1fb46, 0x02d4c253, 0x1fdfe071, 0x1fdf5186, 0x02db0475, 0x02edca32, 0x1fdd9d64, + 0x1fdd098e, 0x02f40be2, 0x0306d042, 0x1fdb46ae, 0x1fdaadee, 0x030d117c, 0x031fd474, 0x1fd8dc51, + 0x1fd83ea8, 0x03261534, 0x0338d6b8, 0x1fd65e4f, 0x1fd5bbbd, 0x033f16fb, 0x0351d700, 0x1fd3ccaa, + 0x1fd32530, 0x035816c1, 0x036ad53c, 0x1fd12763, 0x1fd07b00, 0x03711477, 0x0383d15c, 0x1fce6e7c, + 0x1fcdbd31, 0x038a100e, 0x039ccb51, 0x1fcba1f5, 0x1fcaebc3, 0x03a30975, 0x03b5c30b, 0x1fc8c1d2, + 0x1fc806b9, 0x03bc009f, 0x03ceb87c, 0x1fc5ce14, 0x1fc50e14, 0x03d4f57a, 0x03e7ab93, 0x1fc2c6bd, + 0x1fc201d7, 0x03ede7f9, 0x04009c42, 0x1fbfabcd, 0x1fbee202, 0x0406d80b, 0x04198a78, 0x1fbc7d49, + 0x1fbbae99, 0x041fc5a1, 0x04327628, 0x1fb93b31, 0x1fb8679c, 0x0438b0ac, 0x044b5f40, 0x1fb5e587, + 0x1fb50d0e, 0x0451991d, 0x046445b2, 0x1fb27c4e, 0x1fb19ef1, 0x046a7ee3, 0x047d296f, 0x1faeff87, + 0x1fae1d47, 0x048361f0, 0x04960a67, 0x1fab6f35, 0x1faa8813, 0x049c4235, 0x04aee88b, 0x1fa7cb5a, + 0x1fa6df56, 0x04b51fa1, 0x04c7c3cb, 0x1fa413f8, 0x1fa32313, 0x04cdfa26, 0x04e09c18, 0x1fa04912, + 0x1f9f534c, 0x04e6d1b4, 0x04f97163, 0x1f9c6aa9, 0x1f9b7003, 0x04ffa63c, 0x0512439d, 0x1f9878c1, + 0x1f97793b, 0x051877af, 0x052b12b6, 0x1f94735b, 0x1f936ef6, 0x053145fd, 0x0543de9e, 0x1f905a7a, + 0x1f8f5137, 0x054a1117, 0x055ca748, 0x1f8c2e21, 0x1f8b2000, 0x0562d8ee, 0x05756ca2, 0x1f87ee52, + 0x1f86db55, 0x057b9d73, 0x058e2e9f, 0x1f839b10, 0x1f828336, 0x05945e95, 0x05a6ed2e, 0x1f7f345e, + 0x1f7e17a8, 0x05ad1c47, 0x05bfa840, 0x1f7aba3e, 0x1f7998ad, 0x05c5d678, 0x05d85fc7, 0x1f762cb2, + 0x1f750647, 0x05de8d19, 0x05f113b3, 0x1f718bbf, 0x1f70607a, 0x05f7401c, 0x0609c3f5, 0x1f6cd766, + 0x1f6ba748, 0x060fef71, 0x0622707d, 0x1f680fab, 0x1f66dab5, 0x06289b08, 0x063b193c, 0x1f633490, + 0x1f61fac3, 0x064142d3, 0x0653be23, 0x1f5e4619, 0x1f5d0775, 0x0659e6c2, 0x066c5f24, 0x1f594448, + 0x1f5800ce, 0x067286c6, 0x0684fc2e, 0x1f542f21, 0x1f52e6d2, 0x068b22d0, 0x069d9532, 0x1f4f06a6, + 0x1f4db983, 0x06a3bad0, 0x06b62a22, 0x1f49cadc, 0x1f4878e5, 0x06bc4eb9, 0x06cebaee, 0x1f447bc4, + 0x1f4324fb, 0x06d4de79, 0x06e74786, 0x1f3f1963, 0x1f3dbdc8, 0x06ed6a03, 0x06ffcfdd, 0x1f39a3bc, + 0x1f384350, 0x0705f147, 0x071853e3, 0x1f341ad2, 0x1f32b595, 0x071e7436, 0x0730d388, 0x1f2e7ea9, + 0x1f2d149d, 0x0736f2c0, 0x07494ebd, 0x1f28cf43, 0x1f276069, 0x074f6cd7, 0x0761c574, 0x1f230ca5, + 0x1f2198fd, 0x0767e26c, 0x077a379d, 0x1f1d36d2, 0x1f1bbe5d, 0x07805370, 0x0792a52a, 0x1f174dce, + 0x1f15d08d, 0x0798bfd3, 0x07ab0e0a, 0x1f11519c, 0x1f0fcf91, 0x07b12786, 0x07c37230, 0x1f0b4240, + 0x1f09bb6b, 0x07c98a7a, 0x07dbd18c, 0x1f051fbe, 0x1f03941f, 0x07e1e8a1, 0x07f42c0e, 0x1efeea19, + 0x1efd59b3, 0x07fa41eb, 0x080c81a9, 0x1ef8a155, 0x1ef70c28, 0x0812964a, 0x0824d24d, 0x1ef24577, + 0x1ef0ab84, 0x082ae5ad, 0x083d1dea, 0x1eebd682, 0x1eea37ca, 0x08433007, 0x08556473, 0x1ee5547a, + 0x1ee3b0fe, 0x085b7548, 0x086da5d8, 0x1edebf64, 0x1edd1724, 0x0873b562, 0x0885e209, 0x1ed81742, + 0x1ed66a41, 0x088bf044, 0x089e18f9, 0x1ed15c1a, 0x1ecfaa57, 0x08a425e1, 0x08b64a98, 0x1eca8def, + 0x1ec8d76c, 0x08bc562a, 0x08ce76d8, 0x1ec3acc6, 0x1ec1f184, 0x08d4810f, 0x08e69da8, 0x1ebcb8a3, + 0x1ebaf8a3, 0x08eca681, 0x08febefb, 0x1eb5b18a, 0x1eb3eccd, 0x0904c673, 0x0916dac2, 0x1eae977f, + 0x1eacce07, 0x091ce0d4, 0x092ef0ed, 0x1ea76a87, 0x1ea59c55, 0x0934f596, 0x0947016e, 0x1ea02aa7, + 0x1e9e57bb, 0x094d04aa, 0x095f0c36, 0x1e98d7e2, 0x1e97003e, 0x09650e01, 0x09771136, 0x1e91723e, + 0x1e8f95e3, 0x097d118d, 0x098f1060, 0x1e89f9bf, 0x1e8818ad, 0x09950f3f, 0x09a709a4, 0x1e826e69, + 0x1e8088a2, 0x09ad0707, 0x09befcf4, 0x1e7ad041, 0x1e78e5c7, 0x09c4f8d8, 0x09d6ea40, 0x1e731f4c, + 0x1e71301f, 0x09dce4a1, 0x09eed17b, 0x1e6b5b8f, 0x1e6967b1, 0x09f4ca56, 0x0a06b296, 0x1e63850e, + 0x1e618c80, 0x0a0ca9e6, 0x0a1e8d81, 0x1e5b9bce, 0x1e599e91, 0x0a248343, 0x0a36622e, 0x1e539fd4, + 0x1e519dea, 0x0a3c565e, 0x0a4e308f, 0x1e4b9126, 0x1e498a8e, 0x0a542329, 0x0a65f894, 0x1e436fc7, + 0x1e416485, 0x0a6be995, 0x0a7dba2f, 0x1e3b3bbd, 0x1e392bd1, 0x0a83a993, 0x0a957551, 0x1e32f50e, + 0x1e30e079, 0x0a9b6315, 0x0aad29ec, 0x1e2a9bbd, 0x1e288281, 0x0ab3160c, 0x0ac4d7f1, 0x1e222fd1, + 0x1e2011ee, 0x0acac26a, 0x0adc7f52, 0x1e19b14f, 0x1e178ec7, 0x0ae2681f, 0x0af41fff, 0x1e11203b, + 0x1e0ef910, 0x0afa071d, 0x0b0bb9eb, 0x1e087c9b, 0x1e0650ce, 0x0b119f56, 0x0b234d07, 0x1dffc674, + 0x1dfd9606, 0x0b2930bb, 0x0b3ad943, 0x1df6fdcc, 0x1df4c8bf, 0x0b40bb3e, 0x0b525e92, 0x1dee22a9, + 0x1debe8fd, 0x0b583ecf, 0x0b69dce6, 0x1de5350f, 0x1de2f6c6, 0x0b6fbb62, 0x0b81542f, 0x1ddc3504, + 0x1dd9f220, 0x0b8730e6, 0x0b98c45f, 0x1dd3228e, 0x1dd0db10, 0x0b9e9f4d, 0x0bb02d68, 0x1dc9fdb2, + 0x1dc7b19b, 0x0bb6068a, 0x0bc78f3b, 0x1dc0c676, 0x1dbe75c8, 0x0bcd668e, 0x0bdee9ca, 0x1db77cdf, + 0x1db5279c, 0x0be4bf4a, 0x0bf63d07, 0x1dae20f4, 0x1dabc71d, 0x0bfc10af, 0x0c0d88e2, 0x1da4b2ba, + 0x1da25450, 0x0c135ab0, 0x0c24cd4e, 0x1d9b3237, 0x1d98cf3b, 0x0c2a9d3e, 0x0c3c0a3d, 0x1d919f70, + 0x1d8f37e5, 0x0c41d84b, 0x0c533fa0, 0x1d87fa6d, 0x1d858e53, 0x0c590bc9, 0x0c6a6d68, 0x1d7e4332, + 0x1d7bd28b, 0x0c7037a8, 0x0c819388, 0x1d7479c5, 0x1d720493, 0x0c875bdb, 0x0c98b1f0, 0x1d6a9e2e, + 0x1d682472, 0x0c9e7854, 0x0cafc894, 0x1d60b070, 0x1d5e322c, 0x0cb58d04, 0x0cc6d764, 0x1d56b094, + 0x1d542dc9, 0x0ccc99de, 0x0cddde53, 0x1d4c9e9f, 0x1d4a174f, 0x0ce39ed2, 0x0cf4dd52, 0x1d427a97, + 0x1d3feec3, 0x0cfa9bd2, 0x0d0bd452, 0x1d384483, 0x1d35b42d, 0x0d1190d1, 0x0d22c347, 0x1d2dfc68, + 0x1d2b6791, 0x0d287dc1, 0x0d39aa21, 0x1d23a24e, 0x1d2108f8, 0x0d3f6292, 0x0d5088d3, 0x1d19363a, + 0x1d169867, 0x0d563f38, 0x0d675f4e, 0x1d0eb833, 0x1d0c15e4, 0x0d6d13a3, 0x0d7e2d85, 0x1d04283f, + 0x1d018176, 0x0d83dfc6, 0x0d94f369, 0x1cf98666, 0x1cf6db24, 0x0d9aa393, 0x0dabb0ec, 0x1ceed2ad, + 0x1cec22f4, 0x0db15efc, 0x0dc26600, 0x1ce40d1b, 0x1ce158ed, 0x0dc811f3, 0x0dd91298, 0x1cd935b7, + 0x1cd67d15, 0x0ddebc69, 0x0defb6a5, 0x1cce4c87, 0x1ccb8f74, 0x0df55e51, 0x0e065219, 0x1cc35192, + 0x1cc0900f, 0x0e0bf79c, 0x0e1ce4e6, 0x1cb844df, 0x1cb57eee, 0x0e22883e, 0x0e336eff, 0x1cad2675, + 0x1caa5c17, 0x0e391027, 0x0e49f055, 0x1ca1f65b, 0x1c9f2792, 0x0e4f8f4b, 0x0e6068db, 0x1c96b497, + 0x1c93e165, 0x0e66059a, 0x0e76d883, 0x1c8b6131, 0x1c888997, 0x0e7c7308, 0x0e8d3f3e, 0x1c7ffc2f, + 0x1c7d202f, 0x0e92d787, 0x0ea39d00, 0x1c748599, 0x1c71a535, 0x0ea93308, 0x0eb9f1ba, 0x1c68fd75, + 0x1c6618ae, 0x0ebf857d, 0x0ed03d5e, 0x1c5d63ca, 0x1c5a7aa4, 0x0ed5ceda, 0x0ee67fdf, 0x1c51b8a1, + 0x1c4ecb1c, 0x0eec0f10, 0x0efcb92f, 0x1c45fc00, 0x1c430a1d, 0x0f024612, 0x0f12e941, 0x1c3a2ded, + 0x1c3737b0, 0x0f1873d2, 0x0f291006, 0x1c2e4e72, 0x1c2b53db, 0x0f2e9842, 0x0f3f2d71, 0x1c225d94, + 0x1c1f5ea6, 0x0f44b354, 0x0f554175, 0x1c165b5b, 0x1c135818, 0x0f5ac4fc, 0x0f6b4c03, 0x1c0a47cf, + 0x1c074038, 0x0f70cd2a, 0x0f814d0e, 0x1bfe22f8, 0x1bfb170f, 0x0f86cbd3, 0x0f974489, 0x1bf1ecdb, + 0x1beedca2, 0x0f9cc0e7, 0x0fad3265, 0x1be5a582, 0x1be290fb, 0x0fb2ac5a, 0x0fc31697, 0x1bd94cf4, + 0x1bd63421, 0x0fc88e1e, 0x0fd8f10f, 0x1bcce337, 0x1bc9c61a, 0x0fde6626, 0x0feec1c0, 0x1bc06855, + 0x1bbd46f0, 0x0ff43464, 0x1004889e, 0x1bb3dc55, 0x1bb0b6a9, 0x1009f8cb, 0x101a459a, 0x1ba73f3d, + 0x1ba4154d, 0x101fb34d, 0x102ff8a8, 0x1b9a9117, 0x1b9762e4, 0x103563dc, 0x1045a1b9, 0x1b8dd1ea, + 0x1b8a9f77, 0x104b0a6c, 0x105b40c1, 0x1b8101be, 0x1b7dcb0c, 0x1060a6ef, 0x1070d5b1, 0x1b74209b, + 0x1b70e5ac, 0x10763958, 0x1086607e, 0x1b672e88, 0x1b63ef5f, 0x108bc19a, 0x109be119, 0x1b5a2b8e, + 0x1b56e82c, 0x10a13fa6, 0x10b15775, 0x1b4d17b4, 0x1b49d01c, 0x10b6b371, 0x10c6c385, 0x1b3ff304, + 0x1b3ca737, 0x10cc1cec, 0x10dc253c, 0x1b32bd84, 0x1b2f6d85, 0x10e17c0b, 0x10f17c8d, 0x1b25773d, + 0x1b22230e, 0x10f6d0c0, 0x1106c96a, 0x1b182038, 0x1b14c7da, 0x110c1afe, 0x111c0bc6, 0x1b0ab87c, + 0x1b075bf1, 0x11215ab8, 0x11314395, 0x1afd4012, 0x1af9df5d, 0x11368fe1, 0x114670c8, 0x1aefb702, + 0x1aec5225, 0x114bba6b, 0x115b9354, 0x1ae21d54, 0x1adeb451, 0x1160da4b, 0x1170ab2a, 0x1ad47311, + 0x1ad105e9, 0x1175ef72, 0x1185b83f, 0x1ac6b841, 0x1ac346f8, 0x118af9d4, 0x119aba84, 0x1ab8ecec, + 0x1ab57784, 0x119ff964, 0x11afb1ee, 0x1aab111c, 0x1aa79796, 0x11b4ee14, 0x11c49e6f, 0x1a9d24d9, + 0x1a99a737, 0x11c9d7d9, 0x11d97ff9, 0x1a8f282b, 0x1a8ba670, 0x11deb6a4, 0x11ee5682, 0x1a811b1b, + 0x1a7d9549, 0x11f38a6a, 0x120321fa, 0x1a72fdb2, 0x1a6f73ca, 0x1208531c, 0x1217e256, 0x1a64cff8, + 0x1a6141fd, 0x121d10af, 0x122c9789, 0x1a5691f5, 0x1a52ffeb, 0x1231c316, 0x12414186, 0x1a4843b4, + 0x1a44ad9b, 0x12466a44, 0x1255e041, 0x1a39e53d, 0x1a364b17, 0x125b062b, 0x126a73ac, 0x1a2b7698, + 0x1a27d868, 0x126f96c1, 0x127efbbb, 0x1a1cf7ce, 0x1a195597, 0x12841bf6, 0x12937861, 0x1a0e68e9, + 0x1a0ac2ac, 0x129895c0, 0x12a7e991, 0x19ffc9f1, 0x19fc1fb1, 0x12ad0412, 0x12bc4f40, 0x19f11af0, + 0x19ed6caf, 0x12c166de, 0x12d0a960, 0x19e25bee, 0x19dea9ae, 0x12d5be18, 0x12e4f7e5, 0x19d38cf4, + 0x19cfd6b8, 0x12ea09b4, 0x12f93ac2, 0x19c4ae0c, 0x19c0f3d6, 0x12fe49a6, 0x130d71eb, 0x19b5bf3f, + 0x19b20111, 0x13127de0, 0x13219d53, 0x19a6c096, 0x19a2fe73, 0x1326a656, 0x1335bcef, 0x1997b21b, + 0x1993ec04, 0x133ac2fc, 0x1349d0b0, 0x198893d6, 0x1984c9ce, 0x134ed3c5, 0x135dd88c, 0x197965d0, + 0x197597da, 0x1362d8a6, 0x1371d476, 0x196a2815, 0x19665632, 0x1376d191, 0x1385c461, 0x195adaab, + 0x195704df, 0x138abe7b, 0x1399a841, 0x194b7d9e, 0x1947a3eb, 0x139e9f56, 0x13ad800a, 0x193c10f7, + 0x1938335e, 0x13b27417, 0x13c14bb0, 0x192c94bf, 0x1928b343, 0x13c63cb2, 0x13d50b26, 0x191d08ff, + 0x191923a3, 0x13d9f91b, 0x13e8be60, 0x190d6dc1, 0x19098488, 0x13eda944, 0x13fc6553, 0x18fdc310, + 0x18f9d5fa, 0x14014d23, 0x140ffff1, 0x18ee08f4, 0x18ea1805, 0x1414e4aa, 0x14238e2f, 0x18de3f77, + 0x18da4ab2, 0x14286fce, 0x14371001, 0x18ce66a3, 0x18ca6e0a, 0x143bee83, 0x144a855b, 0x18be7e82, + 0x18ba8217, 0x144f60bd, 0x145dee30, 0x18ae871e, 0x18aa86e3, 0x1462c670, 0x14714a76, 0x189e8080, + 0x189a7c78, 0x14761f8f, 0x14849a1f, 0x188e6ab2, 0x188a62e0, 0x14896c0f, 0x1497dd20, 0x187e45be, + 0x187a3a25, 0x149cabe4, 0x14ab136d, 0x186e11af, 0x186a0250, 0x14afdf03, 0x14be3cfa, 0x185dce8e, + 0x1859bb6c, 0x14c3055e, 0x14d159bc, 0x184d7c65, 0x18496583, 0x14d61eeb, 0x14e469a6, 0x183d1b3e, + 0x1839009e, 0x14e92b9e, 0x14f76cad, 0x182cab24, 0x18288cc8, 0x14fc2b6a, 0x150a62c6, 0x181c2c20, + 0x18180a0c, 0x150f1e45, 0x151d4be3, 0x180b9e3d, 0x18077873, 0x15220422, 0x153027fb, 0x17fb0185, + 0x17f6d807, 0x1534dcf6, 0x1542f700, 0x17ea5602, 0x17e628d3, 0x1547a8b5, 0x1555b8e8, 0x17d99bbe, + 0x17d56ae0, 0x155a6754, 0x15686da7, 0x17c8d2c4, 0x17c49e3b, 0x156d18c7, 0x157b1532, 0x17b7fb1f, + 0x17b3c2ec, 0x157fbd03, 0x158daf7c, 0x17a714d7, 0x17a2d8fe, 0x159253fb, 0x15a03c7a, 0x17961ff9, + 0x1791e07b, 0x15a4dda5, 0x15b2bc22, 0x17851c8e, 0x1780d96f, 0x15b759f5, 0x15c52e67, 0x17740aa1, + 0x176fc3e3, 0x15c9c8e0, 0x15d7933f, 0x1762ea3d, 0x175e9fe2, 0x15dc2a5a, 0x15e9ea9d, 0x1751bb6b, + 0x174d6d77, 0x15ee7e58, 0x15fc3477, 0x17407e37, 0x173c2cac, 0x1600c4cf, 0x160e70c1, 0x172f32ab, + 0x172add8c, 0x1612fdb3, 0x16209f70, 0x171dd8d2, 0x17198021, 0x162528fa, 0x1632c078, 0x170c70b7, + 0x17081477, 0x16374697, 0x1644d3d0, 0x16fafa64, 0x16f69a97, 0x16495680, 0x1656d96a, 0x16e975e4, + 0x16e5128e, 0x165b58aa, 0x1668d13e, 0x16d7e341, 0x16d37c65, 0x166d4d0a, 0x167abb3e, 0x16c64288, + 0x16c1d827, 0x167f3394, 0x168c9760, 0x16b493c2, 0x16b025e0, 0x16910c3d, 0x169e659a, 0x16a2d6fb +}; + +const int twidTab512[8*6 + 32*6 + 128*6] = { + 0x20000000, 0x00000000, 0x1d906bcf, 0x0c3ef153, 0x16a09e66, 0x16a09e66, 0x0c3ef153, 0x1d906bcf, + 0x20000000, 0x00000000, 0x1f6297d0, 0x063e2e0f, 0x1d906bcf, 0x0c3ef153, 0x1a9b6629, 0x11c73b3a, + 0x20000000, 0x00000000, 0x1a9b6629, 0x11c73b3a, 0x0c3ef153, 0x1d906bcf, 0xf9c1d1f1, 0x1f6297d0, + 0x00000000, 0x20000000, 0xf3c10ead, 0x1d906bcf, 0xe95f619a, 0x16a09e66, 0xe26f9431, 0x0c3ef153, + 0x16a09e66, 0x16a09e66, 0x11c73b3a, 0x1a9b6629, 0x0c3ef153, 0x1d906bcf, 0x063e2e0f, 0x1f6297d0, + 0xe95f619a, 0x16a09e66, 0xe09d6830, 0x063e2e0f, 0xe26f9431, 0xf3c10ead, 0xee38c4c6, 0xe56499d7, + + 0x20000000, 0x00000000, 0x1fd88da4, 0x0322f4d8, 0x1f6297d0, 0x063e2e0f, 0x1e9f4157, 0x094a0317, + 0x20000000, 0x00000000, 0x1ff621e3, 0x0191f65f, 0x1fd88da4, 0x0322f4d8, 0x1fa7557f, 0x04b2041c, + 0x20000000, 0x00000000, 0x1fa7557f, 0x04b2041c, 0x1e9f4157, 0x094a0317, 0x1ced7af4, 0x0dae8805, + 0x1d906bcf, 0x0c3ef153, 0x1c38b2f2, 0x0f15ae9c, 0x1a9b6629, 0x11c73b3a, 0x18bc806b, 0x144cf325, + 0x1f6297d0, 0x063e2e0f, 0x1f0a7efc, 0x07c67e5f, 0x1e9f4157, 0x094a0317, 0x1e212105, 0x0ac7cd3b, + 0x1a9b6629, 0x11c73b3a, 0x17b5df22, 0x157d6935, 0x144cf325, 0x18bc806b, 0x10738799, 0x1b728345, + 0x16a09e66, 0x16a09e66, 0x144cf325, 0x18bc806b, 0x11c73b3a, 0x1a9b6629, 0x0f15ae9c, 0x1c38b2f2, + 0x1d906bcf, 0x0c3ef153, 0x1ced7af4, 0x0dae8805, 0x1c38b2f2, 0x0f15ae9c, 0x1b728345, 0x10738799, + 0x0c3ef153, 0x1d906bcf, 0x07c67e5f, 0x1f0a7efc, 0x0322f4d8, 0x1fd88da4, 0xfe6e09a1, 0x1ff621e3, + 0x0c3ef153, 0x1d906bcf, 0x094a0317, 0x1e9f4157, 0x063e2e0f, 0x1f6297d0, 0x0322f4d8, 0x1fd88da4, + 0x1a9b6629, 0x11c73b3a, 0x19b3e048, 0x130ff7fd, 0x18bc806b, 0x144cf325, 0x17b5df22, 0x157d6935, + 0xf9c1d1f1, 0x1f6297d0, 0xf53832c5, 0x1e212105, 0xf0ea5164, 0x1c38b2f2, 0xecf00803, 0x19b3e048, + 0x00000000, 0x20000000, 0xfcdd0b28, 0x1fd88da4, 0xf9c1d1f1, 0x1f6297d0, 0xf6b5fce9, 0x1e9f4157, + 0x16a09e66, 0x16a09e66, 0x157d6935, 0x17b5df22, 0x144cf325, 0x18bc806b, 0x130ff7fd, 0x19b3e048, + 0xe95f619a, 0x16a09e66, 0xe64c1fb8, 0x130ff7fd, 0xe3c74d0e, 0x0f15ae9c, 0xe1dedefb, 0x0ac7cd3b, + 0xf3c10ead, 0x1d906bcf, 0xf0ea5164, 0x1c38b2f2, 0xee38c4c6, 0x1a9b6629, 0xebb30cdb, 0x18bc806b, + 0x11c73b3a, 0x1a9b6629, 0x10738799, 0x1b728345, 0x0f15ae9c, 0x1c38b2f2, 0x0dae8805, 0x1ced7af4, + 0xe09d6830, 0x063e2e0f, 0xe009de1d, 0x0191f65f, 0xe027725c, 0xfcdd0b28, 0xe0f58104, 0xf83981a1, + 0xe95f619a, 0x16a09e66, 0xe7437f95, 0x144cf325, 0xe56499d7, 0x11c73b3a, 0xe3c74d0e, 0x0f15ae9c, + 0x0c3ef153, 0x1d906bcf, 0x0ac7cd3b, 0x1e212105, 0x094a0317, 0x1e9f4157, 0x07c67e5f, 0x1f0a7efc, + 0xe26f9431, 0xf3c10ead, 0xe48d7cbb, 0xef8c7867, 0xe7437f95, 0xebb30cdb, 0xea8296cb, 0xe84a20de, + 0xe26f9431, 0x0c3ef153, 0xe160bea9, 0x094a0317, 0xe09d6830, 0x063e2e0f, 0xe027725c, 0x0322f4d8, + 0x063e2e0f, 0x1f6297d0, 0x04b2041c, 0x1fa7557f, 0x0322f4d8, 0x1fd88da4, 0x0191f65f, 0x1ff621e3, + 0xee38c4c6, 0xe56499d7, 0xf25177fb, 0xe312850c, 0xf6b5fce9, 0xe160bea9, 0xfb4dfbe4, 0xe058aa81, + + 0x20000000, 0x00000000, 0x1ffd8861, 0x00c90ab0, 0x1ff621e3, 0x0191f65f, 0x1fe9cdad, 0x025aa412, + 0x20000000, 0x00000000, 0x1fff6217, 0x00648748, 0x1ffd8861, 0x00c90ab0, 0x1ffa72f0, 0x012d8657, + 0x20000000, 0x00000000, 0x1ffa72f0, 0x012d8657, 0x1fe9cdad, 0x025aa412, 0x1fce15fd, 0x0386f0b9, + 0x1fd88da4, 0x0322f4d8, 0x1fc26471, 0x03eac9cb, 0x1fa7557f, 0x04b2041c, 0x1f8764fa, 0x05788511, + 0x1ff621e3, 0x0191f65f, 0x1ff09566, 0x01f656e8, 0x1fe9cdad, 0x025aa412, 0x1fe1cafd, 0x02beda01, + 0x1fa7557f, 0x04b2041c, 0x1f7599a4, 0x05db7678, 0x1f38f3ac, 0x0702e09b, 0x1ef178a4, 0x0827dc07, + 0x1f6297d0, 0x063e2e0f, 0x1f38f3ac, 0x0702e09b, 0x1f0a7efc, 0x07c67e5f, 0x1ed740e7, 0x0888e931, + 0x1fd88da4, 0x0322f4d8, 0x1fce15fd, 0x0386f0b9, 0x1fc26471, 0x03eac9cb, 0x1fb57972, 0x044e7c34, + 0x1e9f4157, 0x094a0317, 0x1e426a4b, 0x0a68f121, 0x1ddb13b7, 0x0b844298, 0x1d696174, 0x0c9b9532, + 0x1e9f4157, 0x094a0317, 0x1e6288ec, 0x0a09ae4a, 0x1e212105, 0x0ac7cd3b, 0x1ddb13b7, 0x0b844298, + 0x1fa7557f, 0x04b2041c, 0x1f97f925, 0x05155dac, 0x1f8764fa, 0x05788511, 0x1f7599a4, 0x05db7678, + 0x1ced7af4, 0x0dae8805, 0x1c678b35, 0x0ebcbbae, 0x1bd7c0ac, 0x0fc5d26e, 0x1b3e4d3f, 0x10c9704d, + 0x1d906bcf, 0x0c3ef153, 0x1d4134d1, 0x0cf7bca2, 0x1ced7af4, 0x0dae8805, 0x1c954b21, 0x0e63374d, + 0x1f6297d0, 0x063e2e0f, 0x1f4e603b, 0x06a0a809, 0x1f38f3ac, 0x0702e09b, 0x1f2252f7, 0x0764d3f9, + 0x1a9b6629, 0x11c73b3a, 0x19ef43ef, 0x12bedb26, 0x193a224a, 0x13affa29, 0x187c4010, 0x149a449c, + 0x1c38b2f2, 0x0f15ae9c, 0x1bd7c0ac, 0x0fc5d26e, 0x1b728345, 0x10738799, 0x1b090a58, 0x111eb354, + 0x1f0a7efc, 0x07c67e5f, 0x1ef178a4, 0x0827dc07, 0x1ed740e7, 0x0888e931, 0x1ebbd8c9, 0x08e9a220, + 0x17b5df22, 0x157d6935, 0x16e74455, 0x16591926, 0x1610b755, 0x172d0838, 0x15328293, 0x17f8ece3, + 0x1a9b6629, 0x11c73b3a, 0x1a29a7a0, 0x126d054d, 0x19b3e048, 0x130ff7fd, 0x193a224a, 0x13affa29, + 0x1e9f4157, 0x094a0317, 0x1e817bab, 0x09aa0861, 0x1e6288ec, 0x0a09ae4a, 0x1e426a4b, 0x0a68f121, + 0x144cf325, 0x18bc806b, 0x136058b1, 0x19777ef5, 0x126d054d, 0x1a29a7a0, 0x11734d64, 0x1ad2bc9e, + 0x18bc806b, 0x144cf325, 0x183b0e0c, 0x14e6cabc, 0x17b5df22, 0x157d6935, 0x172d0838, 0x1610b755, + 0x1e212105, 0x0ac7cd3b, 0x1dfeae62, 0x0b263eef, 0x1ddb13b7, 0x0b844298, 0x1db65262, 0x0be1d499, + 0x10738799, 0x1b728345, 0x0f6e0ca9, 0x1c08c426, 0x0e63374d, 0x1c954b21, 0x0d536416, 0x1d17e774, + 0x16a09e66, 0x16a09e66, 0x1610b755, 0x172d0838, 0x157d6935, 0x17b5df22, 0x14e6cabc, 0x183b0e0c, + 0x1d906bcf, 0x0c3ef153, 0x1d696174, 0x0c9b9532, 0x1d4134d1, 0x0cf7bca2, 0x1d17e774, 0x0d536416, + 0x0c3ef153, 0x1d906bcf, 0x0b263eef, 0x1dfeae62, 0x0a09ae4a, 0x1e6288ec, 0x08e9a220, 0x1ebbd8c9, + 0x144cf325, 0x18bc806b, 0x13affa29, 0x193a224a, 0x130ff7fd, 0x19b3e048, 0x126d054d, 0x1a29a7a0, + 0x1ced7af4, 0x0dae8805, 0x1cc1f0f4, 0x0e0924ec, 0x1c954b21, 0x0e63374d, 0x1c678b35, 0x0ebcbbae, + 0x07c67e5f, 0x1f0a7efc, 0x06a0a809, 0x1f4e603b, 0x05788511, 0x1f8764fa, 0x044e7c34, 0x1fb57972, + 0x11c73b3a, 0x1a9b6629, 0x111eb354, 0x1b090a58, 0x10738799, 0x1b728345, 0x0fc5d26e, 0x1bd7c0ac, + 0x1c38b2f2, 0x0f15ae9c, 0x1c08c426, 0x0f6e0ca9, 0x1bd7c0ac, 0x0fc5d26e, 0x1ba5aa67, 0x101cfc87, + 0x0322f4d8, 0x1fd88da4, 0x01f656e8, 0x1ff09566, 0x00c90ab0, 0x1ffd8861, 0xff9b78b8, 0x1fff6217, + 0x0f15ae9c, 0x1c38b2f2, 0x0e63374d, 0x1c954b21, 0x0dae8805, 0x1ced7af4, 0x0cf7bca2, 0x1d4134d1, + 0x1b728345, 0x10738799, 0x1b3e4d3f, 0x10c9704d, 0x1b090a58, 0x111eb354, 0x1ad2bc9e, 0x11734d64, + 0xfe6e09a1, 0x1ff621e3, 0xfd4125ff, 0x1fe1cafd, 0xfc153635, 0x1fc26471, 0xfaeaa254, 0x1f97f925, + 0x0c3ef153, 0x1d906bcf, 0x0b844298, 0x1ddb13b7, 0x0ac7cd3b, 0x1e212105, 0x0a09ae4a, 0x1e6288ec, + 0x1a9b6629, 0x11c73b3a, 0x1a63091b, 0x121a7999, 0x1a29a7a0, 0x126d054d, 0x19ef43ef, 0x12bedb26, + 0xf9c1d1f1, 0x1f6297d0, 0xf89b2c07, 0x1f2252f7, 0xf77716cf, 0x1ed740e7, 0xf655f79f, 0x1e817bab, + 0x094a0317, 0x1e9f4157, 0x0888e931, 0x1ed740e7, 0x07c67e5f, 0x1f0a7efc, 0x0702e09b, 0x1f38f3ac, + 0x19b3e048, 0x130ff7fd, 0x19777ef5, 0x136058b1, 0x193a224a, 0x13affa29, 0x18fbcca4, 0x13fed953, + 0xf53832c5, 0x1e212105, 0xf41e2b67, 0x1db65262, 0xf308435e, 0x1d4134d1, 0xf1f6db14, 0x1cc1f0f4, + 0x063e2e0f, 0x1f6297d0, 0x05788511, 0x1f8764fa, 0x04b2041c, 0x1fa7557f, 0x03eac9cb, 0x1fc26471, + 0x18bc806b, 0x144cf325, 0x187c4010, 0x149a449c, 0x183b0e0c, 0x14e6cabc, 0x17f8ece3, 0x15328293, + 0xf0ea5164, 0x1c38b2f2, 0xefe30379, 0x1ba5aa67, 0xeee14cac, 0x1b090a58, 0xede58667, 0x1a63091b, + 0x0322f4d8, 0x1fd88da4, 0x025aa412, 0x1fe9cdad, 0x0191f65f, 0x1ff621e3, 0x00c90ab0, 0x1ffd8861, + 0x17b5df22, 0x157d6935, 0x1771e75f, 0x15c77bbe, 0x172d0838, 0x1610b755, 0x16e74455, 0x16591926, + 0xecf00803, 0x19b3e048, 0xec0126ad, 0x18fbcca4, 0xeb193544, 0x183b0e0c, 0xea388442, 0x1771e75f, + 0x00000000, 0x20000000, 0xff36f550, 0x1ffd8861, 0xfe6e09a1, 0x1ff621e3, 0xfda55bee, 0x1fe9cdad, + 0x16a09e66, 0x16a09e66, 0x16591926, 0x16e74455, 0x1610b755, 0x172d0838, 0x15c77bbe, 0x1771e75f, + 0xe95f619a, 0x16a09e66, 0xe88e18a1, 0x15c77bbe, 0xe7c4f1f4, 0x14e6cabc, 0xe704335c, 0x13fed953, + 0xfcdd0b28, 0x1fd88da4, 0xfc153635, 0x1fc26471, 0xfb4dfbe4, 0x1fa7557f, 0xfa877aef, 0x1f8764fa, + 0x157d6935, 0x17b5df22, 0x15328293, 0x17f8ece3, 0x14e6cabc, 0x183b0e0c, 0x149a449c, 0x187c4010, + 0xe64c1fb8, 0x130ff7fd, 0xe59cf6e5, 0x121a7999, 0xe4f6f5a8, 0x111eb354, 0xe45a5599, 0x101cfc87, + 0xf9c1d1f1, 0x1f6297d0, 0xf8fd1f65, 0x1f38f3ac, 0xf83981a1, 0x1f0a7efc, 0xf77716cf, 0x1ed740e7, + 0x144cf325, 0x18bc806b, 0x13fed953, 0x18fbcca4, 0x13affa29, 0x193a224a, 0x136058b1, 0x19777ef5, + 0xe3c74d0e, 0x0f15ae9c, 0xe33e0f0c, 0x0e0924ec, 0xe2becb2f, 0x0cf7bca2, 0xe249ad9e, 0x0be1d499, + 0xf6b5fce9, 0x1e9f4157, 0xf5f651b6, 0x1e6288ec, 0xf53832c5, 0x1e212105, 0xf47bbd68, 0x1ddb13b7, + 0x130ff7fd, 0x19b3e048, 0x12bedb26, 0x19ef43ef, 0x126d054d, 0x1a29a7a0, 0x121a7999, 0x1a63091b, + 0xe1dedefb, 0x0ac7cd3b, 0xe17e8455, 0x09aa0861, 0xe128bf19, 0x0888e931, 0xe0ddad09, 0x0764d3f9, + 0xf3c10ead, 0x1d906bcf, 0xf308435e, 0x1d4134d1, 0xf25177fb, 0x1ced7af4, 0xf19cc8b3, 0x1c954b21, + 0x11c73b3a, 0x1a9b6629, 0x11734d64, 0x1ad2bc9e, 0x111eb354, 0x1b090a58, 0x10c9704d, 0x1b3e4d3f, + 0xe09d6830, 0x063e2e0f, 0xe06806db, 0x05155dac, 0xe03d9b8f, 0x03eac9cb, 0xe01e3503, 0x02beda01, + 0xf0ea5164, 0x1c38b2f2, 0xf03a2d92, 0x1bd7c0ac, 0xef8c7867, 0x1b728345, 0xeee14cac, 0x1b090a58, + 0x10738799, 0x1b728345, 0x101cfc87, 0x1ba5aa67, 0x0fc5d26e, 0x1bd7c0ac, 0x0f6e0ca9, 0x1c08c426, + 0xe009de1d, 0x0191f65f, 0xe0009de9, 0x00648748, 0xe002779f, 0xff36f550, 0xe00f6a9a, 0xfe09a918, + 0xee38c4c6, 0x1a9b6629, 0xed92fab3, 0x1a29a7a0, 0xecf00803, 0x19b3e048, 0xec5005d7, 0x193a224a, + 0x0f15ae9c, 0x1c38b2f2, 0x0ebcbbae, 0x1c678b35, 0x0e63374d, 0x1c954b21, 0x0e0924ec, 0x1cc1f0f4, + 0xe027725c, 0xfcdd0b28, 0xe04a868e, 0xfbb183cc, 0xe0789b06, 0xfa877aef, 0xe0b19fc5, 0xf95f57f7, + 0xebb30cdb, 0x18bc806b, 0xeb193544, 0x183b0e0c, 0xea8296cb, 0x17b5df22, 0xe9ef48ab, 0x172d0838, + 0x0dae8805, 0x1ced7af4, 0x0d536416, 0x1d17e774, 0x0cf7bca2, 0x1d4134d1, 0x0c9b9532, 0x1d696174, + 0xe0f58104, 0xf83981a1, 0xe1442737, 0xf7165de0, 0xe19d7714, 0xf5f651b6, 0xe201519e, 0xf4d9c111, + 0xe95f619a, 0x16a09e66, 0xe8d2f7c8, 0x1610b755, 0xe84a20de, 0x157d6935, 0xe7c4f1f4, 0x14e6cabc, + 0x0c3ef153, 0x1d906bcf, 0x0be1d499, 0x1db65262, 0x0b844298, 0x1ddb13b7, 0x0b263eef, 0x1dfeae62, + 0xe26f9431, 0xf3c10ead, 0xe2e8188c, 0xf2ac9bea, 0xe36ab4df, 0xf19cc8b3, 0xe3f73bda, 0xf091f357, + 0xe7437f95, 0x144cf325, 0xe6c5ddb6, 0x13affa29, 0xe64c1fb8, 0x130ff7fd, 0xe5d65860, 0x126d054d, + 0x0ac7cd3b, 0x1e212105, 0x0a68f121, 0x1e426a4b, 0x0a09ae4a, 0x1e6288ec, 0x09aa0861, 0x1e817bab, + 0xe48d7cbb, 0xef8c7867, 0xe52d4362, 0xee8cb29c, 0xe5d65860, 0xed92fab3, 0xe688810b, 0xec9fa74f, + 0xe56499d7, 0x11c73b3a, 0xe4f6f5a8, 0x111eb354, 0xe48d7cbb, 0x10738799, 0xe4283f54, 0x0fc5d26e, + 0x094a0317, 0x1e9f4157, 0x08e9a220, 0x1ebbd8c9, 0x0888e931, 0x1ed740e7, 0x0827dc07, 0x1ef178a4, + 0xe7437f95, 0xebb30cdb, 0xe807131d, 0xeacd7d6d, 0xe8d2f7c8, 0xe9ef48ab, 0xe9a6e6da, 0xe918bbab, + 0xe3c74d0e, 0x0f15ae9c, 0xe36ab4df, 0x0e63374d, 0xe312850c, 0x0dae8805, 0xe2becb2f, 0x0cf7bca2, + 0x07c67e5f, 0x1f0a7efc, 0x0764d3f9, 0x1f2252f7, 0x0702e09b, 0x1f38f3ac, 0x06a0a809, 0x1f4e603b, + 0xea8296cb, 0xe84a20de, 0xeb65bb64, 0xe783bff0, 0xec5005d7, 0xe6c5ddb6, 0xed4124da, 0xe610bc11, + 0xe26f9431, 0x0c3ef153, 0xe224ec49, 0x0b844298, 0xe1dedefb, 0x0ac7cd3b, 0xe19d7714, 0x0a09ae4a, + 0x063e2e0f, 0x1f6297d0, 0x05db7678, 0x1f7599a4, 0x05788511, 0x1f8764fa, 0x05155dac, 0x1f97f925, + 0xee38c4c6, 0xe56499d7, 0xef368fb3, 0xe4c1b2c1, 0xf03a2d92, 0xe4283f54, 0xf1434452, 0xe39874cb, + 0xe160bea9, 0x094a0317, 0xe128bf19, 0x0888e931, 0xe0f58104, 0x07c67e5f, 0xe0c70c54, 0x0702e09b, + 0x04b2041c, 0x1fa7557f, 0x044e7c34, 0x1fb57972, 0x03eac9cb, 0x1fc26471, 0x0386f0b9, 0x1fce15fd, + 0xf25177fb, 0xe312850c, 0xf3646ace, 0xe2969e8c, 0xf47bbd68, 0xe224ec49, 0xf5970edf, 0xe1bd95b5, + 0xe09d6830, 0x063e2e0f, 0xe0789b06, 0x05788511, 0xe058aa81, 0x04b2041c, 0xe03d9b8f, 0x03eac9cb, + 0x0322f4d8, 0x1fd88da4, 0x02beda01, 0x1fe1cafd, 0x025aa412, 0x1fe9cdad, 0x01f656e8, 0x1ff09566, + 0xf6b5fce9, 0xe160bea9, 0xf7d823f9, 0xe10e875c, 0xf8fd1f65, 0xe0c70c54, 0xfa248988, 0xe08a665c, + 0xe027725c, 0x0322f4d8, 0xe0163253, 0x025aa412, 0xe009de1d, 0x0191f65f, 0xe002779f, 0x00c90ab0, + 0x0191f65f, 0x1ff621e3, 0x012d8657, 0x1ffa72f0, 0x00c90ab0, 0x1ffd8861, 0x00648748, 0x1fff6217, + 0xfb4dfbe4, 0xe058aa81, 0xfc790f47, 0xe031ea03, 0xfda55bee, 0xe0163253, 0xfed279a9, 0xe0058d10 +}; + +const int twidTab64[4*6 + 16*6] = { + 0x20000000, 0x00000000, 0x16a09e66, 0x16a09e66, 0x00000000, 0x20000000, 0xe95f619a, 0x16a09e66, + 0x20000000, 0x00000000, 0x1d906bcf, 0x0c3ef153, 0x16a09e66, 0x16a09e66, 0x0c3ef153, 0x1d906bcf, + 0x20000000, 0x00000000, 0x0c3ef153, 0x1d906bcf, 0xe95f619a, 0x16a09e66, 0xe26f9431, 0xf3c10ead, + + 0x20000000, 0x00000000, 0x1f6297d0, 0x063e2e0f, 0x1d906bcf, 0x0c3ef153, 0x1a9b6629, 0x11c73b3a, + 0x20000000, 0x00000000, 0x1fd88da4, 0x0322f4d8, 0x1f6297d0, 0x063e2e0f, 0x1e9f4157, 0x094a0317, + 0x20000000, 0x00000000, 0x1e9f4157, 0x094a0317, 0x1a9b6629, 0x11c73b3a, 0x144cf325, 0x18bc806b, + 0x16a09e66, 0x16a09e66, 0x11c73b3a, 0x1a9b6629, 0x0c3ef153, 0x1d906bcf, 0x063e2e0f, 0x1f6297d0, + 0x1d906bcf, 0x0c3ef153, 0x1c38b2f2, 0x0f15ae9c, 0x1a9b6629, 0x11c73b3a, 0x18bc806b, 0x144cf325, + 0x0c3ef153, 0x1d906bcf, 0x0322f4d8, 0x1fd88da4, 0xf9c1d1f1, 0x1f6297d0, 0xf0ea5164, 0x1c38b2f2, + 0x00000000, 0x20000000, 0xf9c1d1f1, 0x1f6297d0, 0xf3c10ead, 0x1d906bcf, 0xee38c4c6, 0x1a9b6629, + 0x16a09e66, 0x16a09e66, 0x144cf325, 0x18bc806b, 0x11c73b3a, 0x1a9b6629, 0x0f15ae9c, 0x1c38b2f2, + 0xe95f619a, 0x16a09e66, 0xe3c74d0e, 0x0f15ae9c, 0xe09d6830, 0x063e2e0f, 0xe027725c, 0xfcdd0b28, + 0xe95f619a, 0x16a09e66, 0xe56499d7, 0x11c73b3a, 0xe26f9431, 0x0c3ef153, 0xe09d6830, 0x063e2e0f, + 0x0c3ef153, 0x1d906bcf, 0x094a0317, 0x1e9f4157, 0x063e2e0f, 0x1f6297d0, 0x0322f4d8, 0x1fd88da4, + 0xe26f9431, 0xf3c10ead, 0xe7437f95, 0xebb30cdb, 0xee38c4c6, 0xe56499d7, 0xf6b5fce9, 0xe160bea9 +}; + +#else + +/* + * Q30 for 128 and 1024 + * + * for (i = 0; i < num/4; i++) { + * angle = (i + 0.125) * M_PI / num; + * x = cos(angle) * (1 << 30); + * x = sin(angle) * (1 << 30); + * + * angle = (num/2 - 1 - i + 0.125) * M_PI / num; + * x = cos(angle) * (1 << 30); + * x = sin(angle) * (1 << 30); + * } + */ +const int cossintab[128 + 1024] = { + /* 128 */ + 0x3fffec43, 0x003243f1, 0x015fd4d2, 0x3ffc38d1, 0x3ff9c13a, 0x01c454f5, 0x02f1b755, 0x3feea776, + 0x3fe9b8a9, 0x03562038, 0x0483259d, 0x3fd73a4a, 0x3fcfd50b, 0x04e767c5, 0x0613e1c5, 0x3fb5f4ea, + 0x3fac1a5b, 0x0677edbb, 0x07a3adff, 0x3f8adc77, 0x3f7e8e1e, 0x08077457, 0x09324ca7, 0x3f55f796, + 0x3f473759, 0x0995bdfd, 0x0abf8043, 0x3f174e70, 0x3f061e95, 0x0b228d42, 0x0c4b0b94, 0x3eceeaad, + 0x3ebb4ddb, 0x0cada4f5, 0x0dd4b19a, 0x3e7cd778, 0x3e66d0b4, 0x0e36c82a, 0x0f5c35a3, 0x3e212179, + 0x3e08b42a, 0x0fbdba40, 0x10e15b4e, 0x3dbbd6d4, 0x3da106bd, 0x11423ef0, 0x1263e699, 0x3d4d0728, + 0x3d2fd86c, 0x12c41a4f, 0x13e39be9, 0x3cd4c38b, 0x3cb53aaa, 0x144310dd, 0x15604013, 0x3c531e88, + 0x3c314060, 0x15bee78c, 0x16d99864, 0x3bc82c1f, 0x3ba3fde7, 0x173763c9, 0x184f6aab, 0x3b3401bb, + 0x3b0d8909, 0x18ac4b87, 0x19c17d44, 0x3a96b636, 0x3a6df8f8, 0x1a1d6544, 0x1b2f971e, 0x39f061d2, + 0x39c5664f, 0x1b8a7815, 0x1c997fc4, 0x39411e33, 0x3913eb0e, 0x1cf34baf, 0x1dfeff67, 0x38890663, + 0x3859a292, 0x1e57a86d, 0x1f5fdee6, 0x37c836c2, 0x3796a996, 0x1fb7575c, 0x20bbe7d8, 0x36fecd0e, + 0x36cb1e2a, 0x21122240, 0x2212e492, 0x362ce855, 0x35f71fb1, 0x2267d3a0, 0x2364a02e, 0x3552a8f4, + 0x351acedd, 0x23b836ca, 0x24b0e699, 0x34703095, 0x34364da6, 0x250317df, 0x25f78497, 0x3385a222, + 0x3349bf48, 0x264843d9, 0x273847c8, 0x329321c7, 0x32554840, 0x27878893, 0x2872feb6, 0x3198d4ea, + 0x31590e3e, 0x28c0b4d2, 0x29a778db, 0x3096e223, 0x30553828, 0x29f3984c, 0x2ad586a3, 0x2f8d713a, + 0x2f49ee0f, 0x2b2003ac, 0x2bfcf97c, 0x2e7cab1c, 0x2e37592c, 0x2c45c8a0, 0x2d1da3d5, 0x2d64b9da, + /* 1024 */ + 0x3fffffb1, 0x0006487f, 0x002bfb74, 0x3ffff0e3, 0x3fffe705, 0x00388c6e, 0x005e3f4c, 0x3fffba9b, + 0x3fffa6de, 0x006ad03b, 0x009082ea, 0x3fff5cd8, 0x3fff3f3c, 0x009d13c5, 0x00c2c62f, 0x3ffed79b, + 0x3ffeb021, 0x00cf56ef, 0x00f508fc, 0x3ffe2ae5, 0x3ffdf98c, 0x01019998, 0x01274b31, 0x3ffd56b5, + 0x3ffd1b7e, 0x0133dba3, 0x01598cb1, 0x3ffc5b0c, 0x3ffc15f7, 0x01661cf0, 0x018bcd5b, 0x3ffb37ec, + 0x3ffae8f9, 0x01985d60, 0x01be0d11, 0x3ff9ed53, 0x3ff99483, 0x01ca9cd4, 0x01f04bb4, 0x3ff87b44, + 0x3ff81896, 0x01fcdb2e, 0x02228924, 0x3ff6e1bf, 0x3ff67534, 0x022f184d, 0x0254c544, 0x3ff520c5, + 0x3ff4aa5d, 0x02615414, 0x0286fff3, 0x3ff33858, 0x3ff2b813, 0x02938e62, 0x02b93914, 0x3ff12878, + 0x3ff09e56, 0x02c5c71a, 0x02eb7086, 0x3feef126, 0x3fee5d28, 0x02f7fe1c, 0x031da62b, 0x3fec9265, + 0x3febf48b, 0x032a3349, 0x034fd9e5, 0x3fea0c35, 0x3fe96480, 0x035c6682, 0x03820b93, 0x3fe75e98, + 0x3fe6ad08, 0x038e97a9, 0x03b43b17, 0x3fe48990, 0x3fe3ce26, 0x03c0c69e, 0x03e66852, 0x3fe18d1f, + 0x3fe0c7da, 0x03f2f342, 0x04189326, 0x3fde6945, 0x3fdd9a27, 0x04251d77, 0x044abb73, 0x3fdb1e06, + 0x3fda450f, 0x0457451d, 0x047ce11a, 0x3fd7ab64, 0x3fd6c894, 0x04896a16, 0x04af03fc, 0x3fd4115f, + 0x3fd324b7, 0x04bb8c42, 0x04e123fa, 0x3fd04ffc, 0x3fcf597c, 0x04edab83, 0x051340f6, 0x3fcc673b, + 0x3fcb66e4, 0x051fc7b9, 0x05455ad1, 0x3fc8571f, 0x3fc74cf3, 0x0551e0c7, 0x0577716b, 0x3fc41fac, + 0x3fc30baa, 0x0583f68c, 0x05a984a6, 0x3fbfc0e3, 0x3fbea30c, 0x05b608eb, 0x05db9463, 0x3fbb3ac7, + 0x3fba131b, 0x05e817c3, 0x060da083, 0x3fb68d5b, 0x3fb55bdc, 0x061a22f7, 0x063fa8e7, 0x3fb1b8a2, + 0x3fb07d50, 0x064c2a67, 0x0671ad71, 0x3facbc9f, 0x3fab777b, 0x067e2df5, 0x06a3ae00, 0x3fa79954, + 0x3fa64a5f, 0x06b02d81, 0x06d5aa77, 0x3fa24ec6, 0x3fa0f600, 0x06e228ee, 0x0707a2b7, 0x3f9cdcf7, + 0x3f9b7a62, 0x0714201b, 0x073996a1, 0x3f9743eb, 0x3f95d787, 0x074612eb, 0x076b8616, 0x3f9183a5, + 0x3f900d72, 0x0778013d, 0x079d70f7, 0x3f8b9c28, 0x3f8a1c29, 0x07a9eaf5, 0x07cf5726, 0x3f858d79, + 0x3f8403ae, 0x07dbcff2, 0x08013883, 0x3f7f579b, 0x3f7dc405, 0x080db016, 0x083314f1, 0x3f78fa92, + 0x3f775d31, 0x083f8b43, 0x0864ec4f, 0x3f727661, 0x3f70cf38, 0x08716159, 0x0896be80, 0x3f6bcb0e, + 0x3f6a1a1c, 0x08a3323a, 0x08c88b65, 0x3f64f89b, 0x3f633de2, 0x08d4fdc6, 0x08fa52de, 0x3f5dff0e, + 0x3f5c3a8f, 0x0906c3e0, 0x092c14ce, 0x3f56de6a, 0x3f551026, 0x09388469, 0x095dd116, 0x3f4f96b4, + 0x3f4dbeac, 0x096a3f42, 0x098f8796, 0x3f4827f0, 0x3f464626, 0x099bf44c, 0x09c13831, 0x3f409223, + 0x3f3ea697, 0x09cda368, 0x09f2e2c7, 0x3f38d552, 0x3f36e006, 0x09ff4c78, 0x0a24873a, 0x3f30f181, + 0x3f2ef276, 0x0a30ef5e, 0x0a56256c, 0x3f28e6b6, 0x3f26ddec, 0x0a628bfa, 0x0a87bd3d, 0x3f20b4f5, + 0x3f1ea26e, 0x0a94222f, 0x0ab94e8f, 0x3f185c43, 0x3f164001, 0x0ac5b1dc, 0x0aead944, 0x3f0fdca5, + 0x3f0db6a9, 0x0af73ae5, 0x0b1c5d3d, 0x3f073621, 0x3f05066d, 0x0b28bd2a, 0x0b4dda5c, 0x3efe68bc, + 0x3efc2f50, 0x0b5a388d, 0x0b7f5081, 0x3ef5747b, 0x3ef3315a, 0x0b8bacf0, 0x0bb0bf8f, 0x3eec5965, + 0x3eea0c8e, 0x0bbd1a33, 0x0be22766, 0x3ee3177e, 0x3ee0c0f4, 0x0bee8038, 0x0c1387e9, 0x3ed9aecc, + 0x3ed74e91, 0x0c1fdee1, 0x0c44e0f9, 0x3ed01f55, 0x3ecdb56a, 0x0c513610, 0x0c763278, 0x3ec66920, + 0x3ec3f585, 0x0c8285a5, 0x0ca77c47, 0x3ebc8c31, 0x3eba0ee9, 0x0cb3cd84, 0x0cd8be47, 0x3eb2888f, + 0x3eb0019c, 0x0ce50d8c, 0x0d09f85b, 0x3ea85e41, 0x3ea5cda3, 0x0d1645a0, 0x0d3b2a64, 0x3e9e0d4c, + 0x3e9b7306, 0x0d4775a1, 0x0d6c5443, 0x3e9395b7, 0x3e90f1ca, 0x0d789d71, 0x0d9d75db, 0x3e88f788, + 0x3e8649f5, 0x0da9bcf2, 0x0dce8f0d, 0x3e7e32c6, 0x3e7b7b90, 0x0ddad406, 0x0dff9fba, 0x3e734778, + 0x3e70869f, 0x0e0be28e, 0x0e30a7c5, 0x3e6835a4, 0x3e656b2b, 0x0e3ce86b, 0x0e61a70f, 0x3e5cfd51, + 0x3e5a2939, 0x0e6de580, 0x0e929d7a, 0x3e519e86, 0x3e4ec0d1, 0x0e9ed9af, 0x0ec38ae8, 0x3e46194a, + 0x3e4331fa, 0x0ecfc4d9, 0x0ef46f3b, 0x3e3a6da4, 0x3e377cbb, 0x0f00a6df, 0x0f254a53, 0x3e2e9b9c, + 0x3e2ba11b, 0x0f317fa5, 0x0f561c15, 0x3e22a338, 0x3e1f9f21, 0x0f624f0c, 0x0f86e460, 0x3e168480, + 0x3e1376d5, 0x0f9314f5, 0x0fb7a317, 0x3e0a3f7b, 0x3e07283f, 0x0fc3d143, 0x0fe8581d, 0x3dfdd432, + 0x3dfab365, 0x0ff483d7, 0x10190352, 0x3df142ab, 0x3dee1851, 0x10252c94, 0x1049a49a, 0x3de48aef, + 0x3de15708, 0x1055cb5b, 0x107a3bd5, 0x3dd7ad05, 0x3dd46f94, 0x1086600e, 0x10aac8e6, 0x3dcaa8f5, + 0x3dc761fc, 0x10b6ea90, 0x10db4baf, 0x3dbd7ec7, 0x3dba2e48, 0x10e76ac3, 0x110bc413, 0x3db02e84, + 0x3dacd481, 0x1117e088, 0x113c31f3, 0x3da2b834, 0x3d9f54af, 0x11484bc2, 0x116c9531, 0x3d951bde, + 0x3d91aed9, 0x1178ac53, 0x119cedaf, 0x3d87598c, 0x3d83e309, 0x11a9021d, 0x11cd3b50, 0x3d797145, + 0x3d75f147, 0x11d94d02, 0x11fd7df6, 0x3d6b6313, 0x3d67d99b, 0x12098ce5, 0x122db583, 0x3d5d2efe, + 0x3d599c0e, 0x1239c1a7, 0x125de1da, 0x3d4ed50f, 0x3d4b38aa, 0x1269eb2b, 0x128e02dc, 0x3d40554e, + 0x3d3caf76, 0x129a0954, 0x12be186c, 0x3d31afc5, 0x3d2e007c, 0x12ca1c03, 0x12ee226c, 0x3d22e47c, + 0x3d1f2bc5, 0x12fa231b, 0x131e20c0, 0x3d13f37e, 0x3d10315a, 0x132a1e7e, 0x134e1348, 0x3d04dcd2, + 0x3d011145, 0x135a0e0e, 0x137df9e7, 0x3cf5a082, 0x3cf1cb8e, 0x1389f1af, 0x13add481, 0x3ce63e98, + 0x3ce2603f, 0x13b9c943, 0x13dda2f7, 0x3cd6b71e, 0x3cd2cf62, 0x13e994ab, 0x140d652c, 0x3cc70a1c, + 0x3cc318ff, 0x141953cb, 0x143d1b02, 0x3cb7379c, 0x3cb33d22, 0x14490685, 0x146cc45c, 0x3ca73fa9, + 0x3ca33bd3, 0x1478acbc, 0x149c611d, 0x3c97224c, 0x3c93151d, 0x14a84652, 0x14cbf127, 0x3c86df8e, + 0x3c82c909, 0x14d7d32a, 0x14fb745e, 0x3c76777b, 0x3c7257a2, 0x15075327, 0x152aeaa3, 0x3c65ea1c, + 0x3c61c0f1, 0x1536c62b, 0x155a53d9, 0x3c55377b, 0x3c510501, 0x15662c18, 0x1589afe3, 0x3c445fa2, + 0x3c4023dd, 0x159584d3, 0x15b8fea4, 0x3c33629d, 0x3c2f1d8e, 0x15c4d03e, 0x15e83fff, 0x3c224075, + 0x3c1df21f, 0x15f40e3a, 0x161773d6, 0x3c10f935, 0x3c0ca19b, 0x16233eac, 0x16469a0d, 0x3bff8ce8, + 0x3bfb2c0c, 0x16526176, 0x1675b286, 0x3bedfb99, 0x3be9917e, 0x1681767c, 0x16a4bd25, 0x3bdc4552, + 0x3bd7d1fa, 0x16b07d9f, 0x16d3b9cc, 0x3bca6a1d, 0x3bc5ed8d, 0x16df76c3, 0x1702a85e, 0x3bb86a08, + 0x3bb3e440, 0x170e61cc, 0x173188be, 0x3ba6451b, 0x3ba1b620, 0x173d3e9b, 0x17605ad0, 0x3b93fb63, + 0x3b8f6337, 0x176c0d15, 0x178f1e76, 0x3b818ceb, 0x3b7ceb90, 0x179acd1c, 0x17bdd394, 0x3b6ef9be, + 0x3b6a4f38, 0x17c97e93, 0x17ec7a0d, 0x3b5c41e8, 0x3b578e39, 0x17f8215e, 0x181b11c4, 0x3b496574, + 0x3b44a8a0, 0x1826b561, 0x18499a9d, 0x3b36646e, 0x3b319e77, 0x18553a7d, 0x1878147a, 0x3b233ee1, + 0x3b1e6fca, 0x1883b097, 0x18a67f3f, 0x3b0ff4d9, 0x3b0b1ca6, 0x18b21791, 0x18d4dad0, 0x3afc8663, + 0x3af7a516, 0x18e06f50, 0x1903270f, 0x3ae8f38b, 0x3ae40926, 0x190eb7b7, 0x193163e1, 0x3ad53c5b, + 0x3ad048e3, 0x193cf0a9, 0x195f9128, 0x3ac160e1, 0x3abc6458, 0x196b1a09, 0x198daec8, 0x3aad6129, + 0x3aa85b92, 0x199933bb, 0x19bbbca6, 0x3a993d3e, 0x3a942e9d, 0x19c73da3, 0x19e9baa3, 0x3a84f52f, + 0x3a7fdd86, 0x19f537a4, 0x1a17a8a5, 0x3a708906, 0x3a6b6859, 0x1a2321a2, 0x1a45868e, 0x3a5bf8d1, + 0x3a56cf23, 0x1a50fb81, 0x1a735442, 0x3a47449c, 0x3a4211f0, 0x1a7ec524, 0x1aa111a6, 0x3a326c74, + 0x3a2d30cd, 0x1aac7e6f, 0x1acebe9d, 0x3a1d7066, 0x3a182bc8, 0x1ada2746, 0x1afc5b0a, 0x3a08507f, + 0x3a0302ed, 0x1b07bf8c, 0x1b29e6d2, 0x39f30ccc, 0x39edb649, 0x1b354727, 0x1b5761d8, 0x39dda55a, + 0x39d845e9, 0x1b62bdf8, 0x1b84cc01, 0x39c81a36, 0x39c2b1da, 0x1b9023e5, 0x1bb22530, 0x39b26b6d, + 0x39acfa2b, 0x1bbd78d2, 0x1bdf6d4a, 0x399c990d, 0x39971ee7, 0x1beabca1, 0x1c0ca432, 0x3986a324, + 0x3981201e, 0x1c17ef39, 0x1c39c9cd, 0x397089bf, 0x396afddc, 0x1c45107c, 0x1c66ddfe, 0x395a4ceb, + 0x3954b82e, 0x1c72204f, 0x1c93e0ab, 0x3943ecb6, 0x393e4f23, 0x1c9f1e96, 0x1cc0d1b6, 0x392d692f, + 0x3927c2c9, 0x1ccc0b35, 0x1cedb106, 0x3916c262, 0x3911132d, 0x1cf8e611, 0x1d1a7e7d, 0x38fff85e, + 0x38fa405e, 0x1d25af0d, 0x1d473a00, 0x38e90b31, 0x38e34a69, 0x1d52660f, 0x1d73e374, 0x38d1fae9, + 0x38cc315d, 0x1d7f0afb, 0x1da07abc, 0x38bac795, 0x38b4f547, 0x1dab9db5, 0x1dccffbf, 0x38a37142, + 0x389d9637, 0x1dd81e21, 0x1df9725f, 0x388bf7ff, 0x3886143b, 0x1e048c24, 0x1e25d282, 0x38745bdb, + 0x386e6f60, 0x1e30e7a4, 0x1e52200c, 0x385c9ce3, 0x3856a7b6, 0x1e5d3084, 0x1e7e5ae2, 0x3844bb28, + 0x383ebd4c, 0x1e8966a8, 0x1eaa82e9, 0x382cb6b7, 0x3826b030, 0x1eb589f7, 0x1ed69805, 0x38148f9f, + 0x380e8071, 0x1ee19a54, 0x1f029a1c, 0x37fc45ef, 0x37f62e1d, 0x1f0d97a5, 0x1f2e8911, 0x37e3d9b7, + 0x37ddb945, 0x1f3981ce, 0x1f5a64cb, 0x37cb4b04, 0x37c521f6, 0x1f6558b5, 0x1f862d2d, 0x37b299e7, + 0x37ac6841, 0x1f911c3d, 0x1fb1e21d, 0x3799c66f, 0x37938c34, 0x1fbccc4d, 0x1fdd8381, 0x3780d0aa, + 0x377a8ddf, 0x1fe868c8, 0x2009113c, 0x3767b8a9, 0x37616d51, 0x2013f196, 0x20348b35, 0x374e7e7b, + 0x37482a9a, 0x203f6699, 0x205ff14f, 0x3735222f, 0x372ec5c9, 0x206ac7b8, 0x208b4372, 0x371ba3d4, + 0x37153eee, 0x209614d9, 0x20b68181, 0x3702037c, 0x36fb9618, 0x20c14ddf, 0x20e1ab63, 0x36e84135, + 0x36e1cb58, 0x20ec72b1, 0x210cc0fc, 0x36ce5d10, 0x36c7debd, 0x21178334, 0x2137c232, 0x36b4571b, + 0x36add058, 0x21427f4d, 0x2162aeea, 0x369a2f69, 0x3693a038, 0x216d66e2, 0x218d870b, 0x367fe608, + 0x36794e6e, 0x219839d8, 0x21b84a79, 0x36657b08, 0x365edb09, 0x21c2f815, 0x21e2f91a, 0x364aee7b, + 0x3644461b, 0x21eda17f, 0x220d92d4, 0x36304070, 0x36298fb4, 0x221835fb, 0x2238178d, 0x361570f8, + 0x360eb7e3, 0x2242b56f, 0x22628729, 0x35fa8023, 0x35f3beba, 0x226d1fc1, 0x228ce191, 0x35df6e03, + 0x35d8a449, 0x229774d7, 0x22b726a8, 0x35c43aa7, 0x35bd68a1, 0x22c1b496, 0x22e15655, 0x35a8e621, + 0x35a20bd3, 0x22ebdee5, 0x230b707e, 0x358d7081, 0x35868def, 0x2315f3a8, 0x23357509, 0x3571d9d9, + 0x356aef08, 0x233ff2c8, 0x235f63dc, 0x35562239, 0x354f2f2c, 0x2369dc29, 0x23893cdd, 0x353a49b2, + 0x35334e6f, 0x2393afb2, 0x23b2fff3, 0x351e5056, 0x35174ce0, 0x23bd6d48, 0x23dcad03, 0x35023636, + 0x34fb2a92, 0x23e714d3, 0x240643f4, 0x34e5fb63, 0x34dee795, 0x2410a639, 0x242fc4ad, 0x34c99fef, + 0x34c283fb, 0x243a215f, 0x24592f13, 0x34ad23eb, 0x34a5ffd5, 0x2463862c, 0x2482830d, 0x34908768, + 0x34895b36, 0x248cd487, 0x24abc082, 0x3473ca79, 0x346c962f, 0x24b60c57, 0x24d4e757, 0x3456ed2f, + 0x344fb0d1, 0x24df2d81, 0x24fdf775, 0x3439ef9c, 0x3432ab2e, 0x250837ed, 0x2526f0c1, 0x341cd1d2, + 0x34158559, 0x25312b81, 0x254fd323, 0x33ff93e2, 0x33f83f62, 0x255a0823, 0x25789e80, 0x33e235df, + 0x33dad95e, 0x2582cdbc, 0x25a152c0, 0x33c4b7db, 0x33bd535c, 0x25ab7c30, 0x25c9efca, 0x33a719e8, + 0x339fad70, 0x25d41369, 0x25f27584, 0x33895c18, 0x3381e7ac, 0x25fc934b, 0x261ae3d6, 0x336b7e7e, + 0x33640223, 0x2624fbbf, 0x26433aa7, 0x334d812d, 0x3345fce6, 0x264d4cac, 0x266b79dd, 0x332f6435, + 0x3327d808, 0x267585f8, 0x2693a161, 0x331127ab, 0x3309939c, 0x269da78b, 0x26bbb119, 0x32f2cba1, + 0x32eb2fb5, 0x26c5b14c, 0x26e3a8ec, 0x32d45029, 0x32ccac64, 0x26eda322, 0x270b88c2, 0x32b5b557, + 0x32ae09be, 0x27157cf5, 0x27335082, 0x3296fb3d, 0x328f47d5, 0x273d3eac, 0x275b0014, 0x327821ee, + 0x327066bc, 0x2764e82f, 0x27829760, 0x3259297d, 0x32516686, 0x278c7965, 0x27aa164c, 0x323a11fe, + 0x32324746, 0x27b3f235, 0x27d17cc1, 0x321adb83, 0x3213090f, 0x27db5288, 0x27f8caa5, 0x31fb8620, + 0x31f3abf5, 0x28029a45, 0x281fffe2, 0x31dc11e8, 0x31d4300b, 0x2829c954, 0x28471c5e, 0x31bc7eee, + 0x31b49564, 0x2850df9d, 0x286e2002, 0x319ccd46, 0x3194dc14, 0x2877dd07, 0x28950ab6, 0x317cfd04, + 0x3175042e, 0x289ec17a, 0x28bbdc61, 0x315d0e3b, 0x31550dc6, 0x28c58cdf, 0x28e294eb, 0x313d00ff, + 0x3134f8f1, 0x28ec3f1e, 0x2909343e, 0x311cd564, 0x3114c5c0, 0x2912d81f, 0x292fba40, 0x30fc8b7d, + 0x30f47449, 0x293957c9, 0x295626da, 0x30dc235e, 0x30d404a0, 0x295fbe06, 0x297c79f5, 0x30bb9d1c, + 0x30b376d8, 0x29860abd, 0x29a2b378, 0x309af8ca, 0x3092cb05, 0x29ac3dd7, 0x29c8d34d, 0x307a367c, + 0x3072013c, 0x29d2573c, 0x29eed95b, 0x30595648, 0x30511991, 0x29f856d5, 0x2a14c58b, 0x30385840, + 0x30301418, 0x2a1e3c8a, 0x2a3a97c7, 0x30173c7a, 0x300ef0e5, 0x2a440844, 0x2a604ff5, 0x2ff6030a, + 0x2fedb00d, 0x2a69b9ec, 0x2a85ee00, 0x2fd4ac04, 0x2fcc51a5, 0x2a8f516b, 0x2aab71d0, 0x2fb3377c, + 0x2faad5c1, 0x2ab4cea9, 0x2ad0db4e, 0x2f91a589, 0x2f893c75, 0x2ada318e, 0x2af62a63, 0x2f6ff63d, + 0x2f6785d7, 0x2aff7a05, 0x2b1b5ef8, 0x2f4e29af, 0x2f45b1fb, 0x2b24a7f6, 0x2b4078f5, 0x2f2c3ff2, + 0x2f23c0f6, 0x2b49bb4a, 0x2b657844, 0x2f0a391d, 0x2f01b2de, 0x2b6eb3ea, 0x2b8a5cce, 0x2ee81543, + 0x2edf87c6, 0x2b9391c0, 0x2baf267d, 0x2ec5d479, 0x2ebd3fc4, 0x2bb854b4, 0x2bd3d53a, 0x2ea376d6, + 0x2e9adaee, 0x2bdcfcb0, 0x2bf868ed, 0x2e80fc6e, 0x2e785958, 0x2c01899e, 0x2c1ce181, 0x2e5e6556, + 0x2e55bb17, 0x2c25fb66, 0x2c413edf, 0x2e3bb1a4, 0x2e330042, 0x2c4a51f3, 0x2c6580f1, 0x2e18e16d, + 0x2e1028ed, 0x2c6e8d2e, 0x2c89a79f, 0x2df5f4c7, 0x2ded352f, 0x2c92ad01, 0x2cadb2d5, 0x2dd2ebc7, + 0x2dca251c, 0x2cb6b155, 0x2cd1a27b, 0x2dafc683, 0x2da6f8ca, 0x2cda9a14, 0x2cf5767c, 0x2d8c8510, + 0x2d83b04f, 0x2cfe6728, 0x2d192ec1, 0x2d692784, 0x2d604bc0, 0x2d22187a, 0x2d3ccb34, 0x2d45adf6 +}; + +const int twidTab512[8*6 + 32*6 + 128*6] = { + 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3b20d79e, 0x187de2a6, + 0x3ec52f9f, 0x0c7c5c1e, 0x3536cc52, 0x238e7673, 0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6, + 0x187de2a6, 0x3b20d79e, 0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673, 0xf383a3e2, 0x3ec52f9f, + 0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xe7821d5a, 0x3b20d79e, + 0x238e7673, 0x3536cc52, 0xc13ad061, 0x0c7c5c1e, 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, + 0xc4df2862, 0xe7821d5a, 0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f, 0xdc71898d, 0xcac933ae, + + 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3fb11b47, 0x0645e9af, + 0x3fec43c6, 0x0323ecbe, 0x3f4eaafe, 0x09640837, 0x3ec52f9f, 0x0c7c5c1e, 0x3fb11b47, 0x0645e9af, + 0x3d3e82ad, 0x1294062e, 0x3d3e82ad, 0x1294062e, 0x3f4eaafe, 0x09640837, 0x39daf5e8, 0x1b5d1009, + 0x3b20d79e, 0x187de2a6, 0x3ec52f9f, 0x0c7c5c1e, 0x3536cc52, 0x238e7673, 0x387165e3, 0x1e2b5d38, + 0x3e14fdf7, 0x0f8cfcbd, 0x2f6bbe44, 0x2afad269, 0x3536cc52, 0x238e7673, 0x3d3e82ad, 0x1294062e, + 0x2899e64a, 0x317900d6, 0x317900d6, 0x2899e64a, 0x3c424209, 0x158f9a75, 0x20e70f32, 0x36e5068a, + 0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x2899e64a, 0x317900d6, + 0x39daf5e8, 0x1b5d1009, 0x0f8cfcbd, 0x3e14fdf7, 0x238e7673, 0x3536cc52, 0x387165e3, 0x1e2b5d38, + 0x0645e9af, 0x3fb11b47, 0x1e2b5d38, 0x387165e3, 0x36e5068a, 0x20e70f32, 0xfcdc1342, 0x3fec43c6, + 0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673, 0xf383a3e2, 0x3ec52f9f, 0x1294062e, 0x3d3e82ad, + 0x3367c08f, 0x261feff9, 0xea70658b, 0x3c424209, 0x0c7c5c1e, 0x3ec52f9f, 0x317900d6, 0x2899e64a, + 0xe1d4a2c8, 0x387165e3, 0x0645e9af, 0x3fb11b47, 0x2f6bbe44, 0x2afad269, 0xd9e01007, 0x3367c08f, + 0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xf9ba1651, 0x3fb11b47, + 0x2afad269, 0x2f6bbe44, 0xcc983f71, 0x261feff9, 0xf383a3e2, 0x3ec52f9f, 0x2899e64a, 0x317900d6, + 0xc78e9a1d, 0x1e2b5d38, 0xed6bf9d2, 0x3d3e82ad, 0x261feff9, 0x3367c08f, 0xc3bdbdf7, 0x158f9a75, + 0xe7821d5a, 0x3b20d79e, 0x238e7673, 0x3536cc52, 0xc13ad061, 0x0c7c5c1e, 0xe1d4a2c8, 0x387165e3, + 0x20e70f32, 0x36e5068a, 0xc013bc3a, 0x0323ecbe, 0xdc71898d, 0x3536cc52, 0x1e2b5d38, 0x387165e3, + 0xc04ee4b9, 0xf9ba1651, 0xd76619b6, 0x317900d6, 0x1b5d1009, 0x39daf5e8, 0xc1eb0209, 0xf0730343, + 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a, 0xce86ff2a, 0x2899e64a, + 0x158f9a75, 0x3c424209, 0xc91af976, 0xdf18f0ce, 0xcac933ae, 0x238e7673, 0x1294062e, 0x3d3e82ad, + 0xce86ff2a, 0xd76619b6, 0xc78e9a1d, 0x1e2b5d38, 0x0f8cfcbd, 0x3e14fdf7, 0xd5052d97, 0xd09441bc, + 0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f, 0xdc71898d, 0xcac933ae, 0xc2c17d53, 0x1294062e, + 0x09640837, 0x3f4eaafe, 0xe4a2eff7, 0xc6250a18, 0xc13ad061, 0x0c7c5c1e, 0x0645e9af, 0x3fb11b47, + 0xed6bf9d2, 0xc2c17d53, 0xc04ee4b9, 0x0645e9af, 0x0323ecbe, 0x3fec43c6, 0xf69bf7c9, 0xc0b15502, + + 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3ffb10c1, 0x0192155f, + 0x3ffec42d, 0x00c90e8f, 0x3ff4e5df, 0x025b0cae, 0x3fec43c6, 0x0323ecbe, 0x3ffb10c1, 0x0192155f, + 0x3fd39b5a, 0x04b54824, 0x3fd39b5a, 0x04b54824, 0x3ff4e5df, 0x025b0cae, 0x3f9c2bfa, 0x070de171, + 0x3fb11b47, 0x0645e9af, 0x3fec43c6, 0x0323ecbe, 0x3f4eaafe, 0x09640837, 0x3f84c8e1, 0x07d59395, + 0x3fe12acb, 0x03ecadcf, 0x3eeb3347, 0x0bb6ecef, 0x3f4eaafe, 0x09640837, 0x3fd39b5a, 0x04b54824, + 0x3e71e758, 0x0e05c135, 0x3f0ec9f4, 0x0af10a22, 0x3fc395f9, 0x057db402, 0x3de2f147, 0x104fb80e, + 0x3ec52f9f, 0x0c7c5c1e, 0x3fb11b47, 0x0645e9af, 0x3d3e82ad, 0x1294062e, 0x3e71e758, 0x0e05c135, + 0x3f9c2bfa, 0x070de171, 0x3c84d496, 0x14d1e242, 0x3e14fdf7, 0x0f8cfcbd, 0x3f84c8e1, 0x07d59395, + 0x3bb6276d, 0x17088530, 0x3dae81ce, 0x1111d262, 0x3f6af2e3, 0x089cf867, 0x3ad2c2e7, 0x19372a63, + 0x3d3e82ad, 0x1294062e, 0x3f4eaafe, 0x09640837, 0x39daf5e8, 0x1b5d1009, 0x3cc511d8, 0x14135c94, + 0x3f2ff249, 0x0a2abb58, 0x38cf1669, 0x1d79775b, 0x3c424209, 0x158f9a75, 0x3f0ec9f4, 0x0af10a22, + 0x37af8158, 0x1f8ba4db, 0x3bb6276d, 0x17088530, 0x3eeb3347, 0x0bb6ecef, 0x367c9a7d, 0x2192e09a, + 0x3b20d79e, 0x187de2a6, 0x3ec52f9f, 0x0c7c5c1e, 0x3536cc52, 0x238e7673, 0x3a8269a2, 0x19ef7943, + 0x3e9cc076, 0x0d415012, 0x33de87de, 0x257db64b, 0x39daf5e8, 0x1b5d1009, 0x3e71e758, 0x0e05c135, + 0x32744493, 0x275ff452, 0x392a9642, 0x1cc66e99, 0x3e44a5ee, 0x0ec9a7f2, 0x30f8801f, 0x29348937, + 0x387165e3, 0x1e2b5d38, 0x3e14fdf7, 0x0f8cfcbd, 0x2f6bbe44, 0x2afad269, 0x37af8158, 0x1f8ba4db, + 0x3de2f147, 0x104fb80e, 0x2dce88a9, 0x2cb2324b, 0x36e5068a, 0x20e70f32, 0x3dae81ce, 0x1111d262, + 0x2c216eaa, 0x2e5a106f, 0x361214b0, 0x223d66a8, 0x3d77b191, 0x11d3443f, 0x2a650525, 0x2ff1d9c6, + 0x3536cc52, 0x238e7673, 0x3d3e82ad, 0x1294062e, 0x2899e64a, 0x317900d6, 0x34534f40, 0x24da0a99, + 0x3d02f756, 0x135410c2, 0x26c0b162, 0x32eefde9, 0x3367c08f, 0x261feff9, 0x3cc511d8, 0x14135c94, + 0x24da0a99, 0x34534f40, 0x32744493, 0x275ff452, 0x3c84d496, 0x14d1e242, 0x22e69ac7, 0x35a5793c, + 0x317900d6, 0x2899e64a, 0x3c424209, 0x158f9a75, 0x20e70f32, 0x36e5068a, 0x30761c17, 0x29cd9577, + 0x3bfd5cc4, 0x164c7ddd, 0x1edc1952, 0x3811884c, 0x2f6bbe44, 0x2afad269, 0x3bb6276d, 0x17088530, + 0x1cc66e99, 0x392a9642, 0x2e5a106f, 0x2c216eaa, 0x3b6ca4c4, 0x17c3a931, 0x1aa6c82b, 0x3a2fcee8, + 0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x2c216eaa, 0x2e5a106f, + 0x3ad2c2e7, 0x19372a63, 0x164c7ddd, 0x3bfd5cc4, 0x2afad269, 0x2f6bbe44, 0x3a8269a2, 0x19ef7943, + 0x14135c94, 0x3cc511d8, 0x29cd9577, 0x30761c17, 0x3a2fcee8, 0x1aa6c82b, 0x11d3443f, 0x3d77b191, + 0x2899e64a, 0x317900d6, 0x39daf5e8, 0x1b5d1009, 0x0f8cfcbd, 0x3e14fdf7, 0x275ff452, 0x32744493, + 0x3983e1e7, 0x1c1249d8, 0x0d415012, 0x3e9cc076, 0x261feff9, 0x3367c08f, 0x392a9642, 0x1cc66e99, + 0x0af10a22, 0x3f0ec9f4, 0x24da0a99, 0x34534f40, 0x38cf1669, 0x1d79775b, 0x089cf867, 0x3f6af2e3, + 0x238e7673, 0x3536cc52, 0x387165e3, 0x1e2b5d38, 0x0645e9af, 0x3fb11b47, 0x223d66a8, 0x361214b0, + 0x3811884c, 0x1edc1952, 0x03ecadcf, 0x3fe12acb, 0x20e70f32, 0x36e5068a, 0x37af8158, 0x1f8ba4db, + 0x0192155f, 0x3ffb10c1, 0x1f8ba4db, 0x37af8158, 0x374b54ce, 0x2039f90e, 0xff36f171, 0x3ffec42d, + 0x1e2b5d38, 0x387165e3, 0x36e5068a, 0x20e70f32, 0xfcdc1342, 0x3fec43c6, 0x1cc66e99, 0x392a9642, + 0x367c9a7d, 0x2192e09a, 0xfa824bfe, 0x3fc395f9, 0x1b5d1009, 0x39daf5e8, 0x361214b0, 0x223d66a8, + 0xf82a6c6b, 0x3f84c8e1, 0x19ef7943, 0x3a8269a2, 0x35a5793c, 0x22e69ac7, 0xf5d544a8, 0x3f2ff249, + 0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673, 0xf383a3e2, 0x3ec52f9f, 0x17088530, 0x3bb6276d, + 0x34c61236, 0x2434f332, 0xf136580e, 0x3e44a5ee, 0x158f9a75, 0x3c424209, 0x34534f40, 0x24da0a99, + 0xeeee2d9e, 0x3dae81ce, 0x14135c94, 0x3cc511d8, 0x33de87de, 0x257db64b, 0xecabef3e, 0x3d02f756, + 0x1294062e, 0x3d3e82ad, 0x3367c08f, 0x261feff9, 0xea70658b, 0x3c424209, 0x1111d262, 0x3dae81ce, + 0x32eefde9, 0x26c0b162, 0xe83c56cf, 0x3b6ca4c4, 0x0f8cfcbd, 0x3e14fdf7, 0x32744493, 0x275ff452, + 0xe61086bd, 0x3a8269a2, 0x0e05c135, 0x3e71e758, 0x31f79947, 0x27fdb2a6, 0xe3edb628, 0x3983e1e7, + 0x0c7c5c1e, 0x3ec52f9f, 0x317900d6, 0x2899e64a, 0xe1d4a2c8, 0x387165e3, 0x0af10a22, 0x3f0ec9f4, + 0x30f8801f, 0x29348937, 0xdfc606f2, 0x374b54ce, 0x09640837, 0x3f4eaafe, 0x30761c17, 0x29cd9577, + 0xddc29958, 0x361214b0, 0x07d59395, 0x3f84c8e1, 0x2ff1d9c6, 0x2a650525, 0xdbcb0cce, 0x34c61236, + 0x0645e9af, 0x3fb11b47, 0x2f6bbe44, 0x2afad269, 0xd9e01007, 0x3367c08f, 0x04b54824, 0x3fd39b5a, + 0x2ee3cebe, 0x2b8ef77c, 0xd8024d5a, 0x31f79947, 0x0323ecbe, 0x3fec43c6, 0x2e5a106f, 0x2c216eaa, + 0xd6326a89, 0x30761c17, 0x0192155f, 0x3ffb10c1, 0x2dce88a9, 0x2cb2324b, 0xd4710884, 0x2ee3cebe, + 0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xfe6deaa1, 0x3ffb10c1, + 0x2cb2324b, 0x2dce88a9, 0xd11c3142, 0x2b8ef77c, 0xfcdc1342, 0x3fec43c6, 0x2c216eaa, 0x2e5a106f, + 0xcf89e3e9, 0x29cd9577, 0xfb4ab7dc, 0x3fd39b5a, 0x2b8ef77c, 0x2ee3cebe, 0xce0866b9, 0x27fdb2a6, + 0xf9ba1651, 0x3fb11b47, 0x2afad269, 0x2f6bbe44, 0xcc983f71, 0x261feff9, 0xf82a6c6b, 0x3f84c8e1, + 0x2a650525, 0x2ff1d9c6, 0xcb39edca, 0x2434f332, 0xf69bf7c9, 0x3f4eaafe, 0x29cd9577, 0x30761c17, + 0xc9edeb50, 0x223d66a8, 0xf50ef5de, 0x3f0ec9f4, 0x29348937, 0x30f8801f, 0xc8b4ab32, 0x2039f90e, + 0xf383a3e2, 0x3ec52f9f, 0x2899e64a, 0x317900d6, 0xc78e9a1d, 0x1e2b5d38, 0xf1fa3ecb, 0x3e71e758, + 0x27fdb2a6, 0x31f79947, 0xc67c1e19, 0x1c1249d8, 0xf0730343, 0x3e14fdf7, 0x275ff452, 0x32744493, + 0xc57d965e, 0x19ef7943, 0xeeee2d9e, 0x3dae81ce, 0x26c0b162, 0x32eefde9, 0xc4935b3c, 0x17c3a931, + 0xed6bf9d2, 0x3d3e82ad, 0x261feff9, 0x3367c08f, 0xc3bdbdf7, 0x158f9a75, 0xebeca36c, 0x3cc511d8, + 0x257db64b, 0x33de87de, 0xc2fd08aa, 0x135410c2, 0xea70658b, 0x3c424209, 0x24da0a99, 0x34534f40, + 0xc2517e32, 0x1111d262, 0xe8f77ad0, 0x3bb6276d, 0x2434f332, 0x34c61236, 0xc1bb5a12, 0x0ec9a7f2, + 0xe7821d5a, 0x3b20d79e, 0x238e7673, 0x3536cc52, 0xc13ad061, 0x0c7c5c1e, 0xe61086bd, 0x3a8269a2, + 0x22e69ac7, 0x35a5793c, 0xc0d00db7, 0x0a2abb58, 0xe4a2eff7, 0x39daf5e8, 0x223d66a8, 0x361214b0, + 0xc07b371f, 0x07d59395, 0xe3399167, 0x392a9642, 0x2192e09a, 0x367c9a7d, 0xc03c6a07, 0x057db402, + 0xe1d4a2c8, 0x387165e3, 0x20e70f32, 0x36e5068a, 0xc013bc3a, 0x0323ecbe, 0xe0745b25, 0x37af8158, + 0x2039f90e, 0x374b54ce, 0xc0013bd3, 0x00c90e8f, 0xdf18f0ce, 0x36e5068a, 0x1f8ba4db, 0x37af8158, + 0xc004ef3f, 0xfe6deaa1, 0xddc29958, 0x361214b0, 0x1edc1952, 0x3811884c, 0xc01ed535, 0xfc135231, + 0xdc71898d, 0x3536cc52, 0x1e2b5d38, 0x387165e3, 0xc04ee4b9, 0xf9ba1651, 0xdb25f567, 0x34534f40, + 0x1d79775b, 0x38cf1669, 0xc0950d1d, 0xf7630799, 0xd9e01007, 0x3367c08f, 0x1cc66e99, 0x392a9642, + 0xc0f1360c, 0xf50ef5de, 0xd8a00bae, 0x32744493, 0x1c1249d8, 0x3983e1e7, 0xc1633f8a, 0xf2beafee, + 0xd76619b6, 0x317900d6, 0x1b5d1009, 0x39daf5e8, 0xc1eb0209, 0xf0730343, 0xd6326a89, 0x30761c17, + 0x1aa6c82b, 0x3a2fcee8, 0xc2884e6f, 0xee2cbbc1, 0xd5052d97, 0x2f6bbe44, 0x19ef7943, 0x3a8269a2, + 0xc33aee28, 0xebeca36c, 0xd3de9156, 0x2e5a106f, 0x19372a63, 0x3ad2c2e7, 0xc402a33c, 0xe9b38223, + 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a, 0xd1a5ef91, 0x2c216eaa, + 0x17c3a931, 0x3b6ca4c4, 0xc5d03118, 0xe55937d5, 0xd09441bc, 0x2afad269, 0x17088530, 0x3bb6276d, + 0xc6d569be, 0xe3399167, 0xcf89e3e9, 0x29cd9577, 0x164c7ddd, 0x3bfd5cc4, 0xc7ee77b4, 0xe123e6ae, + 0xce86ff2a, 0x2899e64a, 0x158f9a75, 0x3c424209, 0xc91af976, 0xdf18f0ce, 0xcd8bbb6d, 0x275ff452, + 0x14d1e242, 0x3c84d496, 0xca5a86c4, 0xdd196539, 0xcc983f71, 0x261feff9, 0x14135c94, 0x3cc511d8, + 0xcbacb0c0, 0xdb25f567, 0xcbacb0c0, 0x24da0a99, 0x135410c2, 0x3d02f756, 0xcd110217, 0xd93f4e9e, + 0xcac933ae, 0x238e7673, 0x1294062e, 0x3d3e82ad, 0xce86ff2a, 0xd76619b6, 0xc9edeb50, 0x223d66a8, + 0x11d3443f, 0x3d77b191, 0xd00e263a, 0xd59afadb, 0xc91af976, 0x20e70f32, 0x1111d262, 0x3dae81ce, + 0xd1a5ef91, 0xd3de9156, 0xc8507ea8, 0x1f8ba4db, 0x104fb80e, 0x3de2f147, 0xd34dcdb5, 0xd2317757, + 0xc78e9a1d, 0x1e2b5d38, 0x0f8cfcbd, 0x3e14fdf7, 0xd5052d97, 0xd09441bc, 0xc6d569be, 0x1cc66e99, + 0x0ec9a7f2, 0x3e44a5ee, 0xd6cb76c9, 0xcf077fe1, 0xc6250a18, 0x1b5d1009, 0x0e05c135, 0x3e71e758, + 0xd8a00bae, 0xcd8bbb6d, 0xc57d965e, 0x19ef7943, 0x0d415012, 0x3e9cc076, 0xda8249b5, 0xcc217822, + 0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f, 0xdc71898d, 0xcac933ae, 0xc449d893, 0x17088530, + 0x0bb6ecef, 0x3eeb3347, 0xde6d1f66, 0xc9836583, 0xc3bdbdf7, 0x158f9a75, 0x0af10a22, 0x3f0ec9f4, + 0xe0745b25, 0xc8507ea8, 0xc33aee28, 0x14135c94, 0x0a2abb58, 0x3f2ff249, 0xe28688a5, 0xc730e997, + 0xc2c17d53, 0x1294062e, 0x09640837, 0x3f4eaafe, 0xe4a2eff7, 0xc6250a18, 0xc2517e32, 0x1111d262, + 0x089cf867, 0x3f6af2e3, 0xe6c8d59d, 0xc52d3d19, 0xc1eb0209, 0x0f8cfcbd, 0x07d59395, 0x3f84c8e1, + 0xe8f77ad0, 0xc449d893, 0xc18e18a8, 0x0e05c135, 0x070de171, 0x3f9c2bfa, 0xeb2e1dbe, 0xc37b2b6a, + 0xc13ad061, 0x0c7c5c1e, 0x0645e9af, 0x3fb11b47, 0xed6bf9d2, 0xc2c17d53, 0xc0f1360c, 0x0af10a22, + 0x057db402, 0x3fc395f9, 0xefb047f2, 0xc21d0eb9, 0xc0b15502, 0x09640837, 0x04b54824, 0x3fd39b5a, + 0xf1fa3ecb, 0xc18e18a8, 0xc07b371f, 0x07d59395, 0x03ecadcf, 0x3fe12acb, 0xf4491311, 0xc114ccb9, + 0xc04ee4b9, 0x0645e9af, 0x0323ecbe, 0x3fec43c6, 0xf69bf7c9, 0xc0b15502, 0xc02c64a6, 0x04b54824, + 0x025b0cae, 0x3ff4e5df, 0xf8f21e8f, 0xc063d406, 0xc013bc3a, 0x0323ecbe, 0x0192155f, 0x3ffb10c1, + 0xfb4ab7dc, 0xc02c64a6, 0xc004ef3f, 0x0192155f, 0x00c90e8f, 0x3ffec42d, 0xfda4f352, 0xc00b1a21 +}; + +const int twidTab64[4*6 + 16*6] = { + 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x2d413ccc, 0x2d413ccc, + 0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, + 0xd2bec334, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a, + + 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3ec52f9f, 0x0c7c5c1e, + 0x3fb11b47, 0x0645e9af, 0x3d3e82ad, 0x1294062e, 0x3b20d79e, 0x187de2a6, 0x3ec52f9f, 0x0c7c5c1e, + 0x3536cc52, 0x238e7673, 0x3536cc52, 0x238e7673, 0x3d3e82ad, 0x1294062e, 0x2899e64a, 0x317900d6, + 0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x238e7673, 0x3536cc52, + 0x387165e3, 0x1e2b5d38, 0x0645e9af, 0x3fb11b47, 0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673, + 0xf383a3e2, 0x3ec52f9f, 0x0c7c5c1e, 0x3ec52f9f, 0x317900d6, 0x2899e64a, 0xe1d4a2c8, 0x387165e3, + 0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xf383a3e2, 0x3ec52f9f, + 0x2899e64a, 0x317900d6, 0xc78e9a1d, 0x1e2b5d38, 0xe7821d5a, 0x3b20d79e, 0x238e7673, 0x3536cc52, + 0xc13ad061, 0x0c7c5c1e, 0xdc71898d, 0x3536cc52, 0x1e2b5d38, 0x387165e3, 0xc04ee4b9, 0xf9ba1651, + 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a, 0xcac933ae, 0x238e7673, + 0x1294062e, 0x3d3e82ad, 0xce86ff2a, 0xd76619b6, 0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f, + 0xdc71898d, 0xcac933ae, 0xc13ad061, 0x0c7c5c1e, 0x0645e9af, 0x3fb11b47, 0xed6bf9d2, 0xc2c17d53 +}; +#endif //ARMV5E + +const int ShortWindowSine[FRAME_LEN_SHORT/2] ={ + 0x00c97fff, 0x025b7ffa, 0x03ed7ff1, 0x057f7fe2, 0x07117fce, 0x08a27fb5, 0x0a337f98, 0x0bc47f75, + 0x0d547f4e, 0x0ee47f22, 0x10737ef0, 0x12017eba, 0x138f7e7f, 0x151c7e3f, 0x16a87dfb, 0x18337db1, + 0x19be7d63, 0x1b477d0f, 0x1cd07cb7, 0x1e577c5a, 0x1fdd7bf9, 0x21627b92, 0x22e57b27, 0x24677ab7, + 0x25e87a42, 0x276879c9, 0x28e5794a, 0x2a6278c8, 0x2bdc7840, 0x2d5577b4, 0x2ecc7723, 0x3042768e, + 0x31b575f4, 0x33277556, 0x349774b3, 0x3604740b, 0x3770735f, 0x38d972af, 0x3a4071fa, 0x3ba57141, + 0x3d087083, 0x3e686fc2, 0x3fc66efb, 0x41216e31, 0x427a6d62, 0x43d16c8f, 0x45246bb8, 0x46756add, + 0x47c469fd, 0x490f691a, 0x4a586832, 0x4b9e6747, 0x4ce16657, 0x4e216564, 0x4f5e646c, 0x50986371, + 0x51cf6272, 0x5303616f, 0x54336068, 0x55605f5e, 0x568a5e50, 0x57b15d3e, 0x58d45c29, 0x59f45b10 +}; + +const int LongWindowKBD[FRAME_LEN_LONG/2]={ + 0x000a7fff, 0x000e7fff, 0x00127fff, 0x00157fff, 0x00197fff, 0x001c7fff, 0x00207fff, 0x00237fff, + 0x00267fff, 0x002a7fff, 0x002d7fff, 0x00307fff, 0x00347fff, 0x00387fff, 0x003b7fff, 0x003f7fff, + 0x00437fff, 0x00477fff, 0x004b7fff, 0x004f7fff, 0x00537fff, 0x00577fff, 0x005b7fff, 0x00607fff, + 0x00647fff, 0x00697fff, 0x006d7fff, 0x00727fff, 0x00777fff, 0x007c7fff, 0x00817fff, 0x00867fff, + 0x008b7fff, 0x00917fff, 0x00967fff, 0x009c7fff, 0x00a17fff, 0x00a77fff, 0x00ad7fff, 0x00b37fff, + 0x00b97fff, 0x00bf7fff, 0x00c67fff, 0x00cc7fff, 0x00d37fff, 0x00da7fff, 0x00e07fff, 0x00e77fff, + 0x00ee7fff, 0x00f57fff, 0x00fd7fff, 0x01047fff, 0x010c7fff, 0x01137fff, 0x011b7fff, 0x01237fff, + 0x012b7fff, 0x01337fff, 0x013c7ffe, 0x01447ffe, 0x014d7ffe, 0x01567ffe, 0x015f7ffe, 0x01687ffe, + 0x01717ffe, 0x017a7ffe, 0x01837ffe, 0x018d7ffe, 0x01977ffd, 0x01a17ffd, 0x01ab7ffd, 0x01b57ffd, + 0x01bf7ffd, 0x01ca7ffd, 0x01d47ffd, 0x01df7ffc, 0x01ea7ffc, 0x01f57ffc, 0x02007ffc, 0x020c7ffc, + 0x02177ffc, 0x02237ffb, 0x022f7ffb, 0x023b7ffb, 0x02477ffb, 0x02537ffb, 0x02607ffa, 0x026d7ffa, + 0x027a7ffa, 0x02877ffa, 0x02947ff9, 0x02a17ff9, 0x02af7ff9, 0x02bc7ff9, 0x02ca7ff8, 0x02d87ff8, + 0x02e77ff8, 0x02f57ff7, 0x03047ff7, 0x03127ff7, 0x03217ff6, 0x03317ff6, 0x03407ff5, 0x034f7ff5, + 0x035f7ff5, 0x036f7ff4, 0x037f7ff4, 0x038f7ff3, 0x03a07ff3, 0x03b07ff2, 0x03c17ff2, 0x03d27ff1, + 0x03e37ff1, 0x03f57ff0, 0x04067ff0, 0x04187fef, 0x042a7fef, 0x043c7fee, 0x044f7fed, 0x04617fed, + 0x04747fec, 0x04877feb, 0x049a7feb, 0x04ae7fea, 0x04c17fe9, 0x04d57fe9, 0x04e97fe8, 0x04fd7fe7, + 0x05127fe6, 0x05277fe5, 0x053b7fe5, 0x05507fe4, 0x05667fe3, 0x057b7fe2, 0x05917fe1, 0x05a77fe0, + 0x05bd7fdf, 0x05d37fde, 0x05ea7fdd, 0x06017fdc, 0x06187fdb, 0x062f7fda, 0x06467fd9, 0x065e7fd7, + 0x06767fd6, 0x068e7fd5, 0x06a67fd4, 0x06bf7fd2, 0x06d87fd1, 0x06f17fd0, 0x070a7fce, 0x07237fcd, + 0x073d7fcc, 0x07577fca, 0x07717fc9, 0x078c7fc7, 0x07a67fc5, 0x07c17fc4, 0x07dc7fc2, 0x07f77fc0, + 0x08137fbf, 0x082f7fbd, 0x084b7fbb, 0x08677fb9, 0x08847fb7, 0x08a07fb6, 0x08bd7fb4, 0x08da7fb2, + 0x08f87faf, 0x09167fad, 0x09347fab, 0x09527fa9, 0x09707fa7, 0x098f7fa5, 0x09ae7fa2, 0x09cd7fa0, + 0x09ec7f9d, 0x0a0c7f9b, 0x0a2c7f98, 0x0a4c7f96, 0x0a6c7f93, 0x0a8d7f91, 0x0aae7f8e, 0x0acf7f8b, + 0x0af07f88, 0x0b127f85, 0x0b337f82, 0x0b557f7f, 0x0b787f7c, 0x0b9a7f79, 0x0bbd7f76, 0x0be07f73, + 0x0c047f6f, 0x0c277f6c, 0x0c4b7f69, 0x0c6f7f65, 0x0c937f61, 0x0cb87f5e, 0x0cdd7f5a, 0x0d027f56, + 0x0d277f53, 0x0d4d7f4f, 0x0d737f4b, 0x0d997f47, 0x0dbf7f43, 0x0de67f3e, 0x0e0c7f3a, 0x0e347f36, + 0x0e5b7f31, 0x0e837f2d, 0x0eaa7f28, 0x0ed37f24, 0x0efb7f1f, 0x0f237f1a, 0x0f4c7f15, 0x0f757f10, + 0x0f9f7f0b, 0x0fc87f06, 0x0ff27f01, 0x101c7efb, 0x10477ef6, 0x10717ef0, 0x109c7eeb, 0x10c87ee5, + 0x10f37edf, 0x111f7eda, 0x114a7ed4, 0x11777ece, 0x11a37ec7, 0x11d07ec1, 0x11fd7ebb, 0x122a7eb4, + 0x12577eae, 0x12857ea7, 0x12b37ea0, 0x12e17e9a, 0x130f7e93, 0x133e7e8c, 0x136d7e84, 0x139c7e7d, + 0x13cc7e76, 0x13fb7e6e, 0x142b7e67, 0x145b7e5f, 0x148c7e57, 0x14bc7e4f, 0x14ed7e47, 0x151e7e3f, + 0x15507e37, 0x15817e2e, 0x15b37e26, 0x15e57e1d, 0x16187e14, 0x164a7e0b, 0x167d7e02, 0x16b07df9, + 0x16e47df0, 0x17177de6, 0x174b7ddd, 0x177f7dd3, 0x17b37dc9, 0x17e87dbf, 0x181d7db5, 0x18527dab, + 0x18877da1, 0x18bc7d96, 0x18f27d8c, 0x19287d81, 0x195e7d76, 0x19957d6b, 0x19cb7d60, 0x1a027d54, + 0x1a397d49, 0x1a717d3d, 0x1aa87d31, 0x1ae07d26, 0x1b187d19, 0x1b507d0d, 0x1b897d01, 0x1bc27cf4, + 0x1bfb7ce8, 0x1c347cdb, 0x1c6d7cce, 0x1ca77cc1, 0x1ce17cb3, 0x1d1b7ca6, 0x1d557c98, 0x1d8f7c8a, + 0x1dca7c7c, 0x1e057c6e, 0x1e407c60, 0x1e7b7c51, 0x1eb77c43, 0x1ef37c34, 0x1f2f7c25, 0x1f6b7c16, + 0x1fa77c06, 0x1fe47bf7, 0x20217be7, 0x205e7bd7, 0x209b7bc7, 0x20d87bb7, 0x21167ba6, 0x21547b96, + 0x21927b85, 0x21d07b74, 0x220e7b63, 0x224d7b52, 0x228c7b40, 0x22cb7b2e, 0x230a7b1c, 0x23497b0a, + 0x23897af8, 0x23c87ae6, 0x24087ad3, 0x24487ac0, 0x24897aad, 0x24c97a9a, 0x250a7a86, 0x254b7a73, + 0x258c7a5f, 0x25cd7a4b, 0x260e7a36, 0x26507a22, 0x26917a0d, 0x26d379f8, 0x271579e3, 0x275779ce, + 0x279a79b8, 0x27dc79a3, 0x281f798d, 0x28627977, 0x28a57960, 0x28e8794a, 0x292b7933, 0x296f791c, + 0x29b27905, 0x29f678ed, 0x2a3a78d6, 0x2a7e78be, 0x2ac278a6, 0x2b07788d, 0x2b4b7875, 0x2b90785c, + 0x2bd47843, 0x2c19782a, 0x2c5e7810, 0x2ca477f7, 0x2ce977dd, 0x2d2e77c3, 0x2d7477a8, 0x2dba778e, + 0x2dff7773, 0x2e457758, 0x2e8b773d, 0x2ed27721, 0x2f187706, 0x2f5e76ea, 0x2fa576cd, 0x2fec76b1, + 0x30327694, 0x30797677, 0x30c0765a, 0x3107763d, 0x314e761f, 0x31967601, 0x31dd75e3, 0x322575c5, + 0x326c75a6, 0x32b47588, 0x32fc7569, 0x33447549, 0x338c752a, 0x33d4750a, 0x341c74ea, 0x346474ca, + 0x34ac74a9, 0x34f57488, 0x353d7467, 0x35857446, 0x35ce7424, 0x36177403, 0x365f73e1, 0x36a873be, + 0x36f1739c, 0x373a7379, 0x37837356, 0x37cc7333, 0x3815730f, 0x385e72ec, 0x38a772c8, 0x38f172a3, + 0x393a727f, 0x3983725a, 0x39cd7235, 0x3a167210, 0x3a6071ea, 0x3aa971c4, 0x3af3719e, 0x3b3c7178, + 0x3b867151, 0x3bd0712b, 0x3c197104, 0x3c6370dc, 0x3cad70b5, 0x3cf7708d, 0x3d407065, 0x3d8a703c, + 0x3dd47014, 0x3e1e6feb, 0x3e686fc2, 0x3eb16f98, 0x3efb6f6f, 0x3f456f45, 0x3f8f6f1b, 0x3fd96ef0, + 0x40236ec6, 0x406d6e9b, 0x40b66e70, 0x41006e44, 0x414a6e19, 0x41946ded, 0x41de6dc1, 0x42286d94, + 0x42716d68, 0x42bb6d3b, 0x43056d0d, 0x434f6ce0, 0x43986cb2, 0x43e26c84, 0x442c6c56, 0x44756c28, + 0x44bf6bf9, 0x45086bca, 0x45526b9b, 0x459b6b6b, 0x45e56b3c, 0x462e6b0c, 0x46786adb, 0x46c16aab, + 0x470a6a7a, 0x47536a49, 0x479c6a18, 0x47e569e7, 0x482e69b5, 0x48776983, 0x48c06951, 0x4909691e, + 0x495268ec, 0x499b68b9, 0x49e36885, 0x4a2c6852, 0x4a74681e, 0x4abd67ea, 0x4b0567b6, 0x4b4d6782, + 0x4b95674d, 0x4bde6718, 0x4c2666e3, 0x4c6d66ae, 0x4cb56678, 0x4cfd6642, 0x4d45660c, 0x4d8c65d6, + 0x4dd4659f, 0x4e1b6568, 0x4e626531, 0x4ea964fa, 0x4ef064c3, 0x4f37648b, 0x4f7e6453, 0x4fc5641b, + 0x500b63e2, 0x505263aa, 0x50986371, 0x50df6338, 0x512562fe, 0x516b62c5, 0x51b1628b, 0x51f66251, + 0x523c6217, 0x528161dc, 0x52c761a2, 0x530c6167, 0x5351612c, 0x539660f1, 0x53db60b5, 0x54206079, + 0x5464603d, 0x54a96001, 0x54ed5fc5, 0x55315f88, 0x55755f4b, 0x55b95f0e, 0x55fc5ed1, 0x56405e94, + 0x56835e56, 0x56c75e18, 0x570a5dda, 0x574d5d9c, 0x578f5d5e, 0x57d25d1f, 0x58145ce0, 0x58565ca1, + 0x58995c62, 0x58da5c23, 0x591c5be3, 0x595e5ba4, 0x599f5b64, 0x59e05b24, 0x5a215ae3, 0x5a625aa3 +}; + + +/* + form factor +*/ +/* sqrt(((i+(1<<(FF_SQRT_BITS-2)+0.5)/2^31) */ +const Word32 formfac_sqrttable[96] = { + 0x000407f8, 0x000417b9, 0x0004273f, 0x0004368c, 0x000445a1, 0x00045483, 0x00046332, 0x000471b0, + 0x00048000, 0x00048e22, 0x00049c1a, 0x0004a9e7, 0x0004b78c, 0x0004c50a, 0x0004d263, 0x0004df96, + 0x0004eca7, 0x0004f995, 0x00050662, 0x0005130e, 0x00051f9c, 0x00052c0a, 0x0005385b, 0x00054490, + 0x000550a8, 0x00055ca5, 0x00056888, 0x00057450, 0x00058000, 0x00058b96, 0x00059715, 0x0005a27c, + 0x0005adcc, 0x0005b906, 0x0005c42b, 0x0005cf39, 0x0005da33, 0x0005e519, 0x0005efea, 0x0005faa8, + 0x00060552, 0x00060fea, 0x00061a70, 0x000624e3, 0x00062f45, 0x00063996, 0x000643d5, 0x00064e04, + 0x00065823, 0x00066231, 0x00066c30, 0x0006761f, 0x00068000, 0x000689d1, 0x00069393, 0x00069d47, + 0x0006a6ed, 0x0006b085, 0x0006ba10, 0x0006c38d, 0x0006ccfc, 0x0006d65f, 0x0006dfb5, 0x0006e8fe, + 0x0006f23b, 0x0006fb6c, 0x00070490, 0x00070da9, 0x000716b6, 0x00071fb8, 0x000728ae, 0x00073199, + 0x00073a79, 0x0007434e, 0x00074c19, 0x000754d9, 0x00075d8e, 0x0007663a, 0x00076edb, 0x00077772, + 0x00078000, 0x00078883, 0x000790fd, 0x0007996e, 0x0007a1d5, 0x0007aa33, 0x0007b288, 0x0007bad4, + 0x0007c318, 0x0007cb52, 0x0007d384, 0x0007dbad, 0x0007e3ce, 0x0007ebe6, 0x0007f3f6, 0x0007fbfe +}; + + + +/*! + \name quantizer and inverse quantizer tables + + \brief these tables are used for the non + linear quantizer and inverse quantizer + +*/ +const Word32 mTab_3_4[512] = { + 0x4c1bf829, 0x4c3880de, 0x4c550603, 0x4c71879c, + 0x4c8e05aa, 0x4caa8030, 0x4cc6f72f, 0x4ce36aab, + 0x4cffdaa4, 0x4d1c471d, 0x4d38b019, 0x4d55159a, + 0x4d7177a1, 0x4d8dd631, 0x4daa314b, 0x4dc688f3, + 0x4de2dd2a, 0x4dff2df2, 0x4e1b7b4d, 0x4e37c53d, + 0x4e540bc5, 0x4e704ee6, 0x4e8c8ea3, 0x4ea8cafd, + 0x4ec503f7, 0x4ee13992, 0x4efd6bd0, 0x4f199ab4, + 0x4f35c640, 0x4f51ee75, 0x4f6e1356, 0x4f8a34e4, + 0x4fa65321, 0x4fc26e10, 0x4fde85b2, 0x4ffa9a0a, + 0x5016ab18, 0x5032b8e0, 0x504ec362, 0x506acaa1, + 0x5086cea0, 0x50a2cf5e, 0x50becce0, 0x50dac725, + 0x50f6be31, 0x5112b205, 0x512ea2a3, 0x514a900d, + 0x51667a45, 0x5182614c, 0x519e4524, 0x51ba25cf, + 0x51d60350, 0x51f1dda7, 0x520db4d6, 0x522988e0, + 0x524559c6, 0x52612789, 0x527cf22d, 0x5298b9b1, + 0x52b47e19, 0x52d03f65, 0x52ebfd98, 0x5307b8b4, + 0x532370b9, 0x533f25aa, 0x535ad789, 0x53768656, + 0x53923215, 0x53addac6, 0x53c9806b, 0x53e52306, + 0x5400c298, 0x541c5f24, 0x5437f8ab, 0x54538f2e, + 0x546f22af, 0x548ab330, 0x54a640b3, 0x54c1cb38, + 0x54dd52c2, 0x54f8d753, 0x551458eb, 0x552fd78d, + 0x554b5339, 0x5566cbf3, 0x558241bb, 0x559db492, + 0x55b9247b, 0x55d49177, 0x55effb87, 0x560b62ad, + 0x5626c6eb, 0x56422842, 0x565d86b4, 0x5678e242, + 0x56943aee, 0x56af90b9, 0x56cae3a4, 0x56e633b2, + 0x570180e4, 0x571ccb3b, 0x573812b8, 0x5753575e, + 0x576e992e, 0x5789d829, 0x57a51450, 0x57c04da6, + 0x57db842b, 0x57f6b7e1, 0x5811e8c9, 0x582d16e6, + 0x58484238, 0x58636ac0, 0x587e9081, 0x5899b37c, + 0x58b4d3b1, 0x58cff123, 0x58eb0bd3, 0x590623c2, + 0x592138f2, 0x593c4b63, 0x59575b19, 0x59726812, + 0x598d7253, 0x59a879da, 0x59c37eab, 0x59de80c6, + 0x59f9802d, 0x5a147ce0, 0x5a2f76e2, 0x5a4a6e34, + 0x5a6562d6, 0x5a8054cb, 0x5a9b4414, 0x5ab630b2, + 0x5ad11aa6, 0x5aec01f1, 0x5b06e696, 0x5b21c895, + 0x5b3ca7ef, 0x5b5784a6, 0x5b725ebc, 0x5b8d3631, + 0x5ba80b06, 0x5bc2dd3e, 0x5bddacd9, 0x5bf879d8, + 0x5c13443d, 0x5c2e0c09, 0x5c48d13e, 0x5c6393dc, + 0x5c7e53e5, 0x5c99115a, 0x5cb3cc3c, 0x5cce848d, + 0x5ce93a4e, 0x5d03ed80, 0x5d1e9e24, 0x5d394c3b, + 0x5d53f7c7, 0x5d6ea0c9, 0x5d894742, 0x5da3eb33, + 0x5dbe8c9e, 0x5dd92b84, 0x5df3c7e5, 0x5e0e61c3, + 0x5e28f920, 0x5e438dfc, 0x5e5e2059, 0x5e78b037, + 0x5e933d99, 0x5eadc87e, 0x5ec850e9, 0x5ee2d6da, + 0x5efd5a53, 0x5f17db54, 0x5f3259e0, 0x5f4cd5f6, + 0x5f674f99, 0x5f81c6c8, 0x5f9c3b87, 0x5fb6add4, + 0x5fd11db3, 0x5feb8b23, 0x6005f626, 0x60205ebd, + 0x603ac4e9, 0x605528ac, 0x606f8a05, 0x6089e8f7, + 0x60a44583, 0x60be9fa9, 0x60d8f76b, 0x60f34cca, + 0x610d9fc7, 0x6127f062, 0x61423e9e, 0x615c8a7a, + 0x6176d3f9, 0x61911b1b, 0x61ab5fe1, 0x61c5a24d, + 0x61dfe25f, 0x61fa2018, 0x62145b7a, 0x622e9485, + 0x6248cb3b, 0x6262ff9d, 0x627d31ab, 0x62976167, + 0x62b18ed1, 0x62cbb9eb, 0x62e5e2b6, 0x63000933, + 0x631a2d62, 0x63344f45, 0x634e6edd, 0x63688c2b, + 0x6382a730, 0x639cbfec, 0x63b6d661, 0x63d0ea90, + 0x63eafc7a, 0x64050c1f, 0x641f1982, 0x643924a2, + 0x64532d80, 0x646d341f, 0x6487387e, 0x64a13a9e, + 0x64bb3a81, 0x64d53828, 0x64ef3393, 0x65092cc4, + 0x652323bb, 0x653d1879, 0x65570b00, 0x6570fb50, + 0x658ae96b, 0x65a4d550, 0x65bebf01, 0x65d8a680, + 0x65f28bcc, 0x660c6ee8, 0x66264fd3, 0x66402e8f, + 0x665a0b1c, 0x6673e57d, 0x668dbdb0, 0x66a793b8, + 0x66c16795, 0x66db3949, 0x66f508d4, 0x670ed636, + 0x6728a172, 0x67426a87, 0x675c3177, 0x6775f643, + 0x678fb8eb, 0x67a97971, 0x67c337d5, 0x67dcf418, + 0x67f6ae3b, 0x6810663f, 0x682a1c25, 0x6843cfed, + 0x685d8199, 0x68773129, 0x6890de9f, 0x68aa89fa, + 0x68c4333d, 0x68ddda67, 0x68f77f7a, 0x69112277, + 0x692ac35e, 0x69446230, 0x695dfeee, 0x6977999a, + 0x69913232, 0x69aac8ba, 0x69c45d31, 0x69ddef98, + 0x69f77ff0, 0x6a110e3a, 0x6a2a9a77, 0x6a4424a8, + 0x6a5daccc, 0x6a7732e6, 0x6a90b6f6, 0x6aaa38fd, + 0x6ac3b8fb, 0x6add36f2, 0x6af6b2e2, 0x6b102ccd, + 0x6b29a4b2, 0x6b431a92, 0x6b5c8e6f, 0x6b76004a, + 0x6b8f7022, 0x6ba8ddf9, 0x6bc249d0, 0x6bdbb3a7, + 0x6bf51b80, 0x6c0e815a, 0x6c27e537, 0x6c414718, + 0x6c5aa6fd, 0x6c7404e7, 0x6c8d60d7, 0x6ca6bace, + 0x6cc012cc, 0x6cd968d2, 0x6cf2bce1, 0x6d0c0ef9, + 0x6d255f1d, 0x6d3ead4b, 0x6d57f985, 0x6d7143cc, + 0x6d8a8c21, 0x6da3d283, 0x6dbd16f5, 0x6dd65976, + 0x6def9a08, 0x6e08d8ab, 0x6e221560, 0x6e3b5027, + 0x6e548902, 0x6e6dbff1, 0x6e86f4f5, 0x6ea0280e, + 0x6eb9593e, 0x6ed28885, 0x6eebb5e3, 0x6f04e15a, + 0x6f1e0aea, 0x6f373294, 0x6f505859, 0x6f697c39, + 0x6f829e35, 0x6f9bbe4e, 0x6fb4dc85, 0x6fcdf8d9, + 0x6fe7134d, 0x70002be0, 0x70194293, 0x70325767, + 0x704b6a5d, 0x70647b76, 0x707d8ab1, 0x70969811, + 0x70afa394, 0x70c8ad3d, 0x70e1b50c, 0x70fabb01, + 0x7113bf1d, 0x712cc161, 0x7145c1ce, 0x715ec064, + 0x7177bd24, 0x7190b80f, 0x71a9b124, 0x71c2a866, + 0x71db9dd4, 0x71f49170, 0x720d8339, 0x72267331, + 0x723f6159, 0x72584db0, 0x72713838, 0x728a20f1, + 0x72a307db, 0x72bbecf9, 0x72d4d049, 0x72edb1ce, + 0x73069187, 0x731f6f75, 0x73384b98, 0x735125f3, + 0x7369fe84, 0x7382d54d, 0x739baa4e, 0x73b47d89, + 0x73cd4efd, 0x73e61eab, 0x73feec94, 0x7417b8b8, + 0x74308319, 0x74494bb6, 0x74621291, 0x747ad7aa, + 0x74939b02, 0x74ac5c98, 0x74c51c6f, 0x74ddda86, + 0x74f696de, 0x750f5178, 0x75280a54, 0x7540c174, + 0x755976d7, 0x75722a7e, 0x758adc69, 0x75a38c9b, + 0x75bc3b12, 0x75d4e7cf, 0x75ed92d4, 0x76063c21, + 0x761ee3b6, 0x76378994, 0x76502dbc, 0x7668d02e, + 0x768170eb, 0x769a0ff3, 0x76b2ad47, 0x76cb48e7, + 0x76e3e2d5, 0x76fc7b10, 0x7715119a, 0x772da673, + 0x7746399b, 0x775ecb13, 0x77775adc, 0x778fe8f6, + 0x77a87561, 0x77c1001f, 0x77d98930, 0x77f21095, + 0x780a964d, 0x78231a5b, 0x783b9cbd, 0x78541d75, + 0x786c9c84, 0x788519e9, 0x789d95a6, 0x78b60fbb, + 0x78ce8828, 0x78e6feef, 0x78ff740f, 0x7917e78a, + 0x7930595f, 0x7948c990, 0x7961381d, 0x7979a506, + 0x7992104c, 0x79aa79f0, 0x79c2e1f1, 0x79db4852, + 0x79f3ad11, 0x7a0c1031, 0x7a2471b0, 0x7a3cd191, + 0x7a552fd3, 0x7a6d8c76, 0x7a85e77d, 0x7a9e40e6, + 0x7ab698b2, 0x7aceeee3, 0x7ae74378, 0x7aff9673, + 0x7b17e7d2, 0x7b303799, 0x7b4885c5, 0x7b60d259, + 0x7b791d55, 0x7b9166b9, 0x7ba9ae86, 0x7bc1f4bc, + 0x7bda395c, 0x7bf27c66, 0x7c0abddb, 0x7c22fdbb, + 0x7c3b3c07, 0x7c5378c0, 0x7c6bb3e5, 0x7c83ed78, + 0x7c9c2579, 0x7cb45be9, 0x7ccc90c7, 0x7ce4c414, + 0x7cfcf5d2, 0x7d152600, 0x7d2d549f, 0x7d4581b0, + 0x7d5dad32, 0x7d75d727, 0x7d8dff8f, 0x7da6266a, + 0x7dbe4bba, 0x7dd66f7d, 0x7dee91b6, 0x7e06b264, + 0x7e1ed188, 0x7e36ef22, 0x7e4f0b34, 0x7e6725bd, + 0x7e7f3ebd, 0x7e975636, 0x7eaf6c28, 0x7ec78093, + 0x7edf9378, 0x7ef7a4d7, 0x7f0fb4b1, 0x7f27c307, + 0x7f3fcfd8, 0x7f57db25, 0x7f6fe4ef, 0x7f87ed36, + 0x7f9ff3fb, 0x7fb7f93e, 0x7fcffcff, 0x7fe7ff40 +}; + +const Word32 mTab_4_3[512]={ + 0x32cbfd4a, 0x32eddd70, 0x330fc339, 0x3331aea3, + 0x33539fac, 0x33759652, 0x33979294, 0x33b99470, + 0x33db9be4, 0x33fda8ed, 0x341fbb8b, 0x3441d3bb, + 0x3463f17c, 0x348614cc, 0x34a83da8, 0x34ca6c10, + 0x34eca001, 0x350ed979, 0x35311877, 0x35535cfa, + 0x3575a6fe, 0x3597f683, 0x35ba4b87, 0x35dca607, + 0x35ff0603, 0x36216b78, 0x3643d665, 0x366646c7, + 0x3688bc9e, 0x36ab37e8, 0x36cdb8a2, 0x36f03ecb, + 0x3712ca62, 0x37355b64, 0x3757f1d1, 0x377a8da5, + 0x379d2ee0, 0x37bfd580, 0x37e28184, 0x380532e8, + 0x3827e9ad, 0x384aa5d0, 0x386d674f, 0x38902e2a, + 0x38b2fa5d, 0x38d5cbe9, 0x38f8a2ca, 0x391b7eff, + 0x393e6088, 0x39614761, 0x3984338a, 0x39a72501, + 0x39ca1bc4, 0x39ed17d1, 0x3a101928, 0x3a331fc6, + 0x3a562baa, 0x3a793cd2, 0x3a9c533d, 0x3abf6ee9, + 0x3ae28fd5, 0x3b05b5ff, 0x3b28e165, 0x3b4c1206, + 0x3b6f47e0, 0x3b9282f2, 0x3bb5c33a, 0x3bd908b7, + 0x3bfc5368, 0x3c1fa349, 0x3c42f85b, 0x3c66529c, + 0x3c89b209, 0x3cad16a2, 0x3cd08065, 0x3cf3ef51, + 0x3d176364, 0x3d3adc9c, 0x3d5e5af8, 0x3d81de77, + 0x3da56717, 0x3dc8f4d6, 0x3dec87b4, 0x3e101fae, + 0x3e33bcc3, 0x3e575ef2, 0x3e7b063a, 0x3e9eb298, + 0x3ec2640c, 0x3ee61a93, 0x3f09d62d, 0x3f2d96d8, + 0x3f515c93, 0x3f75275b, 0x3f98f731, 0x3fbccc11, + 0x3fe0a5fc, 0x400484ef, 0x402868ea, 0x404c51e9, + 0x40703fee, 0x409432f5, 0x40b82afd, 0x40dc2806, + 0x41002a0d, 0x41243111, 0x41483d12, 0x416c4e0d, + 0x41906401, 0x41b47eed, 0x41d89ecf, 0x41fcc3a7, + 0x4220ed72, 0x42451c30, 0x42694fde, 0x428d887d, + 0x42b1c609, 0x42d60883, 0x42fa4fe8, 0x431e9c37, + 0x4342ed70, 0x43674390, 0x438b9e96, 0x43affe82, + 0x43d46351, 0x43f8cd03, 0x441d3b95, 0x4441af08, + 0x44662758, 0x448aa487, 0x44af2690, 0x44d3ad75, + 0x44f83933, 0x451cc9c8, 0x45415f35, 0x4565f977, + 0x458a988d, 0x45af3c76, 0x45d3e531, 0x45f892bc, + 0x461d4516, 0x4641fc3e, 0x4666b832, 0x468b78f2, + 0x46b03e7c, 0x46d508cf, 0x46f9d7e9, 0x471eabca, + 0x47438470, 0x476861d9, 0x478d4406, 0x47b22af3, + 0x47d716a1, 0x47fc070e, 0x4820fc39, 0x4845f620, + 0x486af4c3, 0x488ff820, 0x48b50035, 0x48da0d03, + 0x48ff1e87, 0x492434c0, 0x49494fad, 0x496e6f4d, + 0x4993939f, 0x49b8bca2, 0x49ddea54, 0x4a031cb4, + 0x4a2853c1, 0x4a4d8f7a, 0x4a72cfde, 0x4a9814eb, + 0x4abd5ea1, 0x4ae2acfd, 0x4b080000, 0x4b2d57a8, + 0x4b52b3f3, 0x4b7814e1, 0x4b9d7a70, 0x4bc2e49f, + 0x4be8536e, 0x4c0dc6db, 0x4c333ee4, 0x4c58bb89, + 0x4c7e3cc9, 0x4ca3c2a2, 0x4cc94d14, 0x4ceedc1c, + 0x4d146fbb, 0x4d3a07ef, 0x4d5fa4b6, 0x4d854611, + 0x4daaebfd, 0x4dd09679, 0x4df64585, 0x4e1bf91f, + 0x4e41b146, 0x4e676dfa, 0x4e8d2f38, 0x4eb2f501, + 0x4ed8bf52, 0x4efe8e2b, 0x4f24618a, 0x4f4a3970, + 0x4f7015d9, 0x4f95f6c6, 0x4fbbdc36, 0x4fe1c626, + 0x5007b497, 0x502da787, 0x50539ef5, 0x50799ae1, + 0x509f9b48, 0x50c5a02a, 0x50eba985, 0x5111b75a, + 0x5137c9a6, 0x515de069, 0x5183fba2, 0x51aa1b4f, + 0x51d03f70, 0x51f66803, 0x521c9508, 0x5242c67d, + 0x5268fc62, 0x528f36b5, 0x52b57575, 0x52dbb8a2, + 0x5302003a, 0x53284c3c, 0x534e9ca8, 0x5374f17c, + 0x539b4ab7, 0x53c1a858, 0x53e80a5f, 0x540e70ca, + 0x5434db98, 0x545b4ac8, 0x5481be5a, 0x54a8364b, + 0x54ceb29c, 0x54f5334c, 0x551bb858, 0x554241c1, + 0x5568cf85, 0x558f61a3, 0x55b5f81b, 0x55dc92eb, + 0x56033212, 0x5629d590, 0x56507d63, 0x5677298a, + 0x569dda05, 0x56c48ed3, 0x56eb47f2, 0x57120562, + 0x5738c721, 0x575f8d2f, 0x5786578a, 0x57ad2633, + 0x57d3f927, 0x57fad066, 0x5821abef, 0x58488bc0, + 0x586f6fda, 0x5896583b, 0x58bd44e2, 0x58e435ce, + 0x590b2aff, 0x59322473, 0x59592229, 0x59802420, + 0x59a72a59, 0x59ce34d0, 0x59f54387, 0x5a1c567b, + 0x5a436dac, 0x5a6a8919, 0x5a91a8c1, 0x5ab8cca3, + 0x5adff4be, 0x5b072111, 0x5b2e519c, 0x5b55865e, + 0x5b7cbf54, 0x5ba3fc80, 0x5bcb3ddf, 0x5bf28371, + 0x5c19cd35, 0x5c411b2a, 0x5c686d4f, 0x5c8fc3a4, + 0x5cb71e27, 0x5cde7cd7, 0x5d05dfb4, 0x5d2d46bd, + 0x5d54b1f0, 0x5d7c214e, 0x5da394d4, 0x5dcb0c83, + 0x5df28859, 0x5e1a0856, 0x5e418c78, 0x5e6914be, + 0x5e90a129, 0x5eb831b7, 0x5edfc667, 0x5f075f38, + 0x5f2efc29, 0x5f569d3a, 0x5f7e426a, 0x5fa5ebb7, + 0x5fcd9921, 0x5ff54aa8, 0x601d004a, 0x6044ba06, + 0x606c77dc, 0x609439ca, 0x60bbffd0, 0x60e3c9ee, + 0x610b9821, 0x61336a6a, 0x615b40c8, 0x61831b39, + 0x61aaf9bd, 0x61d2dc53, 0x61fac2fa, 0x6222adb2, + 0x624a9c79, 0x62728f4f, 0x629a8633, 0x62c28123, + 0x62ea8020, 0x63128329, 0x633a8a3c, 0x63629559, + 0x638aa47f, 0x63b2b7ad, 0x63dacee2, 0x6402ea1e, + 0x642b0960, 0x64532ca6, 0x647b53f1, 0x64a37f3f, + 0x64cbae8f, 0x64f3e1e2, 0x651c1935, 0x65445488, + 0x656c93db, 0x6594d72c, 0x65bd1e7b, 0x65e569c7, + 0x660db90f, 0x66360c53, 0x665e6391, 0x6686bec9, + 0x66af1dfa, 0x66d78123, 0x66ffe844, 0x6728535b, + 0x6750c268, 0x6779356b, 0x67a1ac62, 0x67ca274c, + 0x67f2a629, 0x681b28f9, 0x6843afb9, 0x686c3a6a, + 0x6894c90b, 0x68bd5b9b, 0x68e5f219, 0x690e8c84, + 0x69372add, 0x695fcd21, 0x69887350, 0x69b11d6a, + 0x69d9cb6d, 0x6a027d5a, 0x6a2b332f, 0x6a53eceb, + 0x6a7caa8d, 0x6aa56c16, 0x6ace3184, 0x6af6fad6, + 0x6b1fc80c, 0x6b489925, 0x6b716e20, 0x6b9a46fd, + 0x6bc323bb, 0x6bec0458, 0x6c14e8d5, 0x6c3dd130, + 0x6c66bd69, 0x6c8fad80, 0x6cb8a172, 0x6ce19940, + 0x6d0a94e9, 0x6d33946d, 0x6d5c97ca, 0x6d859eff, + 0x6daeaa0d, 0x6dd7b8f1, 0x6e00cbad, 0x6e29e23e, + 0x6e52fca4, 0x6e7c1adf, 0x6ea53cee, 0x6ece62cf, + 0x6ef78c83, 0x6f20ba09, 0x6f49eb5f, 0x6f732085, + 0x6f9c597b, 0x6fc59640, 0x6feed6d3, 0x70181b33, + 0x70416360, 0x706aaf59, 0x7093ff1d, 0x70bd52ab, + 0x70e6aa04, 0x71100525, 0x7139640f, 0x7162c6c1, + 0x718c2d3a, 0x71b5977a, 0x71df057f, 0x72087749, + 0x7231ecd8, 0x725b662a, 0x7284e33f, 0x72ae6417, + 0x72d7e8b0, 0x7301710a, 0x732afd24, 0x73548cfe, + 0x737e2097, 0x73a7b7ee, 0x73d15303, 0x73faf1d5, + 0x74249462, 0x744e3aac, 0x7477e4b0, 0x74a1926e, + 0x74cb43e6, 0x74f4f917, 0x751eb201, 0x75486ea1, + 0x75722ef9, 0x759bf307, 0x75c5baca, 0x75ef8642, + 0x7619556f, 0x7643284f, 0x766cfee2, 0x7696d928, + 0x76c0b71f, 0x76ea98c7, 0x77147e20, 0x773e6728, + 0x776853df, 0x77924445, 0x77bc3858, 0x77e63019, + 0x78102b85, 0x783a2a9e, 0x78642d62, 0x788e33d1, + 0x78b83de9, 0x78e24bab, 0x790c5d15, 0x79367228, + 0x79608ae1, 0x798aa742, 0x79b4c748, 0x79deeaf4, + 0x7a091245, 0x7a333d3a, 0x7a5d6bd2, 0x7a879e0e, + 0x7ab1d3ec, 0x7adc0d6b, 0x7b064a8c, 0x7b308b4d, + 0x7b5acfae, 0x7b8517ae, 0x7baf634c, 0x7bd9b289, + 0x7c040563, 0x7c2e5bda, 0x7c58b5ec, 0x7c83139b, + 0x7cad74e4, 0x7cd7d9c7, 0x7d024244, 0x7d2cae5a, + 0x7d571e09, 0x7d81914f, 0x7dac082d, 0x7dd682a1, + 0x7e0100ac, 0x7e2b824b, 0x7e560780, 0x7e809048, + 0x7eab1ca5, 0x7ed5ac94, 0x7f004015, 0x7f2ad729, + 0x7f5571cd, 0x7f801003, 0x7faab1c8, 0x7fd5571d +}; + + +const Word32 invSBF[24] = { + 0x3FFD34FC, 0x2D3F8000, 0x24F18C7E, 0x1FFE9A7E, + 0x1C9DF10C, 0x1A1F851A, 0x182FE994, 0x169FC000, + 0x15542AAA, 0x143C31C2, 0x134B1B6C, 0x127920BE, + 0x11BF2FCC, 0x111A749E, 0x1085FC42, 0x0FFFA7BE, + 0x0F855818, 0x0F14EE56, 0x0EAE6A78, 0x0E4EF886, + 0x0DF69880, 0x0DA49568, 0x0D578542, 0x0D101D0C +}; + +const Word16 pow2tominusNover16[17] = { + 0x7fff, 0x7a93, 0x7560, 0x7066, + 0x6ba2, 0x6712, 0x62b4, 0x5e84, + 0x5a82, 0x56ac, 0x52ff, 0x4f7b, + 0x4c1c, 0x48e2, 0x45cb, 0x42d5, + 0x4000 +}; + +const Word16 sideInfoTabLong[MAX_SFB_LONG + 1] = { + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14 +}; + +const Word16 sideInfoTabShort[MAX_SFB_SHORT + 1] = { + 7, 7, 7, 7, 7, 7, 7, 10, 10, + 10, 10, 10, 10, 10, 13, 13 +}; + +Word32 specExpMantTableComb_enc[4][14] = +{ + {0x40000000, 0x50a28be6, 0x6597fa95, 0x40000000, + 0x50a28be6, 0x6597fa95, 0x40000000, 0x50a28be6, + 0x6597fa95, 0x40000000, 0x50a28be6, 0x6597fa95, + 0x40000000, 0x50a28be6}, + + {0x4c1bf829, 0x5fe4435e, 0x78d0df9c, 0x4c1bf829, + 0x5fe4435e, 0x78d0df9c, 0x4c1bf829, 0x5fe4435e, + 0x78d0df9c, 0x4c1bf829, 0x5fe4435e, 0x78d0df9c, + 0x4c1bf829, 0x5fe4435e}, + + {0x5a82799a, 0x7208f81d, 0x47d66b0f, 0x5a82799a, + 0x7208f81d, 0x47d66b0f, 0x5a82799a, 0x7208f81d, + 0x47d66b0f, 0x5a82799a, 0x7208f81d, 0x47d66b0f, + 0x5a82799a, 0x7208f81d}, + + {0x6ba27e65, 0x43ce3e4b, 0x556e0424, 0x6ba27e65, + 0x43ce3e4b, 0x556e0424, 0x6ba27e65, 0x43ce3e4b, + 0x556e0424, 0x6ba27e65, 0x43ce3e4b, 0x556e0424, + 0x6ba27e65, 0x43ce3e4b} +}; + +const UWord8 specExpTableComb_enc[4][14] = +{ + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18}, + {1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19} +}; + +const Word16 quantBorders[4][4] = { + /* pow(1.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */ + {0x0400, 0x0ee7, 0x1c86, 0x2c0d}, + /* pow(2.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */ + {0x04c2, 0x11b9, 0x21eb, 0x3463}, + /* pow(3.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */ + {0x05a8, 0x1514, 0x2856, 0x3e4c}, + /* pow(4.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */ + {0x06ba, 0x1911, 0x2ff8, 0x4a16}, +}; + +const Word16 quantRecon[4][3] = { + {0x0800, 0x1429, 0x229d}, + {0x0983, 0x17f9, 0x292a}, + {0x0b50, 0x1c82, 0x30f4}, + {0x0d74, 0x21e7, 0x3a37}, +}; + +const int sampRateTab[NUM_SAMPLE_RATES] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000 +}; + + +const int rates[8] = { + 160, 240, 320, 400, 480, 560, 640, 0 +}; + +const int BandwithCoefTab[8][NUM_SAMPLE_RATES] = { + { 7000, 7000, 4666, 3500, 3500, 2800, 2800, 2800, 2800, 2000, 2000, 2000}, + {12000, 12000, 8000, 6000, 6000, 6000, 4000, 4000, 4000, 3000, 3000, 3000}, + {18000, 18000, 12000, 9000, 9000, 9000, 7000, 7000, 7000, 5000, 5000, 5000}, + {20000, 20000, 16000, 12000, 12000, 12000, 9000, 9000, 9000, 6000, 6000, 6000}, + {20000, 20000, 18666, 14000, 14000, 14000, 10000, 10000, 10000, 7000, 7000, 7000}, + {20000, 20000, 20000, 16000, 16000, 16000, 12000, 12000, 12000, 8000, 8000, 8000}, + {20000, 20000, 20000, 20000, 20000, 20000, 15000, 15000, 15000, 10000, 10000, 10000}, + {20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000} +}; + + +/* total number of scale factor bands in one window */ +const UWord8 sfBandTotalShort[NUM_SAMPLE_RATES] = { + 12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15 +}; + +const UWord8 sfBandTotalLong[NUM_SAMPLE_RATES] = { + 41, 41, 47, 49, 49, 51, 47, 47, 43, 43, 43, 40 +}; + +/* scale factor band tables */ +const int sfBandTabShortOffset[NUM_SAMPLE_RATES] = {0, 0, 0, 13, 13, 13, 28, 28, 44, 44, 44, 60}; + +const short sfBandTabShort[76] = { + /* short block 64, 88, 96 kHz [13] */ + 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, 128, + + /* short block 32, 44, 48 kHz [15] */ + 0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112, 128, + + /* short block 22, 24 kHz [16] */ + 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92, 108, 128, + + /* short block 11, 12, 16 kHz [16] */ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 60, 72, 88, 108, 128, + + /* short block 8 kHz [16] */ + 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 60, 72, 88, 108, 128 +}; + +const int sfBandTabLongOffset[NUM_SAMPLE_RATES] = {0, 0, 42, 90, 90, 140, 192, 192, 240, 240, 240, 284}; + +const short sfBandTabLong[325] = { + /* long block 88, 96 kHz [42] */ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 156, 172, 188, 212, + 240, 276, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, + + /* long block 64 kHz [48] */ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64, + 72, 80, 88, 100, 112, 124, 140, 156, 172, 192, 216, 240, 268, 304, 344, 384, + 424, 464, 504, 544, 584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 984, 1024, + + /* long block 44, 48 kHz [50] */ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 88, + 96, 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384, 416, 448, + 480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 1024, + + /* long block 32 kHz [52] */ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 88, 96, + 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, + 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960, 992, 1024, + + /* long block 22, 24 kHz [48] */ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, 68, 76, + 84, 92, 100, 108, 116, 124, 136, 148, 160, 172, 188, 204, 220, 240, 260, 284, + 308, 336, 364, 396, 432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960, 1024, + + /* long block 11, 12, 16 kHz [44] */ + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 100, 112, 124, + 136, 148, 160, 172, 184, 196, 212, 228, 244, 260, 280, 300, 320, 344, 368, + 396, 424, 456, 492, 532, 572, 616, 664, 716, 772, 832, 896, 960, 1024, + + /* long block 8 kHz [41] */ + 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, + 172, 188, 204, 220, 236, 252, 268, 288, 308, 328, 348, 372, 396, 420, + 448, 476, 508, 544, 580, 620, 664, 712, 764, 820, 880, 944, 1024 +}; + +/* + these tables are used only for counting and + are stored in packed format +*/ +const UWord16 huff_ltab1_2[3][3][3][3]= +{ + { + { + {0x0b09,0x0907,0x0b09}, + {0x0a08,0x0706,0x0a08}, + {0x0b09,0x0908,0x0b09} + }, + { + {0x0a08,0x0706,0x0a07}, + {0x0706,0x0505,0x0706}, + {0x0907,0x0706,0x0a08} + }, + { + {0x0b09,0x0907,0x0b08}, + {0x0908,0x0706,0x0908}, + {0x0b09,0x0907,0x0b09} + } + }, + { + { + {0x0908,0x0706,0x0907}, + {0x0706,0x0505,0x0706}, + {0x0907,0x0706,0x0908} + }, + { + {0x0706,0x0505,0x0706}, + {0x0505,0x0103,0x0505}, + {0x0706,0x0505,0x0706} + }, + { + {0x0908,0x0706,0x0907}, + {0x0706,0x0505,0x0706}, + {0x0908,0x0706,0x0908} + } + }, + { + { + {0x0b09,0x0907,0x0b09}, + {0x0908,0x0706,0x0908}, + {0x0b08,0x0907,0x0b09} + }, + { + {0x0a08,0x0706,0x0907}, + {0x0706,0x0504,0x0706}, + {0x0908,0x0706,0x0a07} + }, + { + {0x0b09,0x0907,0x0b09}, + {0x0a07,0x0706,0x0908}, + {0x0b09,0x0907,0x0b09} + } + } +}; + + +const UWord16 huff_ltab3_4[3][3][3][3]= +{ + { + { + {0x0104,0x0405,0x0808}, + {0x0405,0x0504,0x0808}, + {0x0909,0x0908,0x0a0b} + }, + { + {0x0405,0x0605,0x0908}, + {0x0605,0x0604,0x0908}, + {0x0908,0x0907,0x0a0a} + }, + { + {0x0909,0x0a08,0x0d0b}, + {0x0908,0x0908,0x0b0a}, + {0x0b0b,0x0a0a,0x0c0b} + } + }, + { + { + {0x0404,0x0605,0x0a08}, + {0x0604,0x0704,0x0a08}, + {0x0a08,0x0a08,0x0c0a} + }, + { + {0x0504,0x0704,0x0b08}, + {0x0604,0x0704,0x0a07}, + {0x0908,0x0907,0x0b09} + }, + { + {0x0908,0x0a08,0x0d0a}, + {0x0807,0x0907,0x0c09}, + {0x0a0a,0x0b09,0x0c0a} + } + }, + { + { + {0x0808,0x0a08,0x0f0b}, + {0x0908,0x0b07,0x0f0a}, + {0x0d0b,0x0e0a,0x100c} + }, + { + {0x0808,0x0a07,0x0e0a}, + {0x0907,0x0a07,0x0e09}, + {0x0c0a,0x0c09,0x0f0b} + }, + { + {0x0b0b,0x0c0a,0x100c}, + {0x0a0a,0x0b09,0x0f0b}, + {0x0c0b,0x0c0a,0x0f0b} + } + } +}; + +const UWord16 huff_ltab5_6[9][9]= +{ + {0x0d0b,0x0c0a,0x0b09,0x0b09,0x0a09,0x0b09,0x0b09,0x0c0a,0x0d0b}, + {0x0c0a,0x0b09,0x0a08,0x0907,0x0807,0x0907,0x0a08,0x0b09,0x0c0a}, + {0x0c09,0x0a08,0x0906,0x0806,0x0706,0x0806,0x0906,0x0a08,0x0b09}, + {0x0b09,0x0907,0x0806,0x0504,0x0404,0x0504,0x0806,0x0907,0x0b09}, + {0x0a09,0x0807,0x0706,0x0404,0x0104,0x0404,0x0706,0x0807,0x0b09}, + {0x0b09,0x0907,0x0806,0x0504,0x0404,0x0504,0x0806,0x0907,0x0b09}, + {0x0b09,0x0a08,0x0906,0x0806,0x0706,0x0806,0x0906,0x0a08,0x0b09}, + {0x0c0a,0x0b09,0x0a08,0x0907,0x0807,0x0907,0x0a07,0x0b08,0x0c0a}, + {0x0d0b,0x0c0a,0x0c09,0x0b09,0x0a09,0x0a09,0x0b09,0x0c0a,0x0d0b} +}; + +const UWord16 huff_ltab7_8[8][8]= +{ + {0x0105,0x0304,0x0605,0x0706,0x0807,0x0908,0x0a09,0x0b0a}, + {0x0304,0x0403,0x0604,0x0705,0x0806,0x0807,0x0907,0x0908}, + {0x0605,0x0604,0x0704,0x0805,0x0806,0x0907,0x0907,0x0a08}, + {0x0706,0x0705,0x0805,0x0806,0x0906,0x0907,0x0a08,0x0a08}, + {0x0807,0x0806,0x0906,0x0906,0x0a07,0x0a07,0x0a08,0x0b09}, + {0x0908,0x0807,0x0906,0x0907,0x0a07,0x0a08,0x0b08,0x0b0a}, + {0x0a09,0x0907,0x0907,0x0a08,0x0a08,0x0b08,0x0c09,0x0c09}, + {0x0b0a,0x0a08,0x0a08,0x0a08,0x0b09,0x0b09,0x0c09,0x0c0a} +}; + +const UWord16 huff_ltab9_10[13][13]= +{ + {0x0106,0x0305,0x0606,0x0806,0x0907,0x0a08,0x0a09,0x0b0a,0x0b0a,0x0c0a,0x0c0b,0x0d0b,0x0d0c}, + {0x0305,0x0404,0x0604,0x0705,0x0806,0x0807,0x0907,0x0a08,0x0a08,0x0a09,0x0b0a,0x0c0a,0x0c0b}, + {0x0606,0x0604,0x0705,0x0805,0x0806,0x0906,0x0a07,0x0a08,0x0a08,0x0b09,0x0c09,0x0c0a,0x0c0a}, + {0x0806,0x0705,0x0805,0x0905,0x0906,0x0a07,0x0a07,0x0b08,0x0b08,0x0b09,0x0c09,0x0c0a,0x0d0a}, + {0x0907,0x0806,0x0906,0x0906,0x0a06,0x0a07,0x0b07,0x0b08,0x0b08,0x0c09,0x0c09,0x0c0a,0x0d0a}, + {0x0a08,0x0907,0x0906,0x0a07,0x0b07,0x0b07,0x0b08,0x0c08,0x0b08,0x0c09,0x0c0a,0x0d0a,0x0d0b}, + {0x0b09,0x0907,0x0a07,0x0b07,0x0b07,0x0b08,0x0c08,0x0c09,0x0c09,0x0c09,0x0d0a,0x0d0a,0x0d0b}, + {0x0b09,0x0a08,0x0a08,0x0b08,0x0b08,0x0c08,0x0c09,0x0d09,0x0d09,0x0d0a,0x0d0a,0x0d0b,0x0d0b}, + {0x0b09,0x0a08,0x0a08,0x0b08,0x0b08,0x0b08,0x0c09,0x0c09,0x0d0a,0x0d0a,0x0e0a,0x0d0b,0x0e0b}, + {0x0b0a,0x0a09,0x0b09,0x0b09,0x0c09,0x0c09,0x0c09,0x0c0a,0x0d0a,0x0d0a,0x0e0b,0x0e0b,0x0e0c}, + {0x0c0a,0x0b09,0x0b09,0x0c09,0x0c09,0x0c0a,0x0d0a,0x0d0a,0x0d0a,0x0e0b,0x0e0b,0x0e0b,0x0f0c}, + {0x0c0b,0x0b0a,0x0c09,0x0c0a,0x0c0a,0x0d0a,0x0d0a,0x0d0a,0x0d0b,0x0e0b,0x0e0b,0x0f0b,0x0f0c}, + {0x0d0b,0x0c0a,0x0c0a,0x0c0a,0x0d0a,0x0d0a,0x0d0a,0x0d0b,0x0e0b,0x0e0c,0x0e0c,0x0e0c,0x0f0c} +}; + +const UWord16 huff_ltab11[17][17]= +{ + {0x0004,0x0005,0x0006,0x0007,0x0008,0x0008,0x0009,0x000a,0x000a,0x000a,0x000b,0x000b,0x000c,0x000b,0x000c,0x000c,0x000a}, + {0x0005,0x0004,0x0005,0x0006,0x0007,0x0007,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000b,0x0008}, + {0x0006,0x0005,0x0005,0x0006,0x0007,0x0007,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008}, + {0x0007,0x0006,0x0006,0x0006,0x0007,0x0007,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008}, + {0x0008,0x0007,0x0007,0x0007,0x0007,0x0008,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008}, + {0x0008,0x0007,0x0007,0x0007,0x0007,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008}, + {0x0009,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x0008}, + {0x0009,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x0008}, + {0x000a,0x0009,0x0008,0x0008,0x0009,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x0008}, + {0x000a,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x0008}, + {0x000b,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000a,0x000b,0x000b,0x0008}, + {0x000b,0x000a,0x0009,0x0009,0x000a,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x0008}, + {0x000b,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x0009}, + {0x000b,0x000a,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x0009}, + {0x000b,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x0009}, + {0x000c,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x000c,0x000c,0x0009}, + {0x0009,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0009,0x0005} +}; + +const UWord16 huff_ltabscf[121]= +{ + 0x0012, + 0x0012, + 0x0012, + 0x0012, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0012, + 0x0013, + 0x0012, + 0x0011, + 0x0011, + 0x0010, + 0x0011, + 0x0010, + 0x0010, + 0x0010, + 0x0010, + 0x000f, + 0x000f, + 0x000e, + 0x000e, + 0x000e, + 0x000e, + 0x000e, + 0x000e, + 0x000d, + 0x000d, + 0x000c, + 0x000c, + 0x000c, + 0x000b, + 0x000c, + 0x000b, + 0x000a, + 0x000a, + 0x000a, + 0x0009, + 0x0009, + 0x0008, + 0x0008, + 0x0008, + 0x0007, + 0x0006, + 0x0006, + 0x0005, + 0x0004, + 0x0003, + 0x0001, + 0x0004, + 0x0004, + 0x0005, + 0x0006, + 0x0006, + 0x0007, + 0x0007, + 0x0008, + 0x0008, + 0x0009, + 0x0009, + 0x000a, + 0x000a, + 0x000a, + 0x000b, + 0x000b, + 0x000b, + 0x000b, + 0x000c, + 0x000c, + 0x000d, + 0x000d, + 0x000d, + 0x000e, + 0x000e, + 0x0010, + 0x000f, + 0x0010, + 0x000f, + 0x0012, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013, + 0x0013 +}; + + +const UWord16 huff_ctab1[3][3][3][3]= +{ + { + { + {0x07f8,0x01f1,0x07fd}, + {0x03f5,0x0068,0x03f0}, + {0x07f7,0x01ec,0x07f5} + }, + { + {0x03f1,0x0072,0x03f4}, + {0x0074,0x0011,0x0076}, + {0x01eb,0x006c,0x03f6} + }, + { + {0x07fc,0x01e1,0x07f1}, + {0x01f0,0x0061,0x01f6}, + {0x07f2,0x01ea,0x07fb} + } + }, + { + { + {0x01f2,0x0069,0x01ed}, + {0x0077,0x0017,0x006f}, + {0x01e6,0x0064,0x01e5} + }, + { + {0x0067,0x0015,0x0062}, + {0x0012,0x0000,0x0014}, + {0x0065,0x0016,0x006d} + }, + { + {0x01e9,0x0063,0x01e4}, + {0x006b,0x0013,0x0071}, + {0x01e3,0x0070,0x01f3} + } + }, + { + { + {0x07fe,0x01e7,0x07f3}, + {0x01ef,0x0060,0x01ee}, + {0x07f0,0x01e2,0x07fa} + }, + { + {0x03f3,0x006a,0x01e8}, + {0x0075,0x0010,0x0073}, + {0x01f4,0x006e,0x03f7} + }, + { + {0x07f6,0x01e0,0x07f9}, + {0x03f2,0x0066,0x01f5}, + {0x07ff,0x01f7,0x07f4} + } + } +}; + +const UWord16 huff_ctab2[3][3][3][3]= +{ + { + { + {0x01f3,0x006f,0x01fd}, + {0x00eb,0x0023,0x00ea}, + {0x01f7,0x00e8,0x01fa} + }, + { + {0x00f2,0x002d,0x0070}, + {0x0020,0x0006,0x002b}, + {0x006e,0x0028,0x00e9} + }, + { + {0x01f9,0x0066,0x00f8}, + {0x00e7,0x001b,0x00f1}, + {0x01f4,0x006b,0x01f5} + } + }, + { + { + {0x00ec,0x002a,0x006c}, + {0x002c,0x000a,0x0027}, + {0x0067,0x001a,0x00f5} + }, + { + {0x0024,0x0008,0x001f}, + {0x0009,0x0000,0x0007}, + {0x001d,0x000b,0x0030} + }, + { + {0x00ef,0x001c,0x0064}, + {0x001e,0x000c,0x0029}, + {0x00f3,0x002f,0x00f0} + } + }, + { + { + {0x01fc,0x0071,0x01f2}, + {0x00f4,0x0021,0x00e6}, + {0x00f7,0x0068,0x01f8} + }, + { + {0x00ee,0x0022,0x0065}, + {0x0031,0x0002,0x0026}, + {0x00ed,0x0025,0x006a} + }, + { + {0x01fb,0x0072,0x01fe}, + {0x0069,0x002e,0x00f6}, + {0x01ff,0x006d,0x01f6} + } + } +}; + +const UWord16 huff_ctab3[3][3][3][3]= +{ + { + { + {0x0000,0x0009,0x00ef}, + {0x000b,0x0019,0x00f0}, + {0x01eb,0x01e6,0x03f2} + }, + { + {0x000a,0x0035,0x01ef}, + {0x0034,0x0037,0x01e9}, + {0x01ed,0x01e7,0x03f3} + }, + { + {0x01ee,0x03ed,0x1ffa}, + {0x01ec,0x01f2,0x07f9}, + {0x07f8,0x03f8,0x0ff8} + } + }, + { + { + {0x0008,0x0038,0x03f6}, + {0x0036,0x0075,0x03f1}, + {0x03eb,0x03ec,0x0ff4} + }, + { + {0x0018,0x0076,0x07f4}, + {0x0039,0x0074,0x03ef}, + {0x01f3,0x01f4,0x07f6} + }, + { + {0x01e8,0x03ea,0x1ffc}, + {0x00f2,0x01f1,0x0ffb}, + {0x03f5,0x07f3,0x0ffc} + } + }, + { + { + {0x00ee,0x03f7,0x7ffe}, + {0x01f0,0x07f5,0x7ffd}, + {0x1ffb,0x3ffa,0xffff} + }, + { + {0x00f1,0x03f0,0x3ffc}, + {0x01ea,0x03ee,0x3ffb}, + {0x0ff6,0x0ffa,0x7ffc} + }, + { + {0x07f2,0x0ff5,0xfffe}, + {0x03f4,0x07f7,0x7ffb}, + {0x0ff7,0x0ff9,0x7ffa} + } + } +}; + +const UWord16 huff_ctab4[3][3][3][3]= +{ + { + { + {0x0007,0x0016,0x00f6}, + {0x0018,0x0008,0x00ef}, + {0x01ef,0x00f3,0x07f8} + }, + { + {0x0019,0x0017,0x00ed}, + {0x0015,0x0001,0x00e2}, + {0x00f0,0x0070,0x03f0} + }, + { + {0x01ee,0x00f1,0x07fa}, + {0x00ee,0x00e4,0x03f2}, + {0x07f6,0x03ef,0x07fd} + } + }, + { + { + {0x0005,0x0014,0x00f2}, + {0x0009,0x0004,0x00e5}, + {0x00f4,0x00e8,0x03f4} + }, + { + {0x0006,0x0002,0x00e7}, + {0x0003,0x0000,0x006b}, + {0x00e3,0x0069,0x01f3} + }, + { + {0x00eb,0x00e6,0x03f6}, + {0x006e,0x006a,0x01f4}, + {0x03ec,0x01f0,0x03f9} + } + }, + { + { + {0x00f5,0x00ec,0x07fb}, + {0x00ea,0x006f,0x03f7}, + {0x07f9,0x03f3,0x0fff} + }, + { + {0x00e9,0x006d,0x03f8}, + {0x006c,0x0068,0x01f5}, + {0x03ee,0x01f2,0x07f4} + }, + { + {0x07f7,0x03f1,0x0ffe}, + {0x03ed,0x01f1,0x07f5}, + {0x07fe,0x03f5,0x07fc} + } + } +}; +const UWord16 huff_ctab5[9][9]= +{ + {0x1fff,0x0ff7,0x07f4,0x07e8,0x03f1,0x07ee,0x07f9,0x0ff8,0x1ffd}, + {0x0ffd,0x07f1,0x03e8,0x01e8,0x00f0,0x01ec,0x03ee,0x07f2,0x0ffa}, + {0x0ff4,0x03ef,0x01f2,0x00e8,0x0070,0x00ec,0x01f0,0x03ea,0x07f3}, + {0x07eb,0x01eb,0x00ea,0x001a,0x0008,0x0019,0x00ee,0x01ef,0x07ed}, + {0x03f0,0x00f2,0x0073,0x000b,0x0000,0x000a,0x0071,0x00f3,0x07e9}, + {0x07ef,0x01ee,0x00ef,0x0018,0x0009,0x001b,0x00eb,0x01e9,0x07ec}, + {0x07f6,0x03eb,0x01f3,0x00ed,0x0072,0x00e9,0x01f1,0x03ed,0x07f7}, + {0x0ff6,0x07f0,0x03e9,0x01ed,0x00f1,0x01ea,0x03ec,0x07f8,0x0ff9}, + {0x1ffc,0x0ffc,0x0ff5,0x07ea,0x03f3,0x03f2,0x07f5,0x0ffb,0x1ffe} +}; + +const UWord16 huff_ctab6[9][9]= +{ + {0x07fe,0x03fd,0x01f1,0x01eb,0x01f4,0x01ea,0x01f0,0x03fc,0x07fd}, + {0x03f6,0x01e5,0x00ea,0x006c,0x0071,0x0068,0x00f0,0x01e6,0x03f7}, + {0x01f3,0x00ef,0x0032,0x0027,0x0028,0x0026,0x0031,0x00eb,0x01f7}, + {0x01e8,0x006f,0x002e,0x0008,0x0004,0x0006,0x0029,0x006b,0x01ee}, + {0x01ef,0x0072,0x002d,0x0002,0x0000,0x0003,0x002f,0x0073,0x01fa}, + {0x01e7,0x006e,0x002b,0x0007,0x0001,0x0005,0x002c,0x006d,0x01ec}, + {0x01f9,0x00ee,0x0030,0x0024,0x002a,0x0025,0x0033,0x00ec,0x01f2}, + {0x03f8,0x01e4,0x00ed,0x006a,0x0070,0x0069,0x0074,0x00f1,0x03fa}, + {0x07ff,0x03f9,0x01f6,0x01ed,0x01f8,0x01e9,0x01f5,0x03fb,0x07fc} +}; + +const UWord16 huff_ctab7[8][8]= +{ + {0x0000,0x0005,0x0037,0x0074,0x00f2,0x01eb,0x03ed,0x07f7}, + {0x0004,0x000c,0x0035,0x0071,0x00ec,0x00ee,0x01ee,0x01f5}, + {0x0036,0x0034,0x0072,0x00ea,0x00f1,0x01e9,0x01f3,0x03f5}, + {0x0073,0x0070,0x00eb,0x00f0,0x01f1,0x01f0,0x03ec,0x03fa}, + {0x00f3,0x00ed,0x01e8,0x01ef,0x03ef,0x03f1,0x03f9,0x07fb}, + {0x01ed,0x00ef,0x01ea,0x01f2,0x03f3,0x03f8,0x07f9,0x07fc}, + {0x03ee,0x01ec,0x01f4,0x03f4,0x03f7,0x07f8,0x0ffd,0x0ffe}, + {0x07f6,0x03f0,0x03f2,0x03f6,0x07fa,0x07fd,0x0ffc,0x0fff} +}; + +const UWord16 huff_ctab8[8][8]= +{ + {0x000e,0x0005,0x0010,0x0030,0x006f,0x00f1,0x01fa,0x03fe}, + {0x0003,0x0000,0x0004,0x0012,0x002c,0x006a,0x0075,0x00f8}, + {0x000f,0x0002,0x0006,0x0014,0x002e,0x0069,0x0072,0x00f5}, + {0x002f,0x0011,0x0013,0x002a,0x0032,0x006c,0x00ec,0x00fa}, + {0x0071,0x002b,0x002d,0x0031,0x006d,0x0070,0x00f2,0x01f9}, + {0x00ef,0x0068,0x0033,0x006b,0x006e,0x00ee,0x00f9,0x03fc}, + {0x01f8,0x0074,0x0073,0x00ed,0x00f0,0x00f6,0x01f6,0x01fd}, + {0x03fd,0x00f3,0x00f4,0x00f7,0x01f7,0x01fb,0x01fc,0x03ff} +}; + +const UWord16 huff_ctab9[13][13]= +{ + {0x0000,0x0005,0x0037,0x00e7,0x01de,0x03ce,0x03d9,0x07c8,0x07cd,0x0fc8,0x0fdd,0x1fe4,0x1fec}, + {0x0004,0x000c,0x0035,0x0072,0x00ea,0x00ed,0x01e2,0x03d1,0x03d3,0x03e0,0x07d8,0x0fcf,0x0fd5}, + {0x0036,0x0034,0x0071,0x00e8,0x00ec,0x01e1,0x03cf,0x03dd,0x03db,0x07d0,0x0fc7,0x0fd4,0x0fe4}, + {0x00e6,0x0070,0x00e9,0x01dd,0x01e3,0x03d2,0x03dc,0x07cc,0x07ca,0x07de,0x0fd8,0x0fea,0x1fdb}, + {0x01df,0x00eb,0x01dc,0x01e6,0x03d5,0x03de,0x07cb,0x07dd,0x07dc,0x0fcd,0x0fe2,0x0fe7,0x1fe1}, + {0x03d0,0x01e0,0x01e4,0x03d6,0x07c5,0x07d1,0x07db,0x0fd2,0x07e0,0x0fd9,0x0feb,0x1fe3,0x1fe9}, + {0x07c4,0x01e5,0x03d7,0x07c6,0x07cf,0x07da,0x0fcb,0x0fda,0x0fe3,0x0fe9,0x1fe6,0x1ff3,0x1ff7}, + {0x07d3,0x03d8,0x03e1,0x07d4,0x07d9,0x0fd3,0x0fde,0x1fdd,0x1fd9,0x1fe2,0x1fea,0x1ff1,0x1ff6}, + {0x07d2,0x03d4,0x03da,0x07c7,0x07d7,0x07e2,0x0fce,0x0fdb,0x1fd8,0x1fee,0x3ff0,0x1ff4,0x3ff2}, + {0x07e1,0x03df,0x07c9,0x07d6,0x0fca,0x0fd0,0x0fe5,0x0fe6,0x1feb,0x1fef,0x3ff3,0x3ff4,0x3ff5}, + {0x0fe0,0x07ce,0x07d5,0x0fc6,0x0fd1,0x0fe1,0x1fe0,0x1fe8,0x1ff0,0x3ff1,0x3ff8,0x3ff6,0x7ffc}, + {0x0fe8,0x07df,0x0fc9,0x0fd7,0x0fdc,0x1fdc,0x1fdf,0x1fed,0x1ff5,0x3ff9,0x3ffb,0x7ffd,0x7ffe}, + {0x1fe7,0x0fcc,0x0fd6,0x0fdf,0x1fde,0x1fda,0x1fe5,0x1ff2,0x3ffa,0x3ff7,0x3ffc,0x3ffd,0x7fff} +}; + +const UWord16 huff_ctab10[13][13]= +{ + {0x0022,0x0008,0x001d,0x0026,0x005f,0x00d3,0x01cf,0x03d0,0x03d7,0x03ed,0x07f0,0x07f6,0x0ffd}, + {0x0007,0x0000,0x0001,0x0009,0x0020,0x0054,0x0060,0x00d5,0x00dc,0x01d4,0x03cd,0x03de,0x07e7}, + {0x001c,0x0002,0x0006,0x000c,0x001e,0x0028,0x005b,0x00cd,0x00d9,0x01ce,0x01dc,0x03d9,0x03f1}, + {0x0025,0x000b,0x000a,0x000d,0x0024,0x0057,0x0061,0x00cc,0x00dd,0x01cc,0x01de,0x03d3,0x03e7}, + {0x005d,0x0021,0x001f,0x0023,0x0027,0x0059,0x0064,0x00d8,0x00df,0x01d2,0x01e2,0x03dd,0x03ee}, + {0x00d1,0x0055,0x0029,0x0056,0x0058,0x0062,0x00ce,0x00e0,0x00e2,0x01da,0x03d4,0x03e3,0x07eb}, + {0x01c9,0x005e,0x005a,0x005c,0x0063,0x00ca,0x00da,0x01c7,0x01ca,0x01e0,0x03db,0x03e8,0x07ec}, + {0x01e3,0x00d2,0x00cb,0x00d0,0x00d7,0x00db,0x01c6,0x01d5,0x01d8,0x03ca,0x03da,0x07ea,0x07f1}, + {0x01e1,0x00d4,0x00cf,0x00d6,0x00de,0x00e1,0x01d0,0x01d6,0x03d1,0x03d5,0x03f2,0x07ee,0x07fb}, + {0x03e9,0x01cd,0x01c8,0x01cb,0x01d1,0x01d7,0x01df,0x03cf,0x03e0,0x03ef,0x07e6,0x07f8,0x0ffa}, + {0x03eb,0x01dd,0x01d3,0x01d9,0x01db,0x03d2,0x03cc,0x03dc,0x03ea,0x07ed,0x07f3,0x07f9,0x0ff9}, + {0x07f2,0x03ce,0x01e4,0x03cb,0x03d8,0x03d6,0x03e2,0x03e5,0x07e8,0x07f4,0x07f5,0x07f7,0x0ffb}, + {0x07fa,0x03ec,0x03df,0x03e1,0x03e4,0x03e6,0x03f0,0x07e9,0x07ef,0x0ff8,0x0ffe,0x0ffc,0x0fff} +}; + +const UWord16 huff_ctab11[17][17]= +{ + {0x0000,0x0006,0x0019,0x003d,0x009c,0x00c6,0x01a7,0x0390,0x03c2,0x03df,0x07e6,0x07f3,0x0ffb,0x07ec,0x0ffa,0x0ffe,0x038e}, + {0x0005,0x0001,0x0008,0x0014,0x0037,0x0042,0x0092,0x00af,0x0191,0x01a5,0x01b5,0x039e,0x03c0,0x03a2,0x03cd,0x07d6,0x00ae}, + {0x0017,0x0007,0x0009,0x0018,0x0039,0x0040,0x008e,0x00a3,0x00b8,0x0199,0x01ac,0x01c1,0x03b1,0x0396,0x03be,0x03ca,0x009d}, + {0x003c,0x0015,0x0016,0x001a,0x003b,0x0044,0x0091,0x00a5,0x00be,0x0196,0x01ae,0x01b9,0x03a1,0x0391,0x03a5,0x03d5,0x0094}, + {0x009a,0x0036,0x0038,0x003a,0x0041,0x008c,0x009b,0x00b0,0x00c3,0x019e,0x01ab,0x01bc,0x039f,0x038f,0x03a9,0x03cf,0x0093}, + {0x00bf,0x003e,0x003f,0x0043,0x0045,0x009e,0x00a7,0x00b9,0x0194,0x01a2,0x01ba,0x01c3,0x03a6,0x03a7,0x03bb,0x03d4,0x009f}, + {0x01a0,0x008f,0x008d,0x0090,0x0098,0x00a6,0x00b6,0x00c4,0x019f,0x01af,0x01bf,0x0399,0x03bf,0x03b4,0x03c9,0x03e7,0x00a8}, + {0x01b6,0x00ab,0x00a4,0x00aa,0x00b2,0x00c2,0x00c5,0x0198,0x01a4,0x01b8,0x038c,0x03a4,0x03c4,0x03c6,0x03dd,0x03e8,0x00ad}, + {0x03af,0x0192,0x00bd,0x00bc,0x018e,0x0197,0x019a,0x01a3,0x01b1,0x038d,0x0398,0x03b7,0x03d3,0x03d1,0x03db,0x07dd,0x00b4}, + {0x03de,0x01a9,0x019b,0x019c,0x01a1,0x01aa,0x01ad,0x01b3,0x038b,0x03b2,0x03b8,0x03ce,0x03e1,0x03e0,0x07d2,0x07e5,0x00b7}, + {0x07e3,0x01bb,0x01a8,0x01a6,0x01b0,0x01b2,0x01b7,0x039b,0x039a,0x03ba,0x03b5,0x03d6,0x07d7,0x03e4,0x07d8,0x07ea,0x00ba}, + {0x07e8,0x03a0,0x01bd,0x01b4,0x038a,0x01c4,0x0392,0x03aa,0x03b0,0x03bc,0x03d7,0x07d4,0x07dc,0x07db,0x07d5,0x07f0,0x00c1}, + {0x07fb,0x03c8,0x03a3,0x0395,0x039d,0x03ac,0x03ae,0x03c5,0x03d8,0x03e2,0x03e6,0x07e4,0x07e7,0x07e0,0x07e9,0x07f7,0x0190}, + {0x07f2,0x0393,0x01be,0x01c0,0x0394,0x0397,0x03ad,0x03c3,0x03c1,0x03d2,0x07da,0x07d9,0x07df,0x07eb,0x07f4,0x07fa,0x0195}, + {0x07f8,0x03bd,0x039c,0x03ab,0x03a8,0x03b3,0x03b9,0x03d0,0x03e3,0x03e5,0x07e2,0x07de,0x07ed,0x07f1,0x07f9,0x07fc,0x0193}, + {0x0ffd,0x03dc,0x03b6,0x03c7,0x03cc,0x03cb,0x03d9,0x03da,0x07d3,0x07e1,0x07ee,0x07ef,0x07f5,0x07f6,0x0ffc,0x0fff,0x019d}, + {0x01c2,0x00b5,0x00a1,0x0096,0x0097,0x0095,0x0099,0x00a0,0x00a2,0x00ac,0x00a9,0x00b1,0x00b3,0x00bb,0x00c0,0x018f,0x0004} +}; + +const UWord32 huff_ctabscf[121]= +{ + 0x0003ffe8, + 0x0003ffe6, + 0x0003ffe7, + 0x0003ffe5, + 0x0007fff5, + 0x0007fff1, + 0x0007ffed, + 0x0007fff6, + 0x0007ffee, + 0x0007ffef, + 0x0007fff0, + 0x0007fffc, + 0x0007fffd, + 0x0007ffff, + 0x0007fffe, + 0x0007fff7, + 0x0007fff8, + 0x0007fffb, + 0x0007fff9, + 0x0003ffe4, + 0x0007fffa, + 0x0003ffe3, + 0x0001ffef, + 0x0001fff0, + 0x0000fff5, + 0x0001ffee, + 0x0000fff2, + 0x0000fff3, + 0x0000fff4, + 0x0000fff1, + 0x00007ff6, + 0x00007ff7, + 0x00003ff9, + 0x00003ff5, + 0x00003ff7, + 0x00003ff3, + 0x00003ff6, + 0x00003ff2, + 0x00001ff7, + 0x00001ff5, + 0x00000ff9, + 0x00000ff7, + 0x00000ff6, + 0x000007f9, + 0x00000ff4, + 0x000007f8, + 0x000003f9, + 0x000003f7, + 0x000003f5, + 0x000001f8, + 0x000001f7, + 0x000000fa, + 0x000000f8, + 0x000000f6, + 0x00000079, + 0x0000003a, + 0x00000038, + 0x0000001a, + 0x0000000b, + 0x00000004, + 0x00000000, + 0x0000000a, + 0x0000000c, + 0x0000001b, + 0x00000039, + 0x0000003b, + 0x00000078, + 0x0000007a, + 0x000000f7, + 0x000000f9, + 0x000001f6, + 0x000001f9, + 0x000003f4, + 0x000003f6, + 0x000003f8, + 0x000007f5, + 0x000007f4, + 0x000007f6, + 0x000007f7, + 0x00000ff5, + 0x00000ff8, + 0x00001ff4, + 0x00001ff6, + 0x00001ff8, + 0x00003ff8, + 0x00003ff4, + 0x0000fff0, + 0x00007ff4, + 0x0000fff6, + 0x00007ff5, + 0x0003ffe2, + 0x0007ffd9, + 0x0007ffda, + 0x0007ffdb, + 0x0007ffdc, + 0x0007ffdd, + 0x0007ffde, + 0x0007ffd8, + 0x0007ffd2, + 0x0007ffd3, + 0x0007ffd4, + 0x0007ffd5, + 0x0007ffd6, + 0x0007fff2, + 0x0007ffdf, + 0x0007ffe7, + 0x0007ffe8, + 0x0007ffe9, + 0x0007ffea, + 0x0007ffeb, + 0x0007ffe6, + 0x0007ffe0, + 0x0007ffe1, + 0x0007ffe2, + 0x0007ffe3, + 0x0007ffe4, + 0x0007ffe5, + 0x0007ffd7, + 0x0007ffec, + 0x0007fff4, + 0x0007fff3 +}; + +const Word32 m_log2_table[INT_BITS] = { + 0x00000000,0x4ae00d00,0x2934f080,0x15c01a3f, + 0x0b31fb80,0x05aeb4e0,0x02dcf2d0,0x016fe50c, + 0x00b84e23,0x005c3e10,0x002e24ca,0x001713d6, + 0x000b8a47,0x0005c53b,0x0002e2a3,0x00017153, + 0x0000b8aa,0x00005c55,0x00002e2b,0x00001715, + 0x00000b8b,0x000005c5,0x000002e3,0x00000171, + 0x000000b9,0x0000005c,0x0000002e,0x00000017, + 0x0000000c,0x00000006,0x00000003,0x00000001 +}; + + +/* + 3 bit resolution +*/ +const Word32 tnsCoeff3[8] = +{ + 0x81f1d1d4, + 0x9126147c, + 0xadb922f7, + 0xd438af09, + 0x00000000, + 0x37898087, + 0x64130dfa, + 0x7cca6ffb, +}; + +const Word32 tnsCoeff3Borders[8] = +{ + 0x80000000, /* -4 */ + 0x87b826de, /* -3 */ + 0x9df24153, /* -2 */ + 0xbfffffe5, /* -1 */ + 0xe9c5e578, /* 0 */ + 0x1c7b90f0, /* 1 */ + 0x4fce83aa, /* 2 */ + 0x7352f2c4, /* 3 */ +}; + + +/* + 4 bit resolution +*/ + +const Word32 tnsCoeff4[16] = +{ + 0x808bc84b, + 0x84e2e57d, + 0x8d6b49fb, + 0x99da9207, + 0xa9c45707, + 0xbc9dde78, + 0xd1c2d4fc, + 0xe87ae539, + 0x00000000, + 0x1a9cd9c0, + 0x340ff23b, + 0x4b3c8bf7, + 0x5f1f5e80, + 0x6ed9eb84, + 0x79bc3880, + 0x7f4c7e89 +}; + +const Word32 tnsCoeff4Borders[16]= +{ + 0x80000000, /* -8 */ + 0x822defef, /* -7 */ + 0x88a4bfe5, /* -6 */ + 0x932c159c, /* -5 */ + 0xa16827c1, /* -4 */ + 0xb2dcde26, /* -3 */ + 0xc6f20b91, /* -2 */ + 0xdcf89c64, /* -1 */ + 0xf4308ce1, /* 0 */ + 0x0d613054, /* 1 */ + 0x278dde80, /* 2 */ + 0x4000001b, /* 3 */ + 0x55a6127c, /* 4 */ + 0x678dde8f, /* 5 */ + 0x74ef0ed8, /* 6 */ + 0x7d33f0db /* 7 */ +}; + + +const unsigned char bitrevTab[17 + 129] = +{ +/* 64 */ +0x01, 0x08, 0x02, 0x04, 0x03, 0x0c, 0x05, 0x0a, 0x07, 0x0e, 0x0b, 0x0d, 0x00, 0x06, 0x09, 0x0f, +0x00, + +/* 512 */ +0x01, 0x40, 0x02, 0x20, 0x03, 0x60, 0x04, 0x10, 0x05, 0x50, 0x06, 0x30, 0x07, 0x70, 0x09, 0x48, +0x0a, 0x28, 0x0b, 0x68, 0x0c, 0x18, 0x0d, 0x58, 0x0e, 0x38, 0x0f, 0x78, 0x11, 0x44, 0x12, 0x24, +0x13, 0x64, 0x15, 0x54, 0x16, 0x34, 0x17, 0x74, 0x19, 0x4c, 0x1a, 0x2c, 0x1b, 0x6c, 0x1d, 0x5c, +0x1e, 0x3c, 0x1f, 0x7c, 0x21, 0x42, 0x23, 0x62, 0x25, 0x52, 0x26, 0x32, 0x27, 0x72, 0x29, 0x4a, +0x2b, 0x6a, 0x2d, 0x5a, 0x2e, 0x3a, 0x2f, 0x7a, 0x31, 0x46, 0x33, 0x66, 0x35, 0x56, 0x37, 0x76, +0x39, 0x4e, 0x3b, 0x6e, 0x3d, 0x5e, 0x3f, 0x7e, 0x43, 0x61, 0x45, 0x51, 0x47, 0x71, 0x4b, 0x69, +0x4d, 0x59, 0x4f, 0x79, 0x53, 0x65, 0x57, 0x75, 0x5b, 0x6d, 0x5f, 0x7d, 0x67, 0x73, 0x6f, 0x7b, +0x00, 0x08, 0x14, 0x1c, 0x22, 0x2a, 0x36, 0x3e, 0x41, 0x49, 0x55, 0x5d, 0x63, 0x6b, 0x77, 0x7f, +0x00, +}; \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/src/aacenc.c b/media/libstagefright/codecs/aacenc/src/aacenc.c new file mode 100644 index 0000000000000000000000000000000000000000..552ae4105ed3afaacc4f60966d29c375fa357e9d --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/aacenc.c @@ -0,0 +1,495 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: aacenc.c + + Content: aac encoder interface functions + +*******************************************************************************/ + +#include "voAAC.h" +#include "typedef.h" +#include "aacenc_core.h" +#include "aac_rom.h" +#include "cmnMemory.h" +#include "memalign.h" + +/** +* Init the audio codec module and return codec handle +* \param phCodec [OUT] Return the video codec handle +* \param vType [IN] The codec type if the module support multi codec. +* \param pUserData [IN] The init param. It is memory operator or alloced memory +* \retval VO_ERR_NONE Succeeded. +*/ +VO_U32 VO_API voAACEncInit(VO_HANDLE * phCodec,VO_AUDIO_CODINGTYPE vType, VO_CODEC_INIT_USERDATA *pUserData) +{ + AAC_ENCODER*hAacEnc; + AACENC_CONFIG config; + int error; + +#ifdef USE_DEAULT_MEM + VO_MEM_OPERATOR voMemoprator; +#endif + VO_MEM_OPERATOR *pMemOP; + int interMem; + + interMem = 0; + error = 0; + + /* init the memory operator */ + if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL ) + { +#ifdef USE_DEAULT_MEM + voMemoprator.Alloc = cmnMemAlloc; + voMemoprator.Copy = cmnMemCopy; + voMemoprator.Free = cmnMemFree; + voMemoprator.Set = cmnMemSet; + voMemoprator.Check = cmnMemCheck; + + interMem = 1; + + pMemOP = &voMemoprator; +#else + *phCodec = NULL; + return VO_ERR_INVALID_ARG; +#endif + } + else + { + pMemOP = (VO_MEM_OPERATOR *)pUserData->memData; + } + + /* init the aac encoder handle */ + hAacEnc = (AAC_ENCODER*)mem_malloc(pMemOP, sizeof(AAC_ENCODER), 32, VO_INDEX_ENC_AAC); + if(NULL == hAacEnc) + { + error = 1; + } + + if(!error) + { + /* init the aac encoder intra memory */ + hAacEnc->intbuf = (short *)mem_malloc(pMemOP, AACENC_BLOCKSIZE*MAX_CHANNELS*sizeof(short), 32, VO_INDEX_ENC_AAC); + if(NULL == hAacEnc->intbuf) + { + error = 1; + } + } + + if (!error) { + /* init the aac encoder psychoacoustic */ + error = (PsyNew(&hAacEnc->psyKernel, MAX_CHANNELS, pMemOP) || + PsyOutNew(&hAacEnc->psyOut, pMemOP)); + } + + if (!error) { + /* init the aac encoder quantization elements */ + error = QCOutNew(&hAacEnc->qcOut,MAX_CHANNELS, pMemOP); + } + + if (!error) { + /* init the aac encoder quantization state */ + error = QCNew(&hAacEnc->qcKernel, pMemOP); + } + + /* uninit the aac encoder if error is nozero */ + if(error) + { + AacEncClose(hAacEnc, pMemOP); + if(hAacEnc) + { + mem_free(pMemOP, hAacEnc, VO_INDEX_ENC_AAC); + hAacEnc = NULL; + } + *phCodec = NULL; + return VO_ERR_OUTOF_MEMORY; + } + + /* init the aac encoder memory operator */ +#ifdef USE_DEAULT_MEM + if(interMem) + { + hAacEnc->voMemoprator.Alloc = cmnMemAlloc; + hAacEnc->voMemoprator.Copy = cmnMemCopy; + hAacEnc->voMemoprator.Free = cmnMemFree; + hAacEnc->voMemoprator.Set = cmnMemSet; + hAacEnc->voMemoprator.Check = cmnMemCheck; + + pMemOP = &hAacEnc->voMemoprator; + } +#endif + /* init the aac encoder default parameter */ + if(hAacEnc->initOK == 0) + { + AACENC_CONFIG config; + config.adtsUsed = 1; + config.bitRate = 128000; + config.nChannelsIn = 2; + config.nChannelsOut = 2; + config.sampleRate = 44100; + config.bandWidth = 20000; + + AacEncOpen(hAacEnc, config); + } + + hAacEnc->voMemop = pMemOP; + + *phCodec = hAacEnc; + + return VO_ERR_NONE; +} + +/** +* Set input audio data. +* \param hCodec [IN]] The Codec Handle which was created by Init function. +* \param pInput [IN] The input buffer param. +* \param pOutBuffer [OUT] The output buffer info. +* \retval VO_ERR_NONE Succeeded. +*/ +VO_U32 VO_API voAACEncSetInputData(VO_HANDLE hCodec, VO_CODECBUFFER * pInput) +{ + AAC_ENCODER *hAacEnc; + int length; + + if(NULL == hCodec || NULL == pInput || NULL == pInput->Buffer) + { + return VO_ERR_INVALID_ARG; + } + + hAacEnc = (AAC_ENCODER *)hCodec; + + /* init input pcm buffer and length*/ + hAacEnc->inbuf = (short *)pInput->Buffer; + hAacEnc->inlen = pInput->Length / sizeof(short); + hAacEnc->uselength = 0; + + hAacEnc->encbuf = hAacEnc->inbuf; + hAacEnc->enclen = hAacEnc->inlen; + + /* rebuild intra pcm buffer and length*/ + if(hAacEnc->intlen) + { + length = min(hAacEnc->config.nChannelsIn*AACENC_BLOCKSIZE - hAacEnc->intlen, hAacEnc->inlen); + hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf + hAacEnc->intlen, + hAacEnc->inbuf, length*sizeof(short)); + + hAacEnc->encbuf = hAacEnc->intbuf; + hAacEnc->enclen = hAacEnc->intlen + length; + + hAacEnc->inbuf += length; + hAacEnc->inlen -= length; + } + + return VO_ERR_NONE; +} + +/** +* Get the outut audio data +* \param hCodec [IN]] The Codec Handle which was created by Init function. +* \param pOutBuffer [OUT] The output audio data +* \param pOutInfo [OUT] The dec module filled audio format and used the input size. +* pOutInfo->InputUsed is total used the input size. +* \retval VO_ERR_NONE Succeeded. +* VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought. +*/ +VO_U32 VO_API voAACEncGetOutputData(VO_HANDLE hCodec, VO_CODECBUFFER * pOutput, VO_AUDIO_OUTPUTINFO * pOutInfo) +{ + AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec; + Word16 numAncDataBytes=0; + Word32 inbuflen; + int ret, length; + if(NULL == hAacEnc) + return VO_ERR_INVALID_ARG; + + inbuflen = AACENC_BLOCKSIZE*hAacEnc->config.nChannelsIn; + + /* check the input pcm buffer and length*/ + if(NULL == hAacEnc->encbuf || hAacEnc->enclen < inbuflen) + { + length = hAacEnc->enclen; + if(hAacEnc->intlen == 0) + { + hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf, + hAacEnc->encbuf, length*sizeof(short)); + hAacEnc->uselength += length*sizeof(short); + } + else + { + hAacEnc->uselength += (length - hAacEnc->intlen)*sizeof(short); + } + + hAacEnc->intlen = length; + + pOutput->Length = 0; + if(pOutInfo) + pOutInfo->InputUsed = hAacEnc->uselength; + return VO_ERR_INPUT_BUFFER_SMALL; + } + + /* check the output aac buffer and length*/ + if(NULL == pOutput || NULL == pOutput->Buffer || pOutput->Length < (6144/8)*hAacEnc->config.nChannelsOut/(sizeof(Word32))) + return VO_ERR_OUTPUT_BUFFER_SMALL; + + /* aac encoder core function */ + AacEncEncode( hAacEnc, + (Word16*)hAacEnc->encbuf, + NULL, + &numAncDataBytes, + pOutput->Buffer, + &pOutput->Length); + + /* update the input pcm buffer and length*/ + if(hAacEnc->intlen) + { + length = inbuflen - hAacEnc->intlen; + hAacEnc->encbuf = hAacEnc->inbuf; + hAacEnc->enclen = hAacEnc->inlen; + hAacEnc->uselength += length*sizeof(short); + hAacEnc->intlen = 0; + } + else + { + hAacEnc->encbuf = hAacEnc->encbuf + inbuflen; + hAacEnc->enclen = hAacEnc->enclen - inbuflen; + hAacEnc->uselength += inbuflen*sizeof(short); + } + + /* update the output aac information */ + if(pOutInfo) + { + pOutInfo->Format.Channels = hAacEnc->config.nChannelsOut; + pOutInfo->Format.SampleRate = hAacEnc->config.sampleRate; + pOutInfo->Format.SampleBits = 16; + pOutInfo->InputUsed = hAacEnc->uselength; + } + + return VO_ERR_NONE; +} + +/** +* Uninit the Codec. +* \param hCodec [IN]] The Codec Handle which was created by Init function. +* \retval VO_ERR_NONE Succeeded. +*/ +VO_U32 VO_API voAACEncUninit(VO_HANDLE hCodec) +{ + AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec; + + if(NULL != hAacEnc) + { + /* close the aac encoder */ + AacEncClose(hAacEnc, hAacEnc->voMemop); + + /* free the aac encoder handle*/ + mem_free(hAacEnc->voMemop, hAacEnc, VO_INDEX_ENC_AAC); + hAacEnc = NULL; + } + + return VO_ERR_NONE; +} + +/** +* Set the param for special target. +* \param hCodec [IN]] The Codec Handle which was created by Init function. +* \param uParamID [IN] The param ID. +* \param pData [IN] The param value depend on the ID> +* \retval VO_ERR_NONE Succeeded. +*/ +VO_U32 VO_API voAACEncSetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData) +{ + AACENC_CONFIG config; + AACENC_PARAM* pAAC_param; + VO_AUDIO_FORMAT *pWAV_Format; + AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec; + int ret, i, bitrate, tmp; + int SampleRateIdx; + + if(NULL == hAacEnc) + return VO_ERR_INVALID_ARG; + + switch(uParamID) + { + case VO_PID_AAC_ENCPARAM: /* init aac encoder parameter*/ + AacInitDefaultConfig(&config); + if(pData == NULL) + return VO_ERR_INVALID_ARG; + pAAC_param = (AACENC_PARAM*)pData; + config.adtsUsed = pAAC_param->adtsUsed; + config.bitRate = pAAC_param->bitRate; + config.nChannelsIn = pAAC_param->nChannels; + config.nChannelsOut = pAAC_param->nChannels; + config.sampleRate = pAAC_param->sampleRate; + + /* check the channel */ + if(config.nChannelsIn< 1 || config.nChannelsIn > MAX_CHANNELS || + config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut) + return VO_ERR_AUDIO_UNSCHANNEL; + + /* check the samplerate */ + ret = -1; + for(i = 0; i < NUM_SAMPLE_RATES; i++) + { + if(config.sampleRate == sampRateTab[i]) + { + ret = 0; + break; + } + } + if(ret < 0) + return VO_ERR_AUDIO_UNSSAMPLERATE; + + SampleRateIdx = i; + + tmp = 441; + if(config.sampleRate%8000 == 0) + tmp =480; + /* check the bitrate */ + if(config.bitRate!=0 && (config.bitRate/config.nChannelsOut < 4000) || + (config.bitRate/config.nChannelsOut > 160000) || + (config.bitRate > config.sampleRate*6*config.nChannelsOut)) + { + config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut; + + if(config.bitRate/config.nChannelsOut < 4000) + config.bitRate = 4000 * config.nChannelsOut; + else if(config.bitRate > config.sampleRate*6*config.nChannelsOut) + config.bitRate = config.sampleRate*6*config.nChannelsOut; + else if(config.bitRate/config.nChannelsOut > 160000) + config.bitRate = config.nChannelsOut*160000; + } + + /* check the bandwidth */ + bitrate = config.bitRate / config.nChannelsOut; + bitrate = bitrate * tmp / config.sampleRate; + + for (i = 0; rates[i]; i++) + { + if (rates[i] >= bitrate) + break; + } + + config.bandWidth = BandwithCoefTab[i][SampleRateIdx]; + + /* init aac encoder core */ + ret = AacEncOpen(hAacEnc, config); + if(ret) + return VO_ERR_AUDIO_UNSFEATURE; + break; + case VO_PID_AUDIO_FORMAT: /* init pcm channel and samplerate*/ + AacInitDefaultConfig(&config); + if(pData == NULL) + return VO_ERR_INVALID_ARG; + pWAV_Format = (VO_AUDIO_FORMAT*)pData; + config.adtsUsed = 1; + config.nChannelsIn = pWAV_Format->Channels; + config.nChannelsOut = pWAV_Format->Channels; + config.sampleRate = pWAV_Format->SampleRate; + + /* check the channel */ + if(config.nChannelsIn< 1 || config.nChannelsIn > MAX_CHANNELS || + config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut) + return VO_ERR_AUDIO_UNSCHANNEL; + + /* check the samplebits */ + if(pWAV_Format->SampleBits != 16) + { + return VO_ERR_AUDIO_UNSFEATURE; + } + + /* check the samplerate */ + ret = -1; + for(i = 0; i < NUM_SAMPLE_RATES; i++) + { + if(config.sampleRate == sampRateTab[i]) + { + ret = 0; + break; + } + } + if(ret < 0) + return VO_ERR_AUDIO_UNSSAMPLERATE; + + SampleRateIdx = i; + + /* update the bitrates */ + tmp = 441; + if(config.sampleRate%8000 == 0) + tmp =480; + + config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut; + + if(config.bitRate/config.nChannelsOut < 4000) + config.bitRate = 4000 * config.nChannelsOut; + else if(config.bitRate > config.sampleRate*6*config.nChannelsOut) + config.bitRate = config.sampleRate*6*config.nChannelsOut; + else if(config.bitRate/config.nChannelsOut > 160000) + config.bitRate = config.nChannelsOut*160000; + + /* check the bandwidth */ + bitrate = config.bitRate / config.nChannelsOut; + bitrate = bitrate * tmp / config.sampleRate; + + for (i = 0; rates[i]; i++) + { + if (rates[i] >= bitrate) + break; + } + + config.bandWidth = BandwithCoefTab[i][SampleRateIdx]; + + /* init aac encoder core */ + ret = AacEncOpen(hAacEnc, config); + if(ret) + return VO_ERR_AUDIO_UNSFEATURE; + break; + default: + return VO_ERR_WRONG_PARAM_ID; + } + + return VO_ERR_NONE; +} + +/** +* Get the param for special target. +* \param hCodec [IN]] The Codec Handle which was created by Init function. +* \param uParamID [IN] The param ID. +* \param pData [IN] The param value depend on the ID> +* \retval VO_ERR_NONE Succeeded. +*/ +VO_U32 VO_API voAACEncGetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData) +{ + return VO_ERR_NONE; +} + +/** + * Get audio codec API interface + * \param pEncHandle [out] Return the AAC Encoder handle. + * \retval VO_ERR_OK Succeeded. + */ +VO_S32 VO_API voGetAACEncAPI(VO_AUDIO_CODECAPI * pDecHandle) +{ + if(pDecHandle == NULL) + return VO_ERR_INVALID_ARG; + + pDecHandle->Init = voAACEncInit; + pDecHandle->SetInputData = voAACEncSetInputData; + pDecHandle->GetOutputData = voAACEncGetOutputData; + pDecHandle->SetParam = voAACEncSetParam; + pDecHandle->GetParam = voAACEncGetParam; + pDecHandle->Uninit = voAACEncUninit; + + return VO_ERR_NONE; +} \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/src/aacenc_core.c b/media/libstagefright/codecs/aacenc/src/aacenc_core.c new file mode 100644 index 0000000000000000000000000000000000000000..616475c90b77222fd6f8b173775cf89db0ce6b23 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/aacenc_core.c @@ -0,0 +1,239 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: aacenc_core.c + + Content: aac encoder core functions + +*******************************************************************************/ + +#include "typedef.h" +#include "aacenc_core.h" +#include "bitenc.h" + +#include "psy_configuration.h" +#include "psy_main.h" +#include "qc_main.h" +#include "psy_main.h" +#include "channel_map.h" +#include "aac_rom.h" + +/******************************************************************************** +* +* function name: AacInitDefaultConfig +* description: gives reasonable default configuration +* +**********************************************************************************/ +void AacInitDefaultConfig(AACENC_CONFIG *config) +{ + /* default configurations */ + config->adtsUsed = 1; + config->nChannelsIn = 2; + config->nChannelsOut = 2; + config->bitRate = 128000; + config->bandWidth = 0; +} + +/******************************************************************************** +* +* function name: AacEncOpen +* description: allocate and initialize a new encoder instance +* returns: 0 if success +* +**********************************************************************************/ +Word16 AacEncOpen( AAC_ENCODER* hAacEnc, /* pointer to an encoder handle, initialized on return */ + const AACENC_CONFIG config /* pre-initialized config struct */ + ) +{ + Word32 i; + Word32 error = 0; + Word16 profile = 1; + + ELEMENT_INFO *elInfo = NULL; + + if (hAacEnc==0) { + error=1; + } + + if (!error) { + hAacEnc->config = config; + } + + if (!error) { + error = InitElementInfo (config.nChannelsOut, + &hAacEnc->elInfo); + } + + if (!error) { + elInfo = &hAacEnc->elInfo; + } + + if (!error) { + /* use or not tns tool for long and short block */ + Word16 tnsMask=3; + + /* init encoder psychoacoustic */ + error = psyMainInit(&hAacEnc->psyKernel, + config.sampleRate, + config.bitRate, + elInfo->nChannelsInEl, + tnsMask, + hAacEnc->config.bandWidth); + } + + /* use or not adts header */ + if(!error) { + hAacEnc->qcOut.qcElement.adtsUsed = config.adtsUsed; + } + + /* init encoder quantization */ + if (!error) { + struct QC_INIT qcInit; + + /*qcInit.channelMapping = &hAacEnc->channelMapping;*/ + qcInit.elInfo = &hAacEnc->elInfo; + + qcInit.maxBits = (Word16) (MAXBITS_COEF*elInfo->nChannelsInEl); + qcInit.bitRes = qcInit.maxBits; + qcInit.averageBits = (Word16) ((config.bitRate * FRAME_LEN_LONG) / config.sampleRate); + + qcInit.padding.paddingRest = config.sampleRate; + + qcInit.meanPe = (Word16) ((10 * FRAME_LEN_LONG * hAacEnc->config.bandWidth) / + (config.sampleRate>>1)); + + qcInit.maxBitFac = (Word16) ((100 * (MAXBITS_COEF-MINBITS_COEF)* elInfo->nChannelsInEl)/ + (qcInit.averageBits?qcInit.averageBits:1)); + + qcInit.bitrate = config.bitRate; + + error = QCInit(&hAacEnc->qcKernel, &qcInit); + } + + /* init bitstream encoder */ + if (!error) { + hAacEnc->bseInit.nChannels = elInfo->nChannelsInEl; + hAacEnc->bseInit.bitrate = config.bitRate; + hAacEnc->bseInit.sampleRate = config.sampleRate; + hAacEnc->bseInit.profile = profile; + } + + return error; +} + +/******************************************************************************** +* +* function name: AacEncEncode +* description: encode pcm to aac data core function +* returns: 0 if success +* +**********************************************************************************/ +Word16 AacEncEncode(AAC_ENCODER *aacEnc, /*!< an encoder handle */ + Word16 *timeSignal, /*!< BLOCKSIZE*nChannels audio samples, interleaved */ + const UWord8 *ancBytes, /*!< pointer to ancillary data bytes */ + Word16 *numAncBytes, /*!< number of ancillary Data Bytes */ + UWord8 *outBytes, /*!< pointer to output buffer (must be large MINBITS_COEF/8*MAX_CHANNELS bytes) */ + Word32 *numOutBytes /*!< number of bytes in output buffer after processing */ + ) +{ + ELEMENT_INFO *elInfo = &aacEnc->elInfo; + Word16 globUsedBits; + Word16 ancDataBytes, ancDataBytesLeft; + + ancDataBytes = ancDataBytesLeft = *numAncBytes; + + /* init output aac data buffer and length */ + aacEnc->hBitStream = CreateBitBuffer(&aacEnc->bitStream, outBytes, *numOutBytes); + + /* psychoacoustic process */ + psyMain(aacEnc->config.nChannelsOut, + elInfo, + timeSignal, + &aacEnc->psyKernel.psyData[elInfo->ChannelIndex[0]], + &aacEnc->psyKernel.tnsData[elInfo->ChannelIndex[0]], + &aacEnc->psyKernel.psyConfLong, + &aacEnc->psyKernel.psyConfShort, + &aacEnc->psyOut.psyOutChannel[elInfo->ChannelIndex[0]], + &aacEnc->psyOut.psyOutElement, + aacEnc->psyKernel.pScratchTns, + aacEnc->config.sampleRate); + + /* adjust bitrate and frame length */ + AdjustBitrate(&aacEnc->qcKernel, + aacEnc->config.bitRate, + aacEnc->config.sampleRate); + + /* quantization and coding process */ + QCMain(&aacEnc->qcKernel, + &aacEnc->qcKernel.elementBits, + &aacEnc->qcKernel.adjThr.adjThrStateElem, + &aacEnc->psyOut.psyOutChannel[elInfo->ChannelIndex[0]], + &aacEnc->psyOut.psyOutElement, + &aacEnc->qcOut.qcChannel[elInfo->ChannelIndex[0]], + &aacEnc->qcOut.qcElement, + elInfo->nChannelsInEl, + min(ancDataBytesLeft,ancDataBytes)); + + ancDataBytesLeft = ancDataBytesLeft - ancDataBytes; + + globUsedBits = FinalizeBitConsumption(&aacEnc->qcKernel, + &aacEnc->qcOut); + + /* write bitstream process */ + WriteBitstream(aacEnc->hBitStream, + *elInfo, + &aacEnc->qcOut, + &aacEnc->psyOut, + &globUsedBits, + ancBytes, + aacEnc->psyKernel.sampleRateIdx); + + updateBitres(&aacEnc->qcKernel, + &aacEnc->qcOut); + + /* write out the bitstream */ + *numOutBytes = GetBitsAvail(aacEnc->hBitStream) >> 3; + + return 0; +} + + +/******************************************************************************** +* +* function name:AacEncClose +* description: deallocate an encoder instance +* +**********************************************************************************/ +void AacEncClose (AAC_ENCODER* hAacEnc, VO_MEM_OPERATOR *pMemOP) +{ + if (hAacEnc) { + QCDelete(&hAacEnc->qcKernel, pMemOP); + + QCOutDelete(&hAacEnc->qcOut, pMemOP); + + PsyDelete(&hAacEnc->psyKernel, pMemOP); + + PsyOutDelete(&hAacEnc->psyOut, pMemOP); + + DeleteBitBuffer(&hAacEnc->hBitStream); + + if(hAacEnc->intbuf) + { + mem_free(pMemOP, hAacEnc->intbuf, VO_INDEX_ENC_AAC); + hAacEnc->intbuf = NULL; + } + } +} diff --git a/media/libstagefright/codecs/aacenc/src/adj_thr.c b/media/libstagefright/codecs/aacenc/src/adj_thr.c new file mode 100644 index 0000000000000000000000000000000000000000..0dbd2166394730fbaa93f454f79b20b5a5b0ae9d --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/adj_thr.c @@ -0,0 +1,1223 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: adj_thr.c + + Content: Threshold compensation functions + +*******************************************************************************/ + +#include "basic_op.h" +#include "oper_32b.h" +#include "adj_thr_data.h" +#include "adj_thr.h" +#include "qc_data.h" +#include "line_pe.h" + + +#define minSnrLimit 0x6666 /* 1 dB */ +#define PEBITS_COEF 0x170a /* 0.18*(1 << 15)*/ + +#define HOLE_THR_LONG 0x2873 /* 0.316*(1 << 15) */ +#define HOLE_THR_SHORT 0x4000 /* 0.5 *(1 << 15) */ + +#define MS_THRSPREAD_COEF 0x7333 /* 0.9 * (1 << 15) */ + +#define MIN_SNR_COEF 0x651f /* 3.16* (1 << (15 - 2)) */ + +/* values for avoid hole flag */ +enum _avoid_hole_state { + NO_AH =0, + AH_INACTIVE =1, + AH_ACTIVE =2 +}; + +/******************************************************************************** +* +* function name:bits2pe +* description: convert from bits to pe +* pe = 1.18*desiredBits +* +**********************************************************************************/ +Word16 bits2pe(const Word16 bits) { + return (bits + ((PEBITS_COEF * bits) >> 15)); +} + +/******************************************************************************** +* +* function name:calcThreshExp +* description: loudness calculation (threshold to the power of redExp) +* thr(n)^0.25 +* +**********************************************************************************/ +static void calcThreshExp(Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + const Word16 nChannels) +{ + Word16 ch, sfb, sfbGrp; + Word32 *pthrExp, *psfbThre; + for (ch=0; chsfbCnt; sfbGrp+= psyOutChan->sfbPerGroup) + pthrExp = &(thrExp[ch][sfbGrp]); + psfbThre = psyOutChan->sfbThreshold + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + *pthrExp = rsqrt(rsqrt(*psfbThre,INT_BITS),INT_BITS); + pthrExp++; psfbThre++; + } + } +} + +/******************************************************************************** +* +* function name:adaptMinSnr +* description: reduce minSnr requirements for bands with relative low energies +* +**********************************************************************************/ +static void adaptMinSnr(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], + MINSNR_ADAPT_PARAM *msaParam, + const Word16 nChannels) +{ + Word16 ch, sfb, sfbOffs, shift; + Word32 nSfb, avgEn; + Word16 log_avgEn = 0; + Word32 startRatio_x_avgEn = 0; + + + for (ch=0; chsfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfbOffs+sfb]); + nSfb = nSfb + 1; + } + } + + if (nSfb > 0) { + avgEn = avgEn / nSfb; + + log_avgEn = iLog4(avgEn); + startRatio_x_avgEn = fixmul(msaParam->startRatio, avgEn); + } + + + /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */ + for (sfbOffs=0; sfbOffssfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + if (psyOutChan->sfbEnergy[sfbOffs+sfb] < startRatio_x_avgEn) { + Word16 dbRatio, minSnrRed; + Word32 snrRed; + Word16 newMinSnr; + + dbRatio = log_avgEn - logSfbEnergy[ch][sfbOffs+sfb]; + dbRatio = dbRatio + (dbRatio << 1); + + minSnrRed = 110 - ((dbRatio + (dbRatio << 1)) >> 2); + minSnrRed = max(minSnrRed, 20); /* 110: (0.375(redOffs)+1)*80, + 3: 0.00375(redRatioFac)*80 + 20: 0.25(maxRed) * 80 */ + + snrRed = minSnrRed * iLog4((psyOutChan->sfbMinSnr[sfbOffs+sfb] << 16)); + /* + snrRedI si now scaled by 80 (minSnrRed) and 4 (ffr_iLog4) + */ + + newMinSnr = round16(pow2_xy(snrRed,80*4)); + + psyOutChan->sfbMinSnr[sfbOffs+sfb] = min(newMinSnr, minSnrLimit); + } + } + } + } + +} + + +/******************************************************************************** +* +* function name:initAvoidHoleFlag +* description: determine bands where avoid hole is not necessary resp. possible +* +**********************************************************************************/ +static void initAvoidHoleFlag(Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT* psyOutElement, + const Word16 nChannels, + AH_PARAM *ahParam) +{ + Word16 ch, sfb, sfbGrp, shift; + Word32 threshold; + Word32* psfbSpreadEn; + + for (ch=0; chwindowSequence != SHORT_WINDOW) { + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + *psfbSpreadEn = *psfbSpreadEn >> 1; /* 0.5 */ + ++psfbSpreadEn; + } + } + } + else { + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + *psfbSpreadEn = (*psfbSpreadEn >> 1) + (*psfbSpreadEn >> 3); /* 0.63 */ + ++psfbSpreadEn; + } + } + } + } + + /* increase minSnr for local peaks, decrease it for valleys */ + if (ahParam->modifyMinSnr) { + for(ch=0; chwindowSequence != SHORT_WINDOW) + threshold = HOLE_THR_LONG; + else + threshold = HOLE_THR_SHORT; + + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + Word16 *psfbMinSnr = psyOutChan->sfbMinSnr + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + Word32 sfbEn, sfbEnm1, sfbEnp1, avgEn; + + if (sfb > 0) + sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp+sfb-1]; + else + sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp]; + + if (sfb < (psyOutChan->maxSfbPerGroup-1)) + sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb+1]; + else + sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb]; + avgEn = (sfbEnm1 + sfbEnp1) >> 1; + sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb]; + + if (sfbEn > avgEn && avgEn > 0) { + Word32 tmpMinSnr; + shift = norm_l(sfbEn); + tmpMinSnr = Div_32(L_mpy_ls(avgEn, minSnrLimit) << shift, sfbEn << shift ); + tmpMinSnr = max(tmpMinSnr, HOLE_THR_LONG); + tmpMinSnr = max(tmpMinSnr, threshold); + *psfbMinSnr = min(*psfbMinSnr, tmpMinSnr); + } + /* valley ? */ + + if ((sfbEn < (avgEn >> 1)) && (sfbEn > 0)) { + Word32 tmpMinSnr; + Word32 minSnrEn = L_mpy_wx(avgEn, *psfbMinSnr); + + if(minSnrEn < sfbEn) { + shift = norm_l(sfbEn); + tmpMinSnr = Div_32( minSnrEn << shift, sfbEn<> 2), mult(*psfbMinSnr, MIN_SNR_COEF)) << 2); + } + psfbMinSnr++; + } + } + } + } + + /* stereo: adapt the minimum requirements sfbMinSnr of mid and + side channels */ + + if (nChannels == 2) { + PSY_OUT_CHANNEL *psyOutChanM = &psyOutChannel[0]; + PSY_OUT_CHANNEL *psyOutChanS = &psyOutChannel[1]; + for (sfb=0; sfbsfbCnt; sfb++) { + if (psyOutElement->toolsInfo.msMask[sfb]) { + Word32 sfbEnM = psyOutChanM->sfbEnergy[sfb]; + Word32 sfbEnS = psyOutChanS->sfbEnergy[sfb]; + Word32 maxSfbEn = max(sfbEnM, sfbEnS); + Word32 maxThr = L_mpy_wx(maxSfbEn, psyOutChanM->sfbMinSnr[sfb]) >> 1; + + if(maxThr >= sfbEnM) { + psyOutChanM->sfbMinSnr[sfb] = MAX_16; + } + else { + shift = norm_l(sfbEnM); + psyOutChanM->sfbMinSnr[sfb] = min(max(psyOutChanM->sfbMinSnr[sfb], + round16(Div_32(maxThr<= sfbEnS) { + psyOutChanS->sfbMinSnr[sfb] = MAX_16; + } + else { + shift = norm_l(sfbEnS); + psyOutChanS->sfbMinSnr[sfb] = min(max(psyOutChanS->sfbMinSnr[sfb], + round16(Div_32(maxThr << shift, sfbEnS << shift))), minSnrLimit); + } + + + if (sfbEnM > psyOutChanM->sfbSpreadedEnergy[sfb]) + psyOutChanS->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnS, MS_THRSPREAD_COEF); + + if (sfbEnS > psyOutChanS->sfbSpreadedEnergy[sfb]) + psyOutChanM->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnM, MS_THRSPREAD_COEF); + } + } + } + + + /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ + for(ch=0; chsfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + Word16 *pahFlag = ahFlag[ch] + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + + if ((psyOutChan->sfbSpreadedEnergy[sfbGrp+sfb] > psyOutChan->sfbEnergy[sfbGrp+sfb]) || + (psyOutChan->sfbEnergy[sfbGrp+sfb] <= psyOutChan->sfbThreshold[sfbGrp+sfb]) || + (psyOutChan->sfbMinSnr[sfbGrp+sfb] == MAX_16)) { + *pahFlag++ = NO_AH; + } + else { + *pahFlag++ = AH_INACTIVE; + } + } + for (sfb=psyOutChan->maxSfbPerGroup; sfbsfbPerGroup; sfb++) { + *pahFlag++ = NO_AH; + } + } + } +} + +/******************************************************************************** +* +* function name:calcPeNoAH +* description: sum the pe data only for bands where avoid hole is inactive +* +**********************************************************************************/ +static void calcPeNoAH(Word16 *pe, + Word16 *constPart, + Word16 *nActiveLines, + PE_DATA *peData, + Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + const Word16 nChannels) +{ + Word16 ch, sfb, sfbGrp; + int ipe, iconstPart, inActiveLines; + + ipe = 0; + iconstPart = 0; + inActiveLines = 0; + for(ch=0; chpeChannelData[ch]; + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + + if (ahFlag[ch][sfbGrp+sfb] < AH_ACTIVE) { + ipe = ipe + peChanData->sfbPe[sfbGrp+sfb]; + iconstPart = iconstPart + peChanData->sfbConstPart[sfbGrp+sfb]; + inActiveLines = inActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb]; + } + } + } + } + + *pe = saturate(ipe); + *constPart = saturate(iconstPart); + *nActiveLines = saturate(inActiveLines); +} + +/******************************************************************************** +* +* function name:reduceThresholds +* description: apply reduction formula +* +**********************************************************************************/ +static void reduceThresholds(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], + const Word16 nChannels, + const Word32 redVal) +{ + Word32 sfbThrReduced; + Word32 *psfbEn, *psfbThr; + Word16 ch, sfb, sfbGrp; + + for(ch=0; chsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) { + psfbEn = psyOutChan->sfbEnergy + sfbGrp; + psfbThr = psyOutChan->sfbThreshold + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + + if (*psfbEn > *psfbThr) { + /* threshold reduction formula */ + Word32 tmp = thrExp[ch][sfbGrp+sfb] + redVal; + tmp = fixmul(tmp, tmp); + sfbThrReduced = fixmul(tmp, tmp); + /* avoid holes */ + tmp = L_mpy_ls(*psfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]); + + if ((sfbThrReduced > tmp) && + (ahFlag[ch][sfbGrp+sfb] != NO_AH)){ + sfbThrReduced = max(tmp, *psfbThr); + ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE; + } + *psfbThr = sfbThrReduced; + } + + psfbEn++; psfbThr++; + } + } + } +} + + +/******************************************************************************** +* +* function name:correctThresh +* description: if pe difference deltaPe between desired pe and real pe is small enough, +* the difference can be distributed among the scale factor bands. +* +**********************************************************************************/ +static void correctThresh(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + PE_DATA *peData, + Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], + const Word32 redVal, + const Word16 nChannels, + const Word32 deltaPe) +{ + Word16 ch, sfb, sfbGrp,shift; + PSY_OUT_CHANNEL *psyOutChan; + PE_CHANNEL_DATA *peChanData; + Word32 deltaSfbPe; + Word32 normFactor; + Word32 *psfbPeFactors; + Word16 *psfbNActiveLines, *pahFlag; + Word32 sfbEn, sfbThr; + Word32 sfbThrReduced; + + /* for each sfb calc relative factors for pe changes */ + normFactor = 1; + for(ch=0; chpeChannelData[ch]; + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp; + psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp; + pahFlag = ahFlag[ch] + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + Word32 redThrExp = thrExp[ch][sfbGrp+sfb] + redVal; + + if (((*pahFlag < AH_ACTIVE) || (deltaPe > 0)) && (redThrExp > 0) ) { + + *psfbPeFactors = (*psfbNActiveLines) * (0x7fffffff / redThrExp); + normFactor = L_add(normFactor, *psfbPeFactors); + } + else { + *psfbPeFactors = 0; + } + psfbPeFactors++; + pahFlag++; psfbNActiveLines++; + } + } + } + + + /* calculate new thresholds */ + for(ch=0; chpeChannelData[ch]; + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp; + psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp; + pahFlag = ahFlag[ch] + sfbGrp; + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + /* pe difference for this sfb */ + deltaSfbPe = *psfbPeFactors * deltaPe; + + /* thr3(n) = thr2(n)*2^deltaSfbPe/b(n) */ + if (*psfbNActiveLines > 0) { + /* new threshold */ + Word32 thrFactor; + sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb]; + sfbThr = psyOutChan->sfbThreshold[sfbGrp+sfb]; + + if(deltaSfbPe >= 0){ + /* + reduce threshold + */ + thrFactor = pow2_xy(L_negate(deltaSfbPe), (normFactor* (*psfbNActiveLines))); + + sfbThrReduced = L_mpy_ls(sfbThr, round16(thrFactor)); + } + else { + /* + increase threshold + */ + thrFactor = pow2_xy(deltaSfbPe, (normFactor * (*psfbNActiveLines))); + + + if(thrFactor > sfbThr) { + shift = norm_l(thrFactor); + sfbThrReduced = Div_32( sfbThr << shift, thrFactor<sfbMinSnr[sfbGrp+sfb]); + + if ((sfbThrReduced > sfbEn) && + (*pahFlag == AH_INACTIVE)) { + sfbThrReduced = max(sfbEn, sfbThr); + *pahFlag = AH_ACTIVE; + } + + psyOutChan->sfbThreshold[sfbGrp+sfb] = sfbThrReduced; + } + + pahFlag++; psfbNActiveLines++; psfbPeFactors++; + } + } + } +} + + +/******************************************************************************** +* +* function name:reduceMinSnr +* description: if the desired pe can not be reached, reduce pe by reducing minSnr +* +**********************************************************************************/ +static void reduceMinSnr(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PE_DATA *peData, + Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + const Word16 nChannels, + const Word16 desiredPe) +{ + Word16 ch, sfb, sfbSubWin; + Word16 deltaPe; + + /* start at highest freq down to 0 */ + sfbSubWin = psyOutChannel[0].maxSfbPerGroup; + while (peData->pe > desiredPe && sfbSubWin > 0) { + + sfbSubWin = sfbSubWin - 1; + /* loop over all subwindows */ + for (sfb=sfbSubWin; sfbpeChannelData; + PSY_OUT_CHANNEL* psyOutCh = psyOutChannel; + for (ch=0; chsfbMinSnr[sfb] < minSnrLimit) { + psyOutCh->sfbMinSnr[sfb] = minSnrLimit; + psyOutCh->sfbThreshold[sfb] = + L_mpy_ls(psyOutCh->sfbEnergy[sfb], psyOutCh->sfbMinSnr[sfb]); + + /* calc new pe */ + deltaPe = ((peChan->sfbNLines4[sfb] + (peChan->sfbNLines4[sfb] >> 1)) >> 2) - + peChan->sfbPe[sfb]; + peData->pe = peData->pe + deltaPe; + peChan->pe = peChan->pe + deltaPe; + } + peChan += 1; psyOutCh += 1; + } + /* stop if enough has been saved */ + + if (peData->pe <= desiredPe) + break; + } + } +} + +/******************************************************************************** +* +* function name:allowMoreHoles +* description: if the desired pe can not be reached, some more scalefactor bands +* have to be quantized to zero +* +**********************************************************************************/ +static void allowMoreHoles(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT *psyOutElement, + PE_DATA *peData, + Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB], + const AH_PARAM *ahParam, + const Word16 nChannels, + const Word16 desiredPe) +{ + Word16 ch, sfb; + Word16 actPe, shift; + + actPe = peData->pe; + + /* for MS allow hole in the channel with less energy */ + + if (nChannels==2 && + psyOutChannel[0].windowSequence==psyOutChannel[1].windowSequence) { + PSY_OUT_CHANNEL *psyOutChanL = &psyOutChannel[0]; + PSY_OUT_CHANNEL *psyOutChanR = &psyOutChannel[1]; + for (sfb=0; sfbsfbCnt; sfb++) { + Word32 minEn; + + if (psyOutElement->toolsInfo.msMask[sfb]) { + /* allow hole in side channel ? */ + minEn = L_mpy_ls(psyOutChanL->sfbEnergy[sfb], (minSnrLimit * psyOutChanL->sfbMinSnr[sfb]) >> 16); + + if (ahFlag[1][sfb] != NO_AH && + minEn > psyOutChanR->sfbEnergy[sfb]) { + ahFlag[1][sfb] = NO_AH; + psyOutChanR->sfbThreshold[sfb] = L_add(psyOutChanR->sfbEnergy[sfb], psyOutChanR->sfbEnergy[sfb]); + actPe = actPe - peData->peChannelData[1].sfbPe[sfb]; + } + /* allow hole in mid channel ? */ + else { + minEn = L_mpy_ls(psyOutChanR->sfbEnergy[sfb], (minSnrLimit * psyOutChanR->sfbMinSnr[sfb]) >> 16); + + if (ahFlag[0][sfb]!= NO_AH && + minEn > psyOutChanL->sfbEnergy[sfb]) { + ahFlag[0][sfb] = NO_AH; + psyOutChanL->sfbThreshold[sfb] = L_add(psyOutChanL->sfbEnergy[sfb], psyOutChanL->sfbEnergy[sfb]); + actPe = actPe - peData->peChannelData[0].sfbPe[sfb]; + } + } + + if (actPe < desiredPe) + break; + } + } + } + + /* subsequently erase bands */ + if (actPe > desiredPe) { + Word16 startSfb[2]; + Word32 avgEn, minEn; + Word16 ahCnt; + Word16 enIdx; + Word16 enDiff; + Word32 en[4]; + Word16 minSfb, maxSfb; + Flag done; + + /* do not go below startSfb */ + for (ch=0; chstartSfbL; + else + startSfb[ch] = ahParam->startSfbS; + } + + avgEn = 0; + minEn = MAX_32; + ahCnt = 0; + for (ch=0; chsfbCnt; sfb++) { + + if ((ahFlag[ch][sfb] != NO_AH) && + (psyOutChan->sfbEnergy[sfb] > psyOutChan->sfbThreshold[sfb])) { + minEn = min(minEn, psyOutChan->sfbEnergy[sfb]); + avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfb]); + ahCnt++; + } + } + } + + if(ahCnt) { + Word32 iahCnt; + shift = norm_l(ahCnt); + iahCnt = Div_32( 1 << shift, ahCnt << shift ); + avgEn = fixmul(avgEn, iahCnt); + } + + enDiff = iLog4(avgEn) - iLog4(minEn); + /* calc some energy borders between minEn and avgEn */ + for (enIdx=0; enIdx<4; enIdx++) { + Word32 enFac; + enFac = ((6-(enIdx << 1)) * enDiff); + en[enIdx] = fixmul(avgEn, pow2_xy(L_negate(enFac),7*4)); + } + + /* start with lowest energy border at highest sfb */ + maxSfb = psyOutChannel[0].sfbCnt - 1; + minSfb = startSfb[0]; + + if (nChannels == 2) { + maxSfb = max(maxSfb, (psyOutChannel[1].sfbCnt - 1)); + minSfb = min(minSfb, startSfb[1]); + } + + sfb = maxSfb; + enIdx = 0; + done = 0; + while (!done) { + + for (ch=0; ch=startSfb[ch] && sfbsfbCnt) { + /* sfb energy below border ? */ + + if (ahFlag[ch][sfb] != NO_AH && psyOutChan->sfbEnergy[sfb] < en[enIdx]){ + /* allow hole */ + ahFlag[ch][sfb] = NO_AH; + psyOutChan->sfbThreshold[sfb] = L_add(psyOutChan->sfbEnergy[sfb], psyOutChan->sfbEnergy[sfb]); + actPe = actPe - peData->peChannelData[ch].sfbPe[sfb]; + } + + if (actPe < desiredPe) { + done = 1; + break; + } + } + } + sfb = sfb - 1; + + if (sfb < minSfb) { + /* restart with next energy border */ + sfb = maxSfb; + enIdx = enIdx + 1; + + if (enIdx - 4 >= 0) + done = 1; + } + } + } +} + +/******************************************************************************** +* +* function name:adaptThresholdsToPe +* description: two guesses for the reduction value and one final correction of the +* thresholds +* +**********************************************************************************/ +static void adaptThresholdsToPe(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT *psyOutElement, + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], + PE_DATA *peData, + const Word16 nChannels, + const Word16 desiredPe, + AH_PARAM *ahParam, + MINSNR_ADAPT_PARAM *msaParam) +{ + Word16 noRedPe, redPe, redPeNoAH; + Word16 constPart, constPartNoAH; + Word16 nActiveLines, nActiveLinesNoAH; + Word16 desiredPeNoAH; + Word32 redVal, avgThrExp; + Word32 iter; + + calcThreshExp(peData->thrExp, psyOutChannel, nChannels); + + adaptMinSnr(psyOutChannel, logSfbEnergy, msaParam, nChannels); + + initAvoidHoleFlag(peData->ahFlag, psyOutChannel, psyOutElement, nChannels, ahParam); + + noRedPe = peData->pe; + constPart = peData->constPart; + nActiveLines = peData->nActiveLines; + + /* first guess of reduction value t^0.25 = 2^((a-pen)/4*b) */ + avgThrExp = pow2_xy((constPart - noRedPe), (nActiveLines << 2)); + + /* r1 = 2^((a-per)/4*b) - t^0.25 */ + redVal = pow2_xy((constPart - desiredPe), (nActiveLines << 2)) - avgThrExp; + + /* reduce thresholds */ + reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal); + + /* pe after first guess */ + calcSfbPe(peData, psyOutChannel, nChannels); + redPe = peData->pe; + + iter = 0; + do { + /* pe for bands where avoid hole is inactive */ + calcPeNoAH(&redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, + peData, peData->ahFlag, psyOutChannel, nChannels); + + desiredPeNoAH = desiredPe -(redPe - redPeNoAH); + + if (desiredPeNoAH < 0) { + desiredPeNoAH = 0; + } + + /* second guess */ + + if (nActiveLinesNoAH > 0) { + + avgThrExp = pow2_xy((constPartNoAH - redPeNoAH), (nActiveLinesNoAH << 2)); + + redVal = (redVal + pow2_xy((constPartNoAH - desiredPeNoAH), (nActiveLinesNoAH << 2))) - avgThrExp; + + /* reduce thresholds */ + reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal); + } + + calcSfbPe(peData, psyOutChannel, nChannels); + redPe = peData->pe; + + iter = iter+1; + + } while ((20 * abs_s(redPe - desiredPe) > desiredPe) && (iter < 2)); + + + if ((100 * redPe < 115 * desiredPe)) { + correctThresh(psyOutChannel, peData->ahFlag, peData, peData->thrExp, redVal, + nChannels, desiredPe - redPe); + } + else { + Word16 desiredPe105 = (105 * desiredPe) / 100; + reduceMinSnr(psyOutChannel, peData, peData->ahFlag, + nChannels, desiredPe105); + allowMoreHoles(psyOutChannel, psyOutElement, peData, peData->ahFlag, + ahParam, nChannels, desiredPe105); + } +} + + +/***************************************************************************** +* +* function name: calcBitSave +* description: Calculates percentage of bit save, see figure below +* returns: +* input: parameters and bitres-fullness +* output: percentage of bit save +* +*****************************************************************************/ +static Word16 calcBitSave(Word16 fillLevel, + const Word16 clipLow, + const Word16 clipHigh, + const Word16 minBitSave, + const Word16 maxBitSave) +{ + Word16 bitsave = 0; + + fillLevel = max(fillLevel, clipLow); + fillLevel = min(fillLevel, clipHigh); + + if(clipHigh-clipLow) + bitsave = (maxBitSave - (((maxBitSave-minBitSave)*(fillLevel-clipLow))/ + (clipHigh-clipLow))); + + return (bitsave); +} + + + +/***************************************************************************** +* +* function name: calcBitSpend +* description: Calculates percentage of bit spend, see figure below +* returns: +* input: parameters and bitres-fullness +* output: percentage of bit spend +* +*****************************************************************************/ +static Word16 calcBitSpend(Word16 fillLevel, + const Word16 clipLow, + const Word16 clipHigh, + const Word16 minBitSpend, + const Word16 maxBitSpend) +{ + Word16 bitspend = 1; + + fillLevel = max(fillLevel, clipLow); + fillLevel = min(fillLevel, clipHigh); + + if(clipHigh-clipLow) + bitspend = (minBitSpend + ((maxBitSpend - minBitSpend)*(fillLevel - clipLow) / + (clipHigh-clipLow))); + + return (bitspend); +} + + +/***************************************************************************** +* +* function name: adjustPeMinMax() +* description: adjusts peMin and peMax parameters over time +* returns: +* input: current pe, peMin, peMax +* output: adjusted peMin/peMax +* +*****************************************************************************/ +static void adjustPeMinMax(const Word16 currPe, + Word16 *peMin, + Word16 *peMax) +{ + Word16 minFacHi, maxFacHi, minFacLo, maxFacLo; + Word16 diff; + Word16 minDiff = extract_l(currPe / 6); + minFacHi = 30; + maxFacHi = 100; + minFacLo = 14; + maxFacLo = 7; + + diff = currPe - *peMax ; + + if (diff > 0) { + *peMin = *peMin + ((diff * minFacHi) / 100); + *peMax = *peMax + ((diff * maxFacHi) / 100); + } else { + diff = *peMin - currPe; + + if (diff > 0) { + *peMin = *peMin - ((diff * minFacLo) / 100); + *peMax = *peMax - ((diff * maxFacLo) / 100); + } else { + *peMin = *peMin + ((currPe - *peMin) * minFacHi / 100); + *peMax = *peMax - ((*peMax - currPe) * maxFacLo / 100); + } + } + + + if ((*peMax - *peMin) < minDiff) { + Word16 partLo, partHi; + + partLo = max(0, (currPe - *peMin)); + partHi = max(0, (*peMax - currPe)); + + *peMax = currPe + ((partHi * minDiff) / (partLo + partHi)); + *peMin = currPe - ((partLo * minDiff) / (partLo + partHi)); + *peMin = max(0, *peMin); + } +} + + +/***************************************************************************** +* +* function name: BitresCalcBitFac +* description: calculates factor of spending bits for one frame +* 1.0 : take all frame dynpart bits +* >1.0 : take all frame dynpart bits + bitres +* <1.0 : put bits in bitreservoir +* returns: BitFac*100 +* input: bitres-fullness, pe, blockType, parameter-settings +* output: +* +*****************************************************************************/ +static Word16 bitresCalcBitFac( const Word16 bitresBits, + const Word16 maxBitresBits, + const Word16 pe, + const Word16 windowSequence, + const Word16 avgBits, + const Word16 maxBitFac, + ADJ_THR_STATE *AdjThr, + ATS_ELEMENT *adjThrChan) +{ + BRES_PARAM *bresParam; + Word16 pex; + Word16 fillLevel; + Word16 bitSave, bitSpend, bitresFac; + + fillLevel = extract_l((100* bitresBits) / maxBitresBits); + + if (windowSequence != SHORT_WINDOW) + bresParam = &(AdjThr->bresParamLong); + else + bresParam = &(AdjThr->bresParamShort); + + pex = max(pe, adjThrChan->peMin); + pex = min(pex,adjThrChan->peMax); + + bitSave = calcBitSave(fillLevel, + bresParam->clipSaveLow, bresParam->clipSaveHigh, + bresParam->minBitSave, bresParam->maxBitSave); + + bitSpend = calcBitSpend(fillLevel, + bresParam->clipSpendLow, bresParam->clipSpendHigh, + bresParam->minBitSpend, bresParam->maxBitSpend); + + if(adjThrChan->peMax != adjThrChan->peMin) + bitresFac = (100 - bitSave) + extract_l(((bitSpend + bitSave) * (pex - adjThrChan->peMin)) / + (adjThrChan->peMax - adjThrChan->peMin)); + else + bitresFac = 0x7fff; + + bitresFac = min(bitresFac, + (100-30 + extract_l((100 * bitresBits) / avgBits))); + + bitresFac = min(bitresFac, maxBitFac); + + adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax); + + return bitresFac; +} + +/***************************************************************************** +* +* function name: AdjThrInit +* description: init thresholds parameter +* +*****************************************************************************/ +void AdjThrInit(ADJ_THR_STATE *hAdjThr, + const Word32 meanPe, + Word32 chBitrate) +{ + ATS_ELEMENT* atsElem = &hAdjThr->adjThrStateElem; + MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam; + + /* common for all elements: */ + /* parameters for bitres control */ + hAdjThr->bresParamLong.clipSaveLow = 20; + hAdjThr->bresParamLong.clipSaveHigh = 95; + hAdjThr->bresParamLong.minBitSave = -5; + hAdjThr->bresParamLong.maxBitSave = 30; + hAdjThr->bresParamLong.clipSpendLow = 20; + hAdjThr->bresParamLong.clipSpendHigh = 95; + hAdjThr->bresParamLong.minBitSpend = -10; + hAdjThr->bresParamLong.maxBitSpend = 40; + + hAdjThr->bresParamShort.clipSaveLow = 20; + hAdjThr->bresParamShort.clipSaveHigh = 75; + hAdjThr->bresParamShort.minBitSave = 0; + hAdjThr->bresParamShort.maxBitSave = 20; + hAdjThr->bresParamShort.clipSpendLow = 20; + hAdjThr->bresParamShort.clipSpendHigh = 75; + hAdjThr->bresParamShort.minBitSpend = -5; + hAdjThr->bresParamShort.maxBitSpend = 50; + + /* specific for each element: */ + + /* parameters for bitres control */ + atsElem->peMin = extract_l(((80*meanPe) / 100)); + atsElem->peMax = extract_l(((120*meanPe) / 100)); + + /* additional pe offset to correct pe2bits for low bitrates */ + atsElem->peOffset = 0; + if (chBitrate < 32000) { + atsElem->peOffset = max(50, (100 - extract_l((100 * chBitrate) / 32000))); + } + + /* avoid hole parameters */ + if (chBitrate > 20000) { + atsElem->ahParam.modifyMinSnr = TRUE; + atsElem->ahParam.startSfbL = 15; + atsElem->ahParam.startSfbS = 3; + } + else { + atsElem->ahParam.modifyMinSnr = FALSE; + atsElem->ahParam.startSfbL = 0; + atsElem->ahParam.startSfbS = 0; + } + + /* minSnr adaptation */ + /* maximum reduction of minSnr goes down to minSnr^maxRed */ + msaParam->maxRed = 0x20000000; /* *0.25f / + /* start adaptation of minSnr for avgEn/sfbEn > startRatio */ + msaParam->startRatio = 0x0ccccccd; /* 10 */ + /* maximum minSnr reduction to minSnr^maxRed is reached for + avgEn/sfbEn >= maxRatio */ + msaParam->maxRatio = 0x0020c49c; /* 1000 */ + /* helper variables to interpolate minSnr reduction for + avgEn/sfbEn between startRatio and maxRatio */ + + msaParam->redRatioFac = 0xfb333333; /* -0.75/20 */ + + msaParam->redOffs = 0x30000000; /* msaParam->redRatioFac * 10*log10(msaParam->startRatio) */ + + + /* pe correction */ + atsElem->peLast = 0; + atsElem->dynBitsLast = 0; + atsElem->peCorrectionFactor = 100; /* 1.0 */ + +} + +/***************************************************************************** +* +* function name: calcPeCorrection +* description: calculates the desired perceptual entropy factor +* It is between 0.85 and 1.15 +* +*****************************************************************************/ +static void calcPeCorrection(Word16 *correctionFac, + const Word16 peAct, + const Word16 peLast, + const Word16 bitsLast) +{ + Word32 peAct100 = 100 * peAct; + Word32 peLast100 = 100 * peLast; + Word16 peBitsLast = bits2pe(bitsLast); + + if ((bitsLast > 0) && + (peAct100 < (150 * peLast)) && (peAct100 > (70 * peLast)) && + ((120 * peBitsLast) > peLast100 ) && (( 65 * peBitsLast) < peLast100)) + { + Word16 newFac = (100 * peLast) / peBitsLast; + /* dead zone */ + + if (newFac < 100) { + newFac = min(((110 * newFac) / 100), 100); + newFac = max(newFac, 85); + } + else { + newFac = max(((90 * newFac) / 100), 100); + newFac = min(newFac, 115); + } + + if ((newFac > 100 && *correctionFac < 100) || + (newFac < 100 && *correctionFac > 100)) { + *correctionFac = 100; + } + /* faster adaptation towards 1.0, slower in the other direction */ + + if ((*correctionFac < 100 && newFac < *correctionFac) || + (*correctionFac > 100 && newFac > *correctionFac)) + *correctionFac = (85 * *correctionFac + 15 * newFac) / 100; + else + *correctionFac = (70 * *correctionFac + 30 * newFac) / 100; + *correctionFac = min(*correctionFac, 115); + *correctionFac = max(*correctionFac, 85); + } + else { + *correctionFac = 100; + } +} + +/******************************************************************************** +* +* function name: AdjustThresholds +* description: Adjust thresholds to the desired bitrate +* +**********************************************************************************/ +void AdjustThresholds(ADJ_THR_STATE *adjThrState, + ATS_ELEMENT *AdjThrStateElement, + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT *psyOutElement, + Word16 *chBitDistribution, + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], + Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB], + QC_OUT_ELEMENT *qcOE, + ELEMENT_BITS *elBits, + const Word16 nChannels, + const Word16 maxBitFac) +{ + PE_DATA peData; + Word16 noRedPe, grantedPe, grantedPeCorr; + Word16 curWindowSequence; + Word16 bitFactor; + Word16 avgBits = (elBits->averageBits - (qcOE->staticBitsUsed + qcOE->ancBitsUsed)); + Word16 bitresBits = elBits->bitResLevel; + Word16 maxBitresBits = elBits->maxBits; + Word16 sideInfoBits = (qcOE->staticBitsUsed + qcOE->ancBitsUsed); + Word16 ch; + + prepareSfbPe(&peData, psyOutChannel, logSfbEnergy, sfbNRelevantLines, nChannels, AdjThrStateElement->peOffset); + + /* pe without reduction */ + calcSfbPe(&peData, psyOutChannel, nChannels); + noRedPe = peData.pe; + + + curWindowSequence = LONG_WINDOW; + + if (nChannels == 2) { + + if ((psyOutChannel[0].windowSequence == SHORT_WINDOW) || + (psyOutChannel[1].windowSequence == SHORT_WINDOW)) { + curWindowSequence = SHORT_WINDOW; + } + } + else { + curWindowSequence = psyOutChannel[0].windowSequence; + } + + + /* bit factor */ + bitFactor = bitresCalcBitFac(bitresBits, maxBitresBits, noRedPe+5*sideInfoBits, + curWindowSequence, avgBits, maxBitFac, + adjThrState, + AdjThrStateElement); + + /* desired pe */ + grantedPe = ((bitFactor * bits2pe(avgBits)) / 100); + + /* correction of pe value */ + calcPeCorrection(&(AdjThrStateElement->peCorrectionFactor), + min(grantedPe, noRedPe), + AdjThrStateElement->peLast, + AdjThrStateElement->dynBitsLast); + grantedPeCorr = (grantedPe * AdjThrStateElement->peCorrectionFactor) / 100; + + + if (grantedPeCorr < noRedPe && noRedPe > peData.offset) { + /* calc threshold necessary for desired pe */ + adaptThresholdsToPe(psyOutChannel, + psyOutElement, + logSfbEnergy, + &peData, + nChannels, + grantedPeCorr, + &AdjThrStateElement->ahParam, + &AdjThrStateElement->minSnrAdaptParam); + } + + /* calculate relative distribution */ + for (ch=0; ch 0) { + Word32 temp = 1000 - (nChannels * 200); + chBitDistribution[ch] = chBitDistribution[ch] + + (temp * peData.peChannelData[ch].pe) / peOffsDiff; + } + } + + /* store pe */ + qcOE->pe = noRedPe; + + /* update last pe */ + AdjThrStateElement->peLast = grantedPe; +} + +/******************************************************************************** +* +* function name: AdjThrUpdate +* description: save dynBitsUsed for correction of bits2pe relation +* +**********************************************************************************/ +void AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement, + const Word16 dynBitsUsed) +{ + AdjThrStateElement->dynBitsLast = dynBitsUsed; +} + + diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/AutoCorrelation_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/AutoCorrelation_v5.s new file mode 100644 index 0000000000000000000000000000000000000000..48edd4ff6003defd6587a3d09e5daf8bbe064a16 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/AutoCorrelation_v5.s @@ -0,0 +1,167 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ File: AutoCorrelation_v5.s +@ +@ Content: AutoCorrelation function armv5 assemble +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + + .section .text + .global AutoCorrelation + +AutoCorrelation: + stmdb sp!, {r4 - r11, lr} + + sub r13, r13, #20 + + mov r5, r0 + mov r7, r1 + mov r9, r3 + mov r2, r2, lsl #16 + mov r0, #0 + mov r4, r2, asr #16 + mov r8, #0 + cmp r4, #0 + ble L136 + + cmp r4, #8 + mov r2, #0 + blt L133 + + sub r12, r4, #8 +L132: + ldr r6, [r5, r2] + add r2, r2, #4 + smulbb r3, r6, r6 + ldr r1, [r5, r2] + smultt r10, r6, r6 + mov r3, r3, asr #9 + smulbb r6, r1, r1 + mov r10, r10, asr #9 + qadd r0, r0, r3 + smultt r11, r1, r1 + add r2, r2, #4 + qadd r0, r0, r10 + mov r6, r6, asr #9 + mov r11, r11, asr #9 + ldr r1, [r5, r2] + qadd r0, r0, r6 + smulbb r10, r1, r1 + smultt r6, r1, r1 + qadd r0, r0, r11 + mov r10, r10, asr #9 + mov r6, r6, asr #9 + qadd r0, r0, r10 + add r2, r2, #4 + add r8, r8, #6 + + qadd r0, r0, r6 + cmp r8, r12 + blt L132 +L133: + ldrsh r6, [r5, r2] + mul r10, r6, r6 + add r2, r2, #2 + mov r1, r10, asr #9 + qadd r0, r0, r1 +L134: + add r8, r8, #1 + cmp r8, r4 + blt L133 +L135: +L136: + str r0, [r7, #0] + cmp r0, #0 + beq L1320 +L137: + mov r2, r9, lsl #16 + mov r8, #1 + mov r2, r2, asr #16 + cmp r2, #1 + ble L1319 +L138: +L139: + sub r4, r4, #1 + mov r14, #0 + mov r3, #0 + cmp r4, #0 + ble L1317 +L1310: + cmp r4, #6 + addlt r6, r5, r8, lsl #1 + blt L1314 +L1311: + add r6, r5, r8, lsl #1 + sub r12, r4, #6 + str r8, [r13, #8] + str r7, [r13, #4] +L1312: + mov r1, r3, lsl #1 + ldrsh r7, [r6, r1] + ldrsh r10, [r5, r1] + add r8, r1, r6 + add r9, r5, r1 + mul r7, r10, r7 + ldrsh r1, [r8, #2] + ldrsh r10, [r8, #4] + add r7, r14, r7, asr #9 + ldrsh r0, [r9, #2] + ldrsh r11, [r9, #4] + mul r1, r0, r1 + ldrsh r14, [r8, #6] + mul r10, r11, r10 + add r7, r7, r1, asr #9 + ldrsh r8, [r8, #8] + add r3, r3, #5 + ldrsh r11, [r9, #6] + ldrsh r1, [r9, #8] + mul r14, r11, r14 + add r7, r7, r10, asr #9 + mul r1, r1, r8 + add r14, r7, r14, asr #9 + cmp r3, r12 + add r14, r14, r1, asr #9 + ble L1312 +L1313: + ldr r8, [r13, #8] + ldr r7, [r13, #4] +L1314: +L1315: + mov r12, r3, lsl #1 + ldrsh r9, [r6, r12] + ldrsh r12, [r5, r12] + add r3, r3, #1 + cmp r3, r4 + mul r12, r12, r9 + add r14, r14, r12, asr #9 + blt L1315 +L1316: +L1317: + str r14, [r7, +r8, lsl #2] + add r8, r8, #1 + cmp r8, r2 + blt L139 + +L1319: +L1320: + add r13, r13, #20 + ldmia sp!, {r4 - r11, pc} + + @ENDP @ |AutoCorrelation| + .end diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/CalcWindowEnergy_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/CalcWindowEnergy_v5.s new file mode 100644 index 0000000000000000000000000000000000000000..7997e982903136fb35c01d72aedeeee2bb7aa39a --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/CalcWindowEnergy_v5.s @@ -0,0 +1,112 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ File: CalcWindowEnergy_v5.s +@ +@ Content: CalcWindowEnergy function armv5 assemble +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + .section .text + + .global CalcWindowEnergy + +CalcWindowEnergy: + stmdb sp!, {r4 - r11, lr} + sub r13, r13, #20 + + mov r3, r3, lsl #16 + ldr r10, [r0, #168] @ states0 = blockSwitchingControl->iirStates[0]; + mov r3, r3, asr #16 + ldr r11, [r0, #172] @ states1 = blockSwitchingControl->iirStates[1]; + + mov r2, r2, lsl #16 + ldr r12, hiPassCoeff @ Coeff0 = hiPassCoeff[0]; + mov r2, r2, asr #16 + ldr r14, hiPassCoeff + 4 @ Coeff1 = hiPassCoeff[1]; + + mov r8, #0 @ w=0 + mov r5, #0 @ wOffset = 0; + +BLOCK_BEGIN: + mov r6, #0 @ accuUE = 0; + mov r7, #0 @ accuFE = 0; + mov r4, #0 @ i=0 + + str r8, [r13, #4] + str r0, [r13, #8] + str r3, [r13, #12] + +ENERGY_BEG: + mov r9, r5, lsl #1 + ldrsh r9, [r1, r9] @ tempUnfiltered = timeSignal[tidx]; + + add r5, r5, r2 @ tidx = tidx + chIncrement; + + smulwb r3, r14, r9 @ accu1 = L_mpy_ls(Coeff1, tempUnfiltered); + smull r0, r8, r12, r11 @ accu2 = fixmul( Coeff0, states1 ); + + mov r3, r3, lsl #1 + mov r8, r8, lsl #1 + + sub r0, r3, r10 @ accu3 = accu1 - states0; + sub r8, r0, r8 @ out = accu3 - accu2; + + mov r10, r3 @ states0 = accu1; + mov r11, r8 @ states1 = out; + + mul r3, r9, r9 + mov r8, r8, asr #16 + + add r4, r4, #1 + add r6, r6, r3, asr #7 + + mul r9, r8, r8 + ldr r3, [r13, #12] + + add r7, r7, r9, asr #7 + + cmp r4, r3 + blt ENERGY_BEG + + ldr r0, [r13, #8] + ldr r8, [r13, #4] + +ENERGY_END: + add r4, r0, r8, lsl #2 + + str r6, [r4, #72] + add r8, r8, #1 + str r7, [r4, #136] + + cmp r8, #8 + blt BLOCK_BEGIN + +BLOCK_END: + str r10, [r0, #168] + str r11, [r0, #172] + mov r0, #1 + + add r13, r13, #20 + ldmia sp!, {r4 - r11, pc} + +hiPassCoeff: + .word 0xbec8b439 + .word 0x609d4952 + + @ENDP + .end diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/PrePostMDCT_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/PrePostMDCT_v5.s new file mode 100644 index 0000000000000000000000000000000000000000..d4d3edb676e163cf9bbed2362a89a31e88c4e59d --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/PrePostMDCT_v5.s @@ -0,0 +1,131 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ File: PrePostMDCT_v5.s +@ +@ Content: premdct and postmdct function armv5 assemble +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + .section .text + .global PreMDCT + +PreMDCT: + stmdb sp!, {r4 - r11, lr} + + add r9, r0, r1, lsl #2 + sub r3, r9, #8 + + movs r1, r1, asr #2 + beq PreMDCT_END + +PreMDCT_LOOP: + ldr r8, [r2], #4 + ldr r9, [r2], #4 + + ldrd r4, [r0] + ldrd r6, [r3] + + smull r14, r11, r4, r8 @ MULHIGH(tr1, cosa) + smull r10, r12, r7, r8 @ MULHIGH(ti1, cosa) + + smull r14, r8, r7, r9 @ MULHIGH(ti1, sina) + smull r7, r10, r4, r9 @ MULHIGH(tr1, sina) + + add r11, r11, r8 @ MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@ + sub r7, r12, r10 @ MULHIGH(ti1, cosa) - MULHIGH(tr1, sina) + + ldr r8, [r2], #4 + ldr r9, [r2], #4 + + smull r14, r4, r6, r8 @ MULHIGH(tr2, cosa) + smull r10, r12, r5, r8 @ MULHIGH(ti2, cosa) + + smull r14, r8, r5, r9 @ MULHIGH(ti2, sina) + smull r5, r10, r6, r9 @ MULHIGH(tr2, sina) + + add r8, r8, r4 + sub r9, r12, r10 + + mov r6, r11 + + strd r6, [r0] + strd r8, [r3] + + subs r1, r1, #1 + sub r3, r3, #8 + add r0, r0, #8 + bne PreMDCT_LOOP + +PreMDCT_END: + ldmia sp!, {r4 - r11, pc} + @ENDP @ |PreMDCT| + + .section .text + .global PostMDCT + +PostMDCT: + stmdb sp!, {r4 - r11, lr} + + add r9, r0, r1, lsl #2 + sub r3, r9, #8 + + movs r1, r1, asr #2 + beq PostMDCT_END + +PostMDCT_LOOP: + ldr r8, [r2], #4 + ldr r9, [r2], #4 + + ldrd r4, [r0] + ldrd r6, [r3] + + smull r14, r11, r4, r8 @ MULHIGH(tr1, cosa) + smull r10, r12, r5, r8 @ MULHIGH(ti1, cosa) + + smull r14, r8, r5, r9 @ MULHIGH(ti1, sina) + smull r5, r10, r4, r9 @ MULHIGH(tr1, sina) + + add r4, r11, r8 @ MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@ + sub r11, r10, r12 @ MULHIGH(ti1, cosa) - MULHIGH(tr1, sina)@ + + ldr r8, [r2], #4 @ + ldr r9, [r2], #4 + + smull r14, r5, r6, r8 @ MULHIGH(tr2, cosa) + smull r10, r12, r7, r8 @ MULHIGH(ti2, cosa) + + smull r14, r8, r7, r9 @ MULHIGH(ti2, sina) + smull r7, r10, r6, r9 @ MULHIGH(tr2, sina) + + add r6, r8, r5 @ MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2)@ + sub r5, r10, r12 @ MULHIGH(sinb, tr2) - MULHIGH(cosb, ti2)@ + + mov r7, r11 + + strd r4, [r0] + strd r6, [r3] + + subs r1, r1, #1 + sub r3, r3, #8 + add r0, r0, #8 + bne PostMDCT_LOOP + +PostMDCT_END: + ldmia sp!, {r4 - r11, pc} + @ENDP @ |PostMDCT| + .end \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/R4R8First_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/R4R8First_v5.s new file mode 100644 index 0000000000000000000000000000000000000000..370daf46d776e4e5e213589d6df2962117715109 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/R4R8First_v5.s @@ -0,0 +1,252 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ File: R4R8First_v5.s +@ +@ Content: Radix8First and Radix4First function armv5 assemble +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + .section .text + .global Radix4First + +Radix4First: + stmdb sp!, {r4 - r11, lr} + + movs r10, r1 + mov r11, r0 + beq Radix4First_END + +Radix4First_LOOP: + ldrd r0, [r11] + ldrd r2, [r11, #8] + ldrd r4, [r11, #16] + ldrd r6, [r11, #24] + + add r8, r0, r2 + add r9, r1, r3 + + sub r0, r0, r2 + sub r1, r1, r3 + + add r2, r4, r6 + add r3, r5, r7 + + sub r4, r4, r6 + sub r5, r5, r7 + + add r6, r8, r2 + add r7, r9, r3 + + sub r8, r8, r2 + sub r9, r9, r3 + + add r2, r0, r5 + sub r3, r1, r4 + + sub r0, r0, r5 + add r1, r1, r4 + + strd r6, [r11] + strd r2, [r11, #8] + strd r8, [r11, #16] + strd r0, [r11, #24] + + subs r10, r10, #1 + add r11, r11, #32 + bne Radix4First_LOOP + +Radix4First_END: + ldmia sp!, {r4 - r11, pc} + @ENDP @ |Radix4First| + + .section .text + .global Radix8First + +Radix8First: + stmdb sp!, {r4 - r11, lr} + sub sp, sp, #0x24 + + mov r12, r1 + mov r14, r0 + cmp r12, #0 + beq Radix8First_END + +Radix8First_LOOP: + ldrd r0, [r14] + ldrd r2, [r14, #8] + ldrd r4, [r14, #16] + ldrd r6, [r14, #24] + + add r8, r0, r2 @ r0 = buf[0] + buf[2]@ + add r9, r1, r3 @ i0 = buf[1] + buf[3]@ + + sub r0, r0, r2 @ r1 = buf[0] - buf[2]@ + sub r1, r1, r3 @ i1 = buf[1] - buf[3]@ + + add r2, r4, r6 @ r2 = buf[4] + buf[6]@ + add r3, r5, r7 @ i2 = buf[5] + buf[7]@ + + sub r4, r4, r6 @ r3 = buf[4] - buf[6]@ + sub r5, r5, r7 @ i3 = buf[5] - buf[7]@ + + add r6, r8, r2 @ r4 = (r0 + r2) >> 1@ + add r7, r9, r3 @ i4 = (i0 + i2) >> 1@ + + sub r8, r8, r2 @ r5 = (r0 - r2) >> 1@ + sub r9, r9, r3 @ i5 = (i0 - i2) >> 1@ + + sub r2, r0, r5 @ r6 = (r1 - i3) >> 1@ + add r3, r1, r4 @ i6 = (i1 + r3) >> 1@ + + add r0, r0, r5 @ r7 = (r1 + i3) >> 1@ + sub r1, r1, r4 @ i7 = (i1 - r3) >> 1@ + + mov r6, r6, asr #1 @ + mov r7, r7, asr #1 @ + + mov r8, r8, asr #1 + mov r9, r9, asr #1 + + mov r2, r2, asr #1 + mov r3, r3, asr #1 + + mov r0, r0, asr #1 + mov r1, r1, asr #1 + + str r6, [sp] + str r7, [sp, #4] + + str r8, [sp, #8] + str r9, [sp, #12] + + str r2, [sp, #16] + str r3, [sp, #20] + + str r0, [sp, #24] + str r1, [sp, #28] + + ldrd r2, [r14, #32] + ldrd r4, [r14, #40] + ldrd r6, [r14, #48] + ldrd r8, [r14, #56] + + add r0, r2, r4 @ r0 = buf[ 8] + buf[10]@ + add r1, r3, r5 @ i0 = buf[ 9] + buf[11]@ + + sub r2, r2, r4 @ r1 = buf[ 8] - buf[10]@ + sub r3, r3, r5 @ i1 = buf[ 9] - buf[11]@ + + add r4, r6, r8 @ r2 = buf[12] + buf[14]@ + add r5, r7, r9 @ i2 = buf[13] + buf[15]@ + + sub r6, r6, r8 @ r3 = buf[12] - buf[14]@ + sub r7, r7, r9 @ i3 = buf[13] - buf[15]@ + + add r8, r0, r4 @ t0 = (r0 + r2) + add r9, r1, r5 @ t1 = (i0 + i2) + + sub r0, r0, r4 @ t2 = (r0 - r2) + sub r1, r1, r5 @ t3 = (i0 - i2) + + mov r8, r8, asr #1 + ldr r4, [sp] + + mov r9, r9, asr #1 + ldr r5, [sp, #4] + + mov r0, r0, asr #1 + mov r1, r1, asr #1 + + add r10, r4, r8 @ buf[ 0] = r4 + t0@ + add r11, r5, r9 @ buf[ 1] = i4 + t1@ + + sub r4, r4, r8 @ buf[ 8] = r4 - t0@ + sub r5, r5, r9 @ buf[ 9] = i4 - t1@ + + strd r10, [r14] + strd r4, [r14, #32] + + ldr r10, [sp, #8] + ldr r11, [sp, #12] + + add r4, r10, r1 @ buf[ 4] = r5 + t3@ + sub r5, r11, r0 @ buf[ 5] = i5 - t2@ + + sub r10, r10, r1 @ buf[12] = r5 - t3@ + add r11, r11, r0 @ buf[13] = i5 + t2@ + + strd r4, [r14, #16] + strd r10, [r14, #48] + + sub r0, r2, r7 @ r0 = r1 - i3@ + add r1, r3, r6 @ i0 = i1 + r3@ + + ldr r11, DATATab + + add r2, r2, r7 @ r2 = r1 + i3@ + sub r3, r3, r6 @ i2 = i1 - r3@ + + sub r4, r0, r1 @ r0 - i0 + add r5, r0, r1 @ r0 + i0 + + sub r0, r2, r3 @ r2 - i2 + add r1, r2, r3 @ r2 + i2 + + smull r8, r6, r4, r11 + smull r9, r7, r5, r11 + + ldr r2, [sp, #16] + ldr r3, [sp, #20] + + smull r8, r4, r0, r11 + smull r9, r5, r1, r11 + + ldr r10, [sp, #24] + ldr r11, [sp, #28] + + sub r8, r2, r6 + sub r9, r3, r7 + + add r2, r2, r6 + add r3, r3, r7 + + add r6, r10, r5 + sub r7, r11, r4 + + sub r0, r10, r5 + add r1, r11, r4 + + strd r6, [r14, #8] + strd r8, [r14, #24] + strd r0, [r14, #40] + strd r2, [r14, #56] + + subs r12, r12, #1 + add r14, r14, #64 + + bne Radix8First_LOOP + +Radix8First_END: + add sp, sp, #0x24 + ldmia sp!, {r4 - r11, pc} + +DATATab: + .word 0x5a82799a + + @ENDP @ |Radix8First| + .end \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/Radix4FFT_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/Radix4FFT_v5.s new file mode 100644 index 0000000000000000000000000000000000000000..db8e5d81bd9d8a8feb2d10abe0f3cdd766279886 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/Radix4FFT_v5.s @@ -0,0 +1,169 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ File: Radix4FFT_v5.s +@ +@ Content: Radix4FFT armv5 assemble +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + .section .text + .global Radix4FFT + +Radix4FFT: + stmdb sp!, {r4 - r11, lr} + sub sp, sp, #32 + + mov r1, r1, asr #2 + cmp r1, #0 + beq Radix4FFT_END + +Radix4FFT_LOOP1: + mov r14, r0 @ xptr = buf@ + mov r10, r1 @ i = num@ + mov r9, r2, lsl #3 @ step = 2*bgn@ + cmp r10, #0 + str r0, [sp] + str r1, [sp, #4] + str r2, [sp, #8] + str r3, [sp, #12] + beq Radix4FFT_LOOP1_END + +Radix4FFT_LOOP2: + mov r12, r3 @ csptr = twidTab@ + mov r11, r2 @ j = bgn + cmp r11, #0 + str r10, [sp, #16] + beq Radix4FFT_LOOP2_END + +Radix4FFT_LOOP3: + str r11, [sp, #20] + + ldrd r0, [r14, #0] @ r0 = xptr[0]@ r1 = xptr[1]@ + add r14, r14, r9 @ xptr += step@ + + ldrd r10, [r14, #0] @ r2 = xptr[0]@ r3 = xptr[1]@ + ldr r8, [r12], #4 @ cosxsinx = csptr[0]@ + + smulwt r4, r10, r8 @ L_mpy_wx(cosx, t0) + smulwt r3, r11, r8 @ L_mpy_wx(cosx, t1) + + smlawb r2, r11, r8, r4 @ r2 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@ + smulwb r5, r10, r8 @ L_mpy_wx(sinx, t0) + + mov r10, r0, asr #2 @ t0 = r0 >> 2@ + mov r11, r1, asr #2 @ t1 = r1 >> 2@ + + sub r3, r3, r5 @ r3 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@ + add r14, r14, r9 @ xptr += step@ + + sub r0, r10, r2 @ r0 = t0 - r2@ + sub r1, r11, r3 @ r1 = t1 - r3@ + + add r2, r10, r2 @ r2 = t0 + r2@ + add r3, r11, r3 @ r3 = t1 + r3@ + + str r2, [sp, #24] + str r3, [sp, #28] + + ldrd r10, [r14, #0] @ r4 = xptr[0]@ r5 = xptr[1]@ + ldr r8, [r12], #4 @ cosxsinx = csptr[1]@ + + smulwt r6, r10, r8 @ L_mpy_wx(cosx, t0) + smulwt r5, r11, r8 @ L_mpy_wx(cosx, t1) + + smlawb r4, r11, r8, r6 @ r4 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@ + smulwb r7, r10, r8 @ L_mpy_wx(sinx, t0) + + add r14, r14, r9 @ xptr += step@ + sub r5, r5, r7 @ r5 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@ + + ldrd r10, [r14] @ r6 = xptr[0]@ r7 = xptr[1]@ + ldr r8, [r12], #4 @ cosxsinx = csptr[1]@ + + smulwt r2, r10, r8 @ L_mpy_wx(cosx, t0) + smulwt r7, r11, r8 @ L_mpy_wx(cosx, t1) + + smlawb r6, r11, r8, r2 @ r4 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@ + smulwb r3, r10, r8 @ L_mpy_wx(sinx, t0) + + mov r10, r4 @ t0 = r4@ + mov r11, r5 @ t1 = r5@ + + sub r7, r7, r3 @ r5 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@ + + + add r4, r10, r6 @ r4 = t0 + r6@ + sub r5, r7, r11 @ r5 = r7 - t1@ + + sub r6, r10, r6 @ r6 = t0 - r6@ + add r7, r7, r11 @ r7 = r7 + t1@ + + ldr r2, [sp, #24] + ldr r3, [sp, #28] + + add r10, r0, r5 @ xptr[0] = r0 + r5@ + add r11, r1, r6 @ xptr[0] = r1 + r6 + + strd r10, [r14] + sub r14, r14, r9 @ xptr -= step@ + + sub r10, r2, r4 @ xptr[0] = r2 - r4@ + sub r11, r3, r7 @ xptr[1] = r3 - r7@ + + strd r10, [r14] + sub r14, r14, r9 @ xptr -= step@ + + sub r10, r0, r5 @ xptr[0] = r0 - r5@ + sub r11, r1, r6 @ xptr[0] = r1 - r6 + + strd r10, [r14] + sub r14, r14, r9 @ xptr -= step@ + + add r10, r2, r4 @ xptr[0] = r2 - r4@ + add r11, r3, r7 @ xptr[1] = r3 - r7@ + + strd r10, [r14] + add r14, r14, #8 @ xptr += 2@ + + ldr r11, [sp, #20] + subs r11, r11, #1 + bne Radix4FFT_LOOP3 + +Radix4FFT_LOOP2_END: + ldr r10, [sp, #16] + ldr r3, [sp, #12] + ldr r2, [sp, #8] + rsb r8, r9, r9, lsl #2 + sub r10, r10, #1 + add r14, r14, r8 + cmp r10, #0 + bhi Radix4FFT_LOOP2 + +Radix4FFT_LOOP1_END: + ldr r0, [sp] + ldr r1, [sp, #4] + add r3, r3, r8, asr #1 + mov r2, r2, lsl #2 + movs r1, r1, asr #2 + bne Radix4FFT_LOOP1 + +Radix4FFT_END: + add sp, sp, #32 + ldmia sp!, {r4 - r11, pc} + + @ENDP @ |Radix4FFT| + .end \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/band_nrg_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/band_nrg_v5.s new file mode 100644 index 0000000000000000000000000000000000000000..a463dfd8b4991e1ca00e137548aa0c185e71b64b --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/band_nrg_v5.s @@ -0,0 +1,204 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ File: band_nrg_v5.s +@ +@ Content: CalcBandEnergy and CalcBandEnergyMS function armv5 assemble +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + .section .text + + .global CalcBandEnergy + +CalcBandEnergy: + stmdb sp!, {r4 - r11, lr} + + mov r2, r2, lsl #16 + ldr r12, [r13, #36] + mov r9, #0 + mov r5, r2, asr #16 + mov r4, #0 + cmp r5, #0 + ble L212 + +L22: + mov r2, r4, lsl #1 + ldrsh r10, [r1, r2] + add r11, r1, r2 + ldrsh r2, [r11, #2] + mov r14, #0 + cmp r10, r2 + bge L28 + +L23: + ldr r11, [r0, +r10, lsl #2] + add r10, r10, #1 + ldr r6, [r0, +r10, lsl #2] + smull r11, r7, r11, r11 + add r10, r10, #1 + smull r6, r8, r6, r6 + ldr r11, [r0, +r10, lsl #2] + qadd r14, r14, r7 + add r10, r10, #1 + smull r11, r7, r11, r11 + ldr r6, [r0, +r10, lsl #2] + qadd r14, r14, r8 + smull r6, r8, r6, r6 + add r10, r10, #1 + qadd r14, r14, r7 + cmp r10, r2 + qadd r14, r14, r8 + blt L23 + +L28: + qadd r14, r14, r14 + str r14, [r3, +r4, lsl #2] + add r4, r4, #1 + qadd r9, r9, r14 + cmp r4, r5 + + blt L22 + +L212: + str r9, [r12, #0] + ldmia sp!, {r4 - r11, pc} + + @ENDP ; |CalcBandEnergy| + + .global CalcBandEnergyMS + +CalcBandEnergyMS: + stmdb sp!, {r4 - r11, lr} + sub r13, r13, #24 + + mov r12, #0 + mov r3, r3, lsl #16 + mov r14, #0 + mov r3, r3, asr #16 + cmp r3, #0 + mov r4, #0 + ble L315 + +L32: + mov r5, r4, lsl #1 + mov r6, #0 + ldrsh r10, [r2, r5] + add r5, r2, r5 + mov r7, #0 + ldrsh r11, [r5, #2] + cmp r10, r11 + bge L39 + + str r3, [r13, #4] + str r4, [r13, #8] + str r12, [r13, #12] + str r14, [r13, #16] + +L33: + ldr r8, [r0, +r10, lsl #2] + ldr r9, [r1, +r10, lsl #2] + mov r8, r8, asr #1 + add r10, r10, #1 + mov r9, r9, asr #1 + + ldr r12, [r0, +r10, lsl #2] + add r5, r8, r9 + ldr r14, [r1, +r10, lsl #2] + sub r8, r8, r9 + + smull r5, r3, r5, r5 + mov r12, r12, asr #1 + smull r8, r4, r8, r8 + mov r14, r14, asr #1 + + qadd r6, r6, r3 + add r5, r12, r14 + qadd r7, r7, r4 + sub r8, r12, r14 + + smull r5, r3, r5, r5 + add r10, r10, #1 + smull r8, r4, r8, r8 + + qadd r6, r6, r3 + qadd r7, r7, r4 + + ldr r8, [r0, +r10, lsl #2] + ldr r9, [r1, +r10, lsl #2] + mov r8, r8, asr #1 + add r10, r10, #1 + mov r9, r9, asr #1 + + ldr r12, [r0, +r10, lsl #2] + add r5, r8, r9 + ldr r14, [r1, +r10, lsl #2] + sub r8, r8, r9 + + smull r5, r3, r5, r5 + mov r12, r12, asr #1 + smull r8, r4, r8, r8 + mov r14, r14, asr #1 + + qadd r6, r6, r3 + add r5, r12, r14 + qadd r7, r7, r4 + sub r8, r12, r14 + + smull r5, r3, r5, r5 + add r10, r10, #1 + smull r8, r4, r8, r8 + + qadd r6, r6, r3 + qadd r7, r7, r4 + + cmp r10, r11 + + blt L33 + + ldr r3, [r13, #4] + ldr r4, [r13, #8] + ldr r12, [r13, #12] + ldr r14, [r13, #16] +L39: + qadd r6, r6, r6 + qadd r7, r7, r7 + + ldr r8, [r13, #60] + ldr r9, [r13, #68] + + qadd r12, r12, r6 + qadd r14, r14, r7 + + str r6, [r8, +r4, lsl #2] + str r7, [r9, +r4, lsl #2] + + add r4, r4, #1 + cmp r4, r3 + blt L32 + +L315: + ldr r8, [r13, #64] + ldr r9, [r13, #72] + str r12, [r8, #0] + str r14, [r9, #0] + + add r13, r13, #24 + ldmia sp!, {r4 - r11, pc} + @ENDP ; |CalcBandEnergyMS| + + .end diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV7/PrePostMDCT_v7.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/PrePostMDCT_v7.s new file mode 100644 index 0000000000000000000000000000000000000000..bf7dcbad7051b94665cf1c484bcc41bbaf9e20c3 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/PrePostMDCT_v7.s @@ -0,0 +1,135 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ File: PrePostMDCT_v7.s +@ +@ Content: premdct and postmdct function armv7 assemble +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + .section .text + .global PreMDCT + +PreMDCT: + stmdb sp!, {r4 - r11, lr} + + add r9, r0, r1, lsl #2 + sub r3, r9, #32 + + movs r1, r1, asr #2 + beq PreMDCT_END + +PreMDCT_LOOP: + VLD4.I32 {d0, d2, d4, d6}, [r2]! @ cosa = *csptr++@ sina = *csptr++@ + VLD4.I32 {d1, d3, d5, d7}, [r2]! @ cosb = *csptr++@ sinb = *csptr++@ + VLD2.I32 {d8, d9, d10, d11}, [r0] @ tr1 = *(buf0 + 0)@ ti2 = *(buf0 + 1)@ + VLD2.I32 {d13, d15}, [r3]! @ tr2 = *(buf1 - 1)@ ti1 = *(buf1 + 0)@ + VLD2.I32 {d12, d14}, [r3]! @ tr2 = *(buf1 - 1)@ ti1 = *(buf1 + 0)@ + + VREV64.32 Q8, Q7 + VREV64.32 Q9, Q6 + + + VQDMULH.S32 Q10, Q0, Q4 @ MULHIGH(cosa, tr1) + VQDMULH.S32 Q11, Q1, Q8 @ MULHIGH(sina, ti1) + VQDMULH.S32 Q12, Q0, Q8 @ MULHIGH(cosa, ti1) + VQDMULH.S32 Q13, Q1, Q4 @ MULHIGH(sina, tr1) + + VADD.S32 Q0, Q10, Q11 @ *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@ + VSUB.S32 Q1, Q12, Q13 @ *buf0++ = MULHIGH(cosa, ti1) - MULHIGH(sina, tr1)@ + + VST2.I32 {d0, d1, d2, d3}, [r0]! + sub r3, r3, #32 + + VQDMULH.S32 Q10, Q2, Q9 @ MULHIGH(cosb, tr2) + VQDMULH.S32 Q11, Q3, Q5 @ MULHIGH(sinb, ti2) + VQDMULH.S32 Q12, Q2, Q5 @ MULHIGH(cosb, ti2) + VQDMULH.S32 Q13, Q3, Q9 @ MULHIGH(sinb, tr2) + + VADD.S32 Q0, Q10, Q11 @ MULHIGH(cosa, tr2) + MULHIGH(sina, ti2)@ + VSUB.S32 Q1, Q12, Q13 @ MULHIGH(cosa, ti2) - MULHIGH(sina, tr2)@ + + VREV64.32 Q3, Q1 + VREV64.32 Q2, Q0 + + VST2.I32 {d5, d7}, [r3]! + VST2.I32 {d4, d6}, [r3]! + + subs r1, r1, #4 + sub r3, r3, #64 + bne PreMDCT_LOOP + +PreMDCT_END: + ldmia sp!, {r4 - r11, pc} + @ENDP @ |PreMDCT| + + .section .text + .global PostMDCT + +PostMDCT: + stmdb sp!, {r4 - r11, lr} + + add r9, r0, r1, lsl #2 + sub r3, r9, #32 + + movs r1, r1, asr #2 + beq PostMDCT_END + +PostMDCT_LOOP: + VLD4.I32 {d0, d2, d4, d6}, [r2]! @ cosa = *csptr++@ sina = *csptr++@ + VLD4.I32 {d1, d3, d5, d7}, [r2]! @ cosb = *csptr++@ sinb = *csptr++@ + VLD2.I32 {d8, d9, d10, d11}, [r0] @ tr1 = *(zbuf1 + 0)@ ti1 = *(zbuf1 + 1)@ + VLD2.I32 {d13, d15}, [r3]! @ tr2 = *(zbuf2 - 1)@ ti2 = *(zbuf2 + 0)@ + VLD2.I32 {d12, d14}, [r3]! @ tr2 = *(zbuf2 - 1)@ ti2 = *(zbuf2 + 0)@ + + VREV64.32 Q8, Q6 + VREV64.32 Q9, Q7 + + VQDMULH.S32 Q10, Q0, Q4 @ MULHIGH(cosa, tr1) + VQDMULH.S32 Q11, Q1, Q5 @ MULHIGH(sina, ti1) + VQDMULH.S32 Q12, Q0, Q5 @ MULHIGH(cosa, ti1) + VQDMULH.S32 Q13, Q1, Q4 @ MULHIGH(sina, tr1) + + VADD.S32 Q0, Q10, Q11 @ *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@ + VSUB.S32 Q5, Q13, Q12 @ *buf1-- = MULHIGH(sina, tr1) - MULHIGH(cosa, ti1)@ + + VQDMULH.S32 Q10, Q2, Q8 @ MULHIGH(cosb, tr2) + VQDMULH.S32 Q11, Q3, Q9 @ MULHIGH(sinb, ti2) + VQDMULH.S32 Q12, Q2, Q9 @ MULHIGH(cosb, ti2) + VQDMULH.S32 Q13, Q3, Q8 @ MULHIGH(sinb, tr2) + + VADD.S32 Q4, Q10, Q11 @ *buf1-- = MULHIGH(cosa, tr2) + MULHIGH(sina, ti2)@ + VSUB.S32 Q1, Q13, Q12 @ *buf0++ = MULHIGH(sina, tr2) - MULHIGH(cosa, ti2)@ + + VREV64.32 Q2, Q4 + VREV64.32 Q3, Q5 + + sub r3, r3, #32 + VST2.I32 {d0, d1, d2, d3}, [r0]! + + VST2.I32 {d5, d7}, [r3]! + VST2.I32 {d4, d6}, [r3]! + + subs r1, r1, #4 + sub r3, r3, #64 + bne PostMDCT_LOOP + +PostMDCT_END: + ldmia sp!, {r4 - r11, pc} + + @ENDP @ |PostMDCT| + .end \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s new file mode 100644 index 0000000000000000000000000000000000000000..99ee68b88ed71793c2316ba3d6569f0823a7d2aa --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s @@ -0,0 +1,146 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ File: R4R8First_v7.s +@ +@ Content: Radix8First and Radix4First function armv7 assemble +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + .section .text + .global Radix8First + +Radix8First: + stmdb sp!, {r4 - r11, lr} + + ldr r3, SQRT1_2 + cmp r1, #0 + + VDUP.I32 Q15, r3 + beq Radix8First_END + +Radix8First_LOOP: + VLD1.I32 {d0, d1, d2, d3}, [r0]! + VLD1.I32 {d8, d9, d10, d11}, [r0]! + + VADD.S32 d4, d0, d1 @ r0 = buf[0] + buf[2]@i0 = buf[1] + buf[3]@ + VSUB.S32 d5, d0, d1 @ r1 = buf[0] - buf[2]@i1 = buf[1] - buf[3]@ + VSUB.S32 d7, d2, d3 @ r2 = buf[4] - buf[6]@i2 = buf[5] - buf[7]@ + VADD.S32 d6, d2, d3 @ r3 = buf[4] + buf[6]@i3 = buf[5] + buf[7]@ + VREV64.I32 d7, d7 + + VADD.S32 Q0, Q2, Q3 @ r4 = (r0 + r2)@i4 = (i0 + i2)@i6 = (i1 + r3)@r7 = (r1 + i3) + VSUB.S32 Q1, Q2, Q3 @ r5 = (r0 - r2)@i5 = (i0 - i2)@r6 = (r1 - i3)@i7 = (i1 - r3)@ + + VREV64.I32 d3, d3 + + VADD.S32 d4, d8, d9 @ r0 = buf[ 8] + buf[10]@i0 = buf[ 9] + buf[11]@ + VSUB.S32 d7, d10, d11 @ r1 = buf[12] - buf[14]@i1 = buf[13] - buf[15]@ + VADD.S32 d6, d10, d11 @ r2 = buf[12] + buf[14]@i2 = buf[13] + buf[15]@ + VREV64.I32 d7, d7 + VSUB.S32 d5, d8, d9 @ r3 = buf[ 8] - buf[10]@i3 = buf[ 9] - buf[11]@ + + VTRN.32 d1, d3 + + VADD.S32 Q4, Q2, Q3 @ t0 = (r0 + r2) >> 1@t1 = (i0 + i2) >> 1@i0 = i1 + r3@r2 = r1 + i3@ + VSUB.S32 Q5, Q2, Q3 @ t2 = (r0 - r2) >> 1@t3 = (i0 - i2) >> 1@r0 = r1 - i3@i2 = i1 - r3@ + + VREV64.I32 d3, d3 + + VSHR.S32 d8, d8, #1 + VSHR.S32 Q0, Q0, #1 + VREV64.I32 d10, d10 + VTRN.32 d11, d9 + VSHR.S32 Q1, Q1, #1 + VSHR.S32 d10, d10, #1 + VREV64.I32 d9, d9 + + sub r0, r0, #0x40 + + VADD.S32 d12, d0, d8 + VSUB.S32 d16, d0, d8 + VADD.S32 d14, d2, d10 + VSUB.S32 d18, d2, d10 + + VSUB.S32 d4, d11, d9 + VADD.S32 d5, d11, d9 + + VREV64.I32 d18, d18 + + VQDMULH.S32 Q3, Q2, Q15 + VTRN.32 d14, d18 + VTRN.32 d6, d7 + VREV64.I32 d18, d18 + + VSUB.S32 d15, d3, d6 + VREV64.I32 d7, d7 + VADD.S32 d19, d3, d6 + VADD.S32 d13, d1, d7 + VSUB.S32 d17, d1, d7 + + VREV64.I32 d17, d17 + VTRN.32 d13, d17 + VREV64.I32 d17, d17 + + subs r1, r1, #1 + + VST1.I32 {d12, d13, d14, d15}, [r0]! + VST1.I32 {d16, d17, d18, d19}, [r0]! + bne Radix8First_LOOP + +Radix8First_END: + ldmia sp!, {r4 - r11, pc} +SQRT1_2: + .word 0x2d413ccd + + @ENDP @ |Radix8First| + + .section .text + .global Radix4First + +Radix4First: + stmdb sp!, {r4 - r11, lr} + + cmp r1, #0 + beq Radix4First_END + +Radix4First_LOOP: + VLD1.I32 {d0, d1, d2, d3}, [r0] + + VADD.S32 d4, d0, d1 @ r0 = buf[0] + buf[2]@ r1 = buf[1] + buf[3]@ + VSUB.S32 d5, d0, d1 @ r2 = buf[0] - buf[2]@ r3 = buf[1] - buf[3]@ + VSUB.S32 d7, d2, d3 @ r4 = buf[4] + buf[6]@ r5 = buf[5] + buf[7]@ + VADD.S32 d6, d2, d3 @ r6 = buf[4] - buf[6]@ r7 = buf[5] - buf[7]@ + + VREV64.I32 d7, d7 @ + + VADD.S32 Q4, Q2, Q3 + VSUB.S32 Q5, Q2, Q3 + + VREV64.I32 d11, d11 + VTRN.32 d9, d11 + subs r1, r1, #1 + VREV64.I32 d11, d11 + VST1.I32 {d8, d9, d10, d11}, [r0]! + + bne Radix4First_LOOP + +Radix4First_END: + ldmia sp!, {r4 - r11, pc} + + @ENDP @ |Radix4First| + .end \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s new file mode 100644 index 0000000000000000000000000000000000000000..e1a843874225516a409afe134843953ff91c7dc4 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s @@ -0,0 +1,143 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@ File: Radix4FFT_v7.s +@ +@ Content: Radix4FFT armv7 assemble +@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + .section .text + .global Radix4FFT + +Radix4FFT: + stmdb sp!, {r4 - r11, lr} + + mov r1, r1, asr #2 + cmp r1, #0 + beq Radix4FFT_END + +Radix4FFT_LOOP1: + mov r5, r2, lsl #1 + mov r8, r0 + mov r7, r1 + mov r5, r5, lsl #2 + cmp r1, #0 + rsbeq r12, r5, r5, lsl #2 + beq Radix4FFT_LOOP1_END + + rsb r12, r5, r5, lsl #2 + +Radix4FFT_LOOP2: + mov r6, r3 + mov r4, r2 + cmp r2, #0 + beq Radix4FFT_LOOP2_END + +Radix4FFT_LOOP3: + @r0 = xptr[0]@ + @r1 = xptr[1]@ + VLD2.I32 {D0, D1, D2, D3}, [r8] + VLD2.I32 {D28, D29, D30, D31}, [r6]! @ cosx = csptr[0]@ sinx = csptr[1]@ + + add r8, r8, r5 @ xptr += step@ + VLD2.I32 {D4, D5, D6,D7}, [r8] @ r2 = xptr[0]@ r3 = xptr[1]@ + + VQDMULH.S32 Q10, Q2, Q14 @ MULHIGH(cosx, t0) + VQDMULH.S32 Q11, Q3, Q15 @ MULHIGH(sinx, t1) + VQDMULH.S32 Q12, Q3, Q14 @ MULHIGH(cosx, t1) + VQDMULH.S32 Q13, Q2, Q15 @ MULHIGH(sinx, t0) + + VADD.S32 Q2, Q10, Q11 @ MULHIGH(cosx, t0) + MULHIGH(sinx, t1) + VSUB.S32 Q3, Q12, Q13 @ MULHIGH(cosx, t1) - MULHIGH(sinx, t0) + + add r8, r8, r5 @ xptr += step@ + VSHR.S32 Q10, Q0, #2 @ t0 = r0 >> 2@ + VSHR.S32 Q11, Q1, #2 @ t1 = r1 >> 2@ + + VSUB.S32 Q0, Q10, Q2 @ r0 = t0 - r2@ + VSUB.S32 Q1, Q11, Q3 @ r1 = t1 - r3@ + VADD.S32 Q2, Q10, Q2 @ r2 = t0 + r2@ + VADD.S32 Q3, Q11, Q3 @ r3 = t1 + r3@ + + VLD2.I32 {D8, D9, D10, D11}, [r8] + VLD2.I32 {D28, D29, D30, D31}, [r6]! + add r8, r8, r5 + + VQDMULH.S32 Q10, Q4, Q14 @ MULHIGH(cosx, t0) + VQDMULH.S32 Q11, Q5, Q15 @ MULHIGH(sinx, t1) + VQDMULH.S32 Q12, Q5, Q14 @ MULHIGH(cosx, t1) + VQDMULH.S32 Q13, Q4, Q15 @ MULHIGH(sinx, t0) + + VADD.S32 Q8, Q10, Q11 @ MULHIGH(cosx, t0) + MULHIGH(sinx, t1) + VSUB.S32 Q9, Q12, Q13 @ MULHIGH(cosx, t1) - MULHIGH(sinx, t0) + + VLD2.I32 {D12, D13, D14, D15}, [r8] + VLD2.I32 {D28, D29, D30, D31}, [r6]! + + VQDMULH.S32 Q10, Q6, Q14 @ MULHIGH(cosx, t0) + VQDMULH.S32 Q11, Q7, Q15 @ MULHIGH(sinx, t1) + VQDMULH.S32 Q12, Q7, Q14 @ MULHIGH(cosx, t1) + VQDMULH.S32 Q13, Q6, Q15 @ MULHIGH(sinx, t0) + + VADD.S32 Q6, Q10, Q11 @ MULHIGH(cosx, t0) + MULHIGH(sinx, t1) + VSUB.S32 Q7, Q12, Q13 @ MULHIGH(cosx, t1) - MULHIGH(sinx, t0) + + VADD.S32 Q4, Q8, Q6 @ r4 = t0 + r6@ + VSUB.S32 Q5, Q7, Q9 @ r5 = r7 - t1@ + VSUB.S32 Q6, Q8, Q6 @ r6 = t0 - r6@ + VADD.S32 Q7, Q7, Q9 @ r7 = r7 + t1@ + + VADD.S32 Q8, Q0, Q5 @ xptr[0] = r0 + r5@ + VADD.S32 Q9, Q1, Q6 @ xptr[1] = r1 + r6@ + VST2.I32 {D16, D17, D18, D19}, [r8] + + VSUB.S32 Q10, Q2, Q4 @ xptr[0] = r2 - r4@ + sub r8, r8, r5 @ xptr -= step@ + VSUB.S32 Q11, Q3, Q7 @ xptr[1] = r3 - r7@ + VST2.I32 {D20, D21, D22, D23}, [r8] + + VSUB.S32 Q8, Q0, Q5 @ xptr[0] = r0 - r5@ + sub r8, r8, r5 @ xptr -= step@ + VSUB.S32 Q9, Q1, Q6 @ xptr[1] = r1 - r6@ + VST2.I32 {D16, D17, D18, D19}, [r8] + + VADD.S32 Q10, Q2, Q4 @ xptr[0] = r2 + r4@ + sub r8, r8, r5 @ xptr -= step@ + VADD.S32 Q11, Q3, Q7 @ xptr[1] = r3 + r7@ + VST2.I32 {D20, D21, D22, D23}, [r8]! + + subs r4, r4, #4 + bne Radix4FFT_LOOP3 + +Radix4FFT_LOOP2_END: + add r8, r8, r12 + sub r7, r7, #1 + cmp r7, #0 + bhi Radix4FFT_LOOP2 + +Radix4FFT_LOOP1_END: + add r3, r12, r3 + mov r2, r2, lsl #2 + movs r1, r1, asr #2 + bne Radix4FFT_LOOP1 + +Radix4FFT_END: + ldmia sp!, {r4 - r11, pc} + + @ENDP @ |Radix4FFT| + .end \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/src/band_nrg.c b/media/libstagefright/codecs/aacenc/src/band_nrg.c new file mode 100644 index 0000000000000000000000000000000000000000..666c4cacc685b060037148dc906c39affdaec02a --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/band_nrg.c @@ -0,0 +1,102 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: band_nrg.c + + Content: Band/Line energy calculations functions + +*******************************************************************************/ + +#include "basic_op.h" +#include "band_nrg.h" + +#ifndef ARMV5E +/******************************************************************************** +* +* function name: CalcBandEnergy +* description: Calc sfb-bandwise mdct-energies for left and right channel +* +**********************************************************************************/ +void CalcBandEnergy(const Word32 *mdctSpectrum, + const Word16 *bandOffset, + const Word16 numBands, + Word32 *bandEnergy, + Word32 *bandEnergySum) +{ + Word32 i, j; + Word32 accuSum = 0; + + for (i=0; i> 1; + r = mdctSpectrumRight[j] >> 1; + specm = l + r; + specs = l - r; + accuMid = L_add(accuMid, MULHIGH(specm, specm)); + accuSide = L_add(accuSide, MULHIGH(specs, specs)); + } + + accuMid = L_add(accuMid, accuMid); + accuSide = L_add(accuSide, accuSide); + bandEnergyMid[i] = accuMid; + accuMidSum = L_add(accuMidSum, accuMid); + bandEnergySide[i] = accuSide; + accuSideSum = L_add(accuSideSum, accuSide); + + } + *bandEnergyMidSum = accuMidSum; + *bandEnergySideSum = accuSideSum; +} + +#endif \ No newline at end of file diff --git a/media/libstagefright/codecs/aacenc/src/bit_cnt.c b/media/libstagefright/codecs/aacenc/src/bit_cnt.c new file mode 100644 index 0000000000000000000000000000000000000000..24837e89a24fc289375ef2b9ba270b40ed2fcc93 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/bit_cnt.c @@ -0,0 +1,885 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: bit_cnt.c + + Content: Huffman Bitcounter & coder functions + +*******************************************************************************/ + +#include "bit_cnt.h" +#include "aac_rom.h" + +#define HI_LTAB(a) (a>>8) +#define LO_LTAB(a) (a & 0xff) + +#define EXPAND(a) ((((Word32)(a&0xff00)) << 8)|(Word32)(a&0xff)) + + +/***************************************************************************** +* +* function name: count1_2_3_4_5_6_7_8_9_10_11 +* description: counts tables 1-11 +* returns: +* input: quantized spectrum +* output: bitCount for tables 1-11 +* +*****************************************************************************/ + +static void count1_2_3_4_5_6_7_8_9_10_11(const Word16 *values, + const Word16 width, + Word16 *bitCount) +{ + Word32 t0,t1,t2,t3,i; + Word32 bc1_2,bc3_4,bc5_6,bc7_8,bc9_10; + Word16 bc11,sc; + + bc1_2=0; + bc3_4=0; + bc5_6=0; + bc7_8=0; + bc9_10=0; + bc11=0; + sc=0; + + for(i=0;i0) + (t1>0) + (t2>0) + (t3>0); + } + + bitCount[1]=extract_h(bc1_2); + bitCount[2]=extract_l(bc1_2); + bitCount[3]=extract_h(bc3_4) + sc; + bitCount[4]=extract_l(bc3_4) + sc; + bitCount[5]=extract_h(bc5_6); + bitCount[6]=extract_l(bc5_6); + bitCount[7]=extract_h(bc7_8) + sc; + bitCount[8]=extract_l(bc7_8) + sc; + bitCount[9]=extract_h(bc9_10) + sc; + bitCount[10]=extract_l(bc9_10) + sc; + bitCount[11]=bc11 + sc; +} + + +/***************************************************************************** +* +* function name: count3_4_5_6_7_8_9_10_11 +* description: counts tables 3-11 +* returns: +* input: quantized spectrum +* output: bitCount for tables 3-11 +* +*****************************************************************************/ + +static void count3_4_5_6_7_8_9_10_11(const Word16 *values, + const Word16 width, + Word16 *bitCount) +{ + Word32 t0,t1,t2,t3, i; + Word32 bc3_4,bc5_6,bc7_8,bc9_10; + Word16 bc11,sc; + + bc3_4=0; + bc5_6=0; + bc7_8=0; + bc9_10=0; + bc11=0; + sc=0; + + for(i=0;i0) + (t1>0) + (t2>0) + (t3>0); + } + + bitCount[1]=INVALID_BITCOUNT; + bitCount[2]=INVALID_BITCOUNT; + bitCount[3]=extract_h(bc3_4) + sc; + bitCount[4]=extract_l(bc3_4) + sc; + bitCount[5]=extract_h(bc5_6); + bitCount[6]=extract_l(bc5_6); + bitCount[7]=extract_h(bc7_8) + sc; + bitCount[8]=extract_l(bc7_8) + sc; + bitCount[9]=extract_h(bc9_10) + sc; + bitCount[10]=extract_l(bc9_10) + sc; + bitCount[11]=bc11 + sc; + +} + + + +/***************************************************************************** +* +* function name: count5_6_7_8_9_10_11 +* description: counts tables 5-11 +* returns: +* input: quantized spectrum +* output: bitCount for tables 5-11 +* +*****************************************************************************/ +static void count5_6_7_8_9_10_11(const Word16 *values, + const Word16 width, + Word16 *bitCount) +{ + + Word32 t0,t1,i; + Word32 bc5_6,bc7_8,bc9_10; + Word16 bc11,sc; + + bc5_6=0; + bc7_8=0; + bc9_10=0; + bc11=0; + sc=0; + + for(i=0;i0) + (t1>0); + } + bitCount[1]=INVALID_BITCOUNT; + bitCount[2]=INVALID_BITCOUNT; + bitCount[3]=INVALID_BITCOUNT; + bitCount[4]=INVALID_BITCOUNT; + bitCount[5]=extract_h(bc5_6); + bitCount[6]=extract_l(bc5_6); + bitCount[7]=extract_h(bc7_8) + sc; + bitCount[8]=extract_l(bc7_8) + sc; + bitCount[9]=extract_h(bc9_10) + sc; + bitCount[10]=extract_l(bc9_10) + sc; + bitCount[11]=bc11 + sc; + +} + + +/***************************************************************************** +* +* function name: count7_8_9_10_11 +* description: counts tables 7-11 +* returns: +* input: quantized spectrum +* output: bitCount for tables 7-11 +* +*****************************************************************************/ + +static void count7_8_9_10_11(const Word16 *values, + const Word16 width, + Word16 *bitCount) +{ + Word32 t0,t1, i; + Word32 bc7_8,bc9_10; + Word16 bc11,sc; + + bc7_8=0; + bc9_10=0; + bc11=0; + sc=0; + + for(i=0;i0) + (t1>0); + } + bitCount[1]=INVALID_BITCOUNT; + bitCount[2]=INVALID_BITCOUNT; + bitCount[3]=INVALID_BITCOUNT; + bitCount[4]=INVALID_BITCOUNT; + bitCount[5]=INVALID_BITCOUNT; + bitCount[6]=INVALID_BITCOUNT; + bitCount[7]=extract_h(bc7_8) + sc; + bitCount[8]=extract_l(bc7_8) + sc; + bitCount[9]=extract_h(bc9_10) + sc; + bitCount[10]=extract_l(bc9_10) + sc; + bitCount[11]=bc11 + sc; + +} + +/***************************************************************************** +* +* function name: count9_10_11 +* description: counts tables 9-11 +* returns: +* input: quantized spectrum +* output: bitCount for tables 9-11 +* +*****************************************************************************/ +static void count9_10_11(const Word16 *values, + const Word16 width, + Word16 *bitCount) +{ + + Word32 t0,t1,i; + Word32 bc9_10; + Word16 bc11,sc; + + bc9_10=0; + bc11=0; + sc=0; + + for(i=0;i0) + (t1>0); + } + bitCount[1]=INVALID_BITCOUNT; + bitCount[2]=INVALID_BITCOUNT; + bitCount[3]=INVALID_BITCOUNT; + bitCount[4]=INVALID_BITCOUNT; + bitCount[5]=INVALID_BITCOUNT; + bitCount[6]=INVALID_BITCOUNT; + bitCount[7]=INVALID_BITCOUNT; + bitCount[8]=INVALID_BITCOUNT; + bitCount[9]=extract_h(bc9_10) + sc; + bitCount[10]=extract_l(bc9_10) + sc; + bitCount[11]=bc11 + sc; + +} + +/***************************************************************************** +* +* function name: count11 +* description: counts table 11 +* returns: +* input: quantized spectrum +* output: bitCount for table 11 +* +*****************************************************************************/ + static void count11(const Word16 *values, + const Word16 width, + Word16 *bitCount) +{ + Word32 t0,t1,i; + Word16 bc11,sc; + + bc11=0; + sc=0; + for(i=0;i0) + (t1>0); + } + + bitCount[1]=INVALID_BITCOUNT; + bitCount[2]=INVALID_BITCOUNT; + bitCount[3]=INVALID_BITCOUNT; + bitCount[4]=INVALID_BITCOUNT; + bitCount[5]=INVALID_BITCOUNT; + bitCount[6]=INVALID_BITCOUNT; + bitCount[7]=INVALID_BITCOUNT; + bitCount[8]=INVALID_BITCOUNT; + bitCount[9]=INVALID_BITCOUNT; + bitCount[10]=INVALID_BITCOUNT; + bitCount[11]=bc11 + sc; +} + +/***************************************************************************** +* +* function name: countEsc +* description: counts table 11 (with Esc) +* returns: +* input: quantized spectrum +* output: bitCount for tables 11 (with Esc) +* +*****************************************************************************/ + +static void countEsc(const Word16 *values, + const Word16 width, + Word16 *bitCount) +{ + Word32 t0,t1,t00,t01,i; + Word16 bc11,ec,sc; + + bc11=0; + sc=0; + ec=0; + for(i=0;i0) + (t1>0); + + t00 = min(t0,16); + t01 = min(t1,16); + bc11 = bc11 + huff_ltab11[t00][t01]; + + + if(t0 >= 16){ + ec = ec + 5; + while(sub(t0=(t0 >> 1), 16) >= 0) { + ec = ec + 2; + } + } + + + if(t1 >= 16){ + ec = ec + 5; + while(sub(t1=(t1 >> 1), 16) >= 0) { + ec = ec + 2; + } + } + } + bitCount[1]=INVALID_BITCOUNT; + bitCount[2]=INVALID_BITCOUNT; + bitCount[3]=INVALID_BITCOUNT; + bitCount[4]=INVALID_BITCOUNT; + bitCount[5]=INVALID_BITCOUNT; + bitCount[6]=INVALID_BITCOUNT; + bitCount[7]=INVALID_BITCOUNT; + bitCount[8]=INVALID_BITCOUNT; + bitCount[9]=INVALID_BITCOUNT; + bitCount[10]=INVALID_BITCOUNT; + bitCount[11]=bc11 + sc + ec; +} + + +typedef void (*COUNT_FUNCTION)(const Word16 *values, + const Word16 width, + Word16 *bitCount); + +static COUNT_FUNCTION countFuncTable[CODE_BOOK_ESC_LAV+1] = + { + + count1_2_3_4_5_6_7_8_9_10_11, /* 0 */ + count1_2_3_4_5_6_7_8_9_10_11, /* 1 */ + count3_4_5_6_7_8_9_10_11, /* 2 */ + count5_6_7_8_9_10_11, /* 3 */ + count5_6_7_8_9_10_11, /* 4 */ + count7_8_9_10_11, /* 5 */ + count7_8_9_10_11, /* 6 */ + count7_8_9_10_11, /* 7 */ + count9_10_11, /* 8 */ + count9_10_11, /* 9 */ + count9_10_11, /* 10 */ + count9_10_11, /* 11 */ + count9_10_11, /* 12 */ + count11, /* 13 */ + count11, /* 14 */ + count11, /* 15 */ + countEsc /* 16 */ + }; + +/***************************************************************************** +* +* function name: bitCount +* description: count bits +* +*****************************************************************************/ +Word16 bitCount(const Word16 *values, + const Word16 width, + Word16 maxVal, + Word16 *bitCount) +{ + /* + check if we can use codebook 0 + */ + + if(maxVal == 0) + bitCount[0] = 0; + else + bitCount[0] = INVALID_BITCOUNT; + + maxVal = min(maxVal, CODE_BOOK_ESC_LAV); + countFuncTable[maxVal](values,width,bitCount); + + return(0); +} + +/***************************************************************************** +* +* function name: codeValues +* description: write huffum bits +* +*****************************************************************************/ +Word16 codeValues(Word16 *values, Word16 width, Word16 codeBook, HANDLE_BIT_BUF hBitstream) +{ + + Word32 i, t0, t1, t2, t3, t00, t01; + Word16 codeWord, codeLength; + Word16 sign, signLength; + + + switch (codeBook) { + case CODE_BOOK_ZERO_NO: + break; + + case CODE_BOOK_1_NO: + for(i=0; i= 16){ + Word16 n, p; + n=0; + p=t0; + while(sub(p=(p >> 1), 16) >= 0){ + + WriteBits(hBitstream,1,1); + n = n + 1; + } + WriteBits(hBitstream,0,1); + n = n + 4; + WriteBits(hBitstream,(t0 - (1 << n)),n); + } + + if(t1 >= 16){ + Word16 n, p; + n=0; + p=t1; + while(sub(p=(p >> 1), 16) >= 0){ + + WriteBits(hBitstream,1,1); + n = n + 1; + } + WriteBits(hBitstream,0,1); + n = n + 4; + WriteBits(hBitstream,(t1 - (1 << n)),n); + } + } + break; + + default: + break; + } + return(0); +} + +Word16 bitCountScalefactorDelta(Word16 delta) +{ + return(huff_ltabscf[delta+CODE_BOOK_SCF_LAV]); +} + +Word16 codeScalefactorDelta(Word16 delta, HANDLE_BIT_BUF hBitstream) +{ + Word32 codeWord; + Word16 codeLength; + + + if(delta > CODE_BOOK_SCF_LAV || delta < -CODE_BOOK_SCF_LAV) + return(1); + + codeWord = huff_ctabscf[delta + CODE_BOOK_SCF_LAV]; + codeLength = huff_ltabscf[delta + CODE_BOOK_SCF_LAV]; + WriteBits(hBitstream,codeWord,codeLength); + return(0); +} diff --git a/media/libstagefright/codecs/aacenc/src/bitbuffer.c b/media/libstagefright/codecs/aacenc/src/bitbuffer.c new file mode 100644 index 0000000000000000000000000000000000000000..3248f0be582ac5241a6dded34a5f22841f1ded40 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/bitbuffer.c @@ -0,0 +1,172 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: bitbuffer.c + + Content: Bit Buffer Management functions + +*******************************************************************************/ + +#include "bitbuffer.h" + +/***************************************************************************** +* +* function name: updateBitBufWordPtr +* description: update Bit Buffer pointer +* +*****************************************************************************/ +static void updateBitBufWordPtr(HANDLE_BIT_BUF hBitBuf, + UWord8 **pBitBufWord, + Word16 cnt) +{ + *pBitBufWord += cnt; + + + if(*pBitBufWord > hBitBuf->pBitBufEnd) { + *pBitBufWord -= (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1); + } + + if(*pBitBufWord < hBitBuf->pBitBufBase) { + *pBitBufWord += (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1); + } +} + + +/***************************************************************************** +* +* function name: CreateBitBuffer +* description: create and init Bit Buffer Management +* +*****************************************************************************/ +HANDLE_BIT_BUF CreateBitBuffer(HANDLE_BIT_BUF hBitBuf, + UWord8 *pBitBufBase, + Word16 bitBufSize) +{ + assert(bitBufSize*8 <= 32768); + + hBitBuf->pBitBufBase = pBitBufBase; + hBitBuf->pBitBufEnd = pBitBufBase + bitBufSize - 1; + + hBitBuf->pWriteNext = pBitBufBase; + + hBitBuf->cache = 0; + + hBitBuf->wBitPos = 0; + hBitBuf->cntBits = 0; + + hBitBuf->size = (bitBufSize << 3); + hBitBuf->isValid = 1; + + return hBitBuf; +} + +/***************************************************************************** +* +* function name: DeleteBitBuffer +* description: uninit Bit Buffer Management +* +*****************************************************************************/ +void DeleteBitBuffer(HANDLE_BIT_BUF *hBitBuf) +{ + if(*hBitBuf) + (*hBitBuf)->isValid = 0; + *hBitBuf = NULL; +} + +/***************************************************************************** +* +* function name: ResetBitBuf +* description: reset Bit Buffer Management +* +*****************************************************************************/ +void ResetBitBuf(HANDLE_BIT_BUF hBitBuf, + UWord8 *pBitBufBase, + Word16 bitBufSize) +{ + hBitBuf->pBitBufBase = pBitBufBase; + hBitBuf->pBitBufEnd = pBitBufBase + bitBufSize - 1; + + + hBitBuf->pWriteNext = pBitBufBase; + + hBitBuf->wBitPos = 0; + hBitBuf->cntBits = 0; + + hBitBuf->cache = 0; +} + +/***************************************************************************** +* +* function name: CopyBitBuf +* description: copy Bit Buffer Management +* +*****************************************************************************/ +void CopyBitBuf(HANDLE_BIT_BUF hBitBufSrc, + HANDLE_BIT_BUF hBitBufDst) +{ + *hBitBufDst = *hBitBufSrc; +} + +/***************************************************************************** +* +* function name: GetBitsAvail +* description: get available bits +* +*****************************************************************************/ +Word16 GetBitsAvail(HANDLE_BIT_BUF hBitBuf) +{ + return hBitBuf->cntBits; +} + +/***************************************************************************** +* +* function name: WriteBits +* description: write bits to the buffer +* +*****************************************************************************/ +Word16 WriteBits(HANDLE_BIT_BUF hBitBuf, + Word32 writeValue, + Word16 noBitsToWrite) +{ + Word16 wBitPos; + + assert(noBitsToWrite <= (Word16)sizeof(Word32)*8); + + if(noBitsToWrite == 0) + return noBitsToWrite; + + hBitBuf->cntBits += noBitsToWrite; + + wBitPos = hBitBuf->wBitPos; + wBitPos += noBitsToWrite; + writeValue <<= 32 - wBitPos; + writeValue |= hBitBuf->cache; + + while (wBitPos >= 8) + { + UWord8 tmp; + tmp = (UWord8)((writeValue >> 24) & 0xFF); + + *hBitBuf->pWriteNext++ = tmp; + writeValue <<= 8; + wBitPos -= 8; + } + + hBitBuf->wBitPos = wBitPos; + hBitBuf->cache = writeValue; + + return noBitsToWrite; +} diff --git a/media/libstagefright/codecs/aacenc/src/bitenc.c b/media/libstagefright/codecs/aacenc/src/bitenc.c new file mode 100644 index 0000000000000000000000000000000000000000..588c2da1fe31752ef3938b5f5835c1e4477c7f80 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/bitenc.c @@ -0,0 +1,690 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: bitenc.c + + Content: Bitstream encoder functions + +*******************************************************************************/ + +#include "bitenc.h" +#include "bit_cnt.h" +#include "dyn_bits.h" +#include "qc_data.h" +#include "interface.h" + + +static const Word16 globalGainOffset = 100; +static const Word16 icsReservedBit = 0; + + +/***************************************************************************** +* +* function name: encodeSpectralData +* description: encode spectral data +* returns: spectral bits used +* +*****************************************************************************/ +static Word32 encodeSpectralData(Word16 *sfbOffset, + SECTION_DATA *sectionData, + Word16 *quantSpectrum, + HANDLE_BIT_BUF hBitStream) +{ + Word16 i,sfb; + Word16 dbgVal; + SECTION_INFO* psectioninfo; + dbgVal = GetBitsAvail(hBitStream); + + for(i=0; inoOfSections; i++) { + psectioninfo = &(sectionData->sectionInfo[i]); + /* + huffencode spectral data for this section + */ + for(sfb=psectioninfo->sfbStart; + sfbsfbStart+psectioninfo->sfbCnt; + sfb++) { + codeValues(quantSpectrum+sfbOffset[sfb], + sfbOffset[sfb+1] - sfbOffset[sfb], + psectioninfo->codeBook, + hBitStream); + } + } + + return(GetBitsAvail(hBitStream)-dbgVal); +} + +/***************************************************************************** +* +* function name:encodeGlobalGain +* description: encodes Global Gain (common scale factor) +* returns: none +* +*****************************************************************************/ +static void encodeGlobalGain(Word16 globalGain, + Word16 logNorm, + Word16 scalefac, + HANDLE_BIT_BUF hBitStream) +{ + WriteBits(hBitStream, ((globalGain - scalefac) + globalGainOffset-(logNorm << 2)), 8); +} + + +/***************************************************************************** +* +* function name:encodeIcsInfo +* description: encodes Ics Info +* returns: none +* +*****************************************************************************/ + +static void encodeIcsInfo(Word16 blockType, + Word16 windowShape, + Word16 groupingMask, + SECTION_DATA *sectionData, + HANDLE_BIT_BUF hBitStream) +{ + WriteBits(hBitStream,icsReservedBit,1); + WriteBits(hBitStream,blockType,2); + WriteBits(hBitStream,windowShape,1); + + + switch(blockType){ + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + WriteBits(hBitStream,sectionData->maxSfbPerGroup,6); + + /* No predictor data present */ + WriteBits(hBitStream, 0, 1); + break; + + case SHORT_WINDOW: + WriteBits(hBitStream,sectionData->maxSfbPerGroup,4); + + /* + Write grouping bits + */ + WriteBits(hBitStream,groupingMask,TRANS_FAC-1); + break; + } +} + +/***************************************************************************** +* +* function name: encodeSectionData +* description: encode section data (common Huffman codebooks for adjacent +* SFB's) +* returns: none +* +*****************************************************************************/ +static Word32 encodeSectionData(SECTION_DATA *sectionData, + HANDLE_BIT_BUF hBitStream) +{ + Word16 sectEscapeVal=0,sectLenBits=0; + Word16 sectLen; + Word16 i; + Word16 dbgVal=GetBitsAvail(hBitStream); + + + + switch(sectionData->blockType) + { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + sectEscapeVal = SECT_ESC_VAL_LONG; + sectLenBits = SECT_BITS_LONG; + break; + + case SHORT_WINDOW: + sectEscapeVal = SECT_ESC_VAL_SHORT; + sectLenBits = SECT_BITS_SHORT; + break; + } + + for(i=0;inoOfSections;i++) { + WriteBits(hBitStream,sectionData->sectionInfo[i].codeBook,4); + sectLen = sectionData->sectionInfo[i].sfbCnt; + + while(sectLen >= sectEscapeVal) { + + WriteBits(hBitStream,sectEscapeVal,sectLenBits); + sectLen = sectLen - sectEscapeVal; + } + WriteBits(hBitStream,sectLen,sectLenBits); + } + return(GetBitsAvail(hBitStream)-dbgVal); +} + +/***************************************************************************** +* +* function name: encodeScaleFactorData +* description: encode DPCM coded scale factors +* returns: none +* +*****************************************************************************/ +static Word32 encodeScaleFactorData(UWord16 *maxValueInSfb, + SECTION_DATA *sectionData, + Word16 *scalefac, + HANDLE_BIT_BUF hBitStream) +{ + Word16 i,j,lastValScf,deltaScf; + Word16 dbgVal = GetBitsAvail(hBitStream); + SECTION_INFO* psectioninfo; + + lastValScf=scalefac[sectionData->firstScf]; + + for(i=0;inoOfSections;i++){ + psectioninfo = &(sectionData->sectionInfo[i]); + if (psectioninfo->codeBook != CODE_BOOK_ZERO_NO){ + for (j=psectioninfo->sfbStart; + jsfbStart+psectioninfo->sfbCnt; j++){ + + if(maxValueInSfb[j] == 0) { + deltaScf = 0; + } + else { + deltaScf = lastValScf - scalefac[j]; + lastValScf = scalefac[j]; + } + + if(codeScalefactorDelta(deltaScf,hBitStream)){ + return(1); + } + } + } + + } + return(GetBitsAvail(hBitStream)-dbgVal); +} + +/***************************************************************************** +* +* function name:encodeMsInfo +* description: encodes MS-Stereo Info +* returns: none +* +*****************************************************************************/ +static void encodeMSInfo(Word16 sfbCnt, + Word16 grpSfb, + Word16 maxSfb, + Word16 msDigest, + Word16 *jsFlags, + HANDLE_BIT_BUF hBitStream) +{ + Word16 sfb, sfbOff; + + + switch(msDigest) + { + case MS_NONE: + WriteBits(hBitStream,SI_MS_MASK_NONE,2); + break; + + case MS_ALL: + WriteBits(hBitStream,SI_MS_MASK_ALL,2); + break; + + case MS_SOME: + WriteBits(hBitStream,SI_MS_MASK_SOME,2); + for(sfbOff = 0; sfbOff < sfbCnt; sfbOff+=grpSfb) { + for(sfb=0; sfb 3 || + tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -4) { + coefBits = 4; + break; + } + } + } + else { + coefBits = 2; + for(k=0; k 1 || + tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -2) { + coefBits = 3; + break; + } + } + } + WriteBits(hBitStream, tnsInfo.coefRes[i] - coefBits, 1); /*coef_compres*/ + for (k=0; kfirstScf], hBitStream); + + + if(!commonWindow) { + encodeIcsInfo(sectionData->blockType, windowShape, groupingMask, sectionData, hBitStream); + } + + encodeSectionData(sectionData, hBitStream); + + encodeScaleFactorData(maxValueInSfb, + sectionData, + scf, + hBitStream); + + encodePulseData(hBitStream); + + encodeTnsData(tnsInfo, sectionData->blockType, hBitStream); + + encodeGainControlData(hBitStream); + + encodeSpectralData(sfbOffset, + sectionData, + quantSpec, + hBitStream); + +} + +/***************************************************************************** +* +* function name: writeSingleChannelElement +* description: write single channel element to bitstream +* returns: none +* +*****************************************************************************/ +static Word16 writeSingleChannelElement(Word16 instanceTag, + Word16 *sfbOffset, + QC_OUT_CHANNEL* qcOutChannel, + HANDLE_BIT_BUF hBitStream, + TNS_INFO tnsInfo) +{ + WriteBits(hBitStream,ID_SCE,3); + WriteBits(hBitStream,instanceTag,4); + writeIndividualChannelStream(0, + qcOutChannel->mdctScale, + qcOutChannel->windowShape, + qcOutChannel->groupingMask, + sfbOffset, + qcOutChannel->scf, + qcOutChannel->maxValueInSfb, + qcOutChannel->globalGain, + qcOutChannel->quantSpec, + &(qcOutChannel->sectionData), + hBitStream, + tnsInfo + ); + return(0); +} + + + +/***************************************************************************** +* +* function name: writeChannelPairElement +* description: +* returns: none +* +*****************************************************************************/ +static Word16 writeChannelPairElement(Word16 instanceTag, + Word16 msDigest, + Word16 msFlags[MAX_GROUPED_SFB], + Word16 *sfbOffset[2], + QC_OUT_CHANNEL qcOutChannel[2], + HANDLE_BIT_BUF hBitStream, + TNS_INFO tnsInfo[2]) +{ + WriteBits(hBitStream,ID_CPE,3); + WriteBits(hBitStream,instanceTag,4); + WriteBits(hBitStream,1,1); /* common window */ + + encodeIcsInfo(qcOutChannel[0].sectionData.blockType, + qcOutChannel[0].windowShape, + qcOutChannel[0].groupingMask, + &(qcOutChannel[0].sectionData), + hBitStream); + + encodeMSInfo(qcOutChannel[0].sectionData.sfbCnt, + qcOutChannel[0].sectionData.sfbPerGroup, + qcOutChannel[0].sectionData.maxSfbPerGroup, + msDigest, + msFlags, + hBitStream); + + writeIndividualChannelStream(1, + qcOutChannel[0].mdctScale, + qcOutChannel[0].windowShape, + qcOutChannel[0].groupingMask, + sfbOffset[0], + qcOutChannel[0].scf, + qcOutChannel[0].maxValueInSfb, + qcOutChannel[0].globalGain, + qcOutChannel[0].quantSpec, + &(qcOutChannel[0].sectionData), + hBitStream, + tnsInfo[0]); + + writeIndividualChannelStream(1, + qcOutChannel[1].mdctScale, + qcOutChannel[1].windowShape, + qcOutChannel[1].groupingMask, + sfbOffset[1], + qcOutChannel[1].scf, + qcOutChannel[1].maxValueInSfb, + qcOutChannel[1].globalGain, + qcOutChannel[1].quantSpec, + &(qcOutChannel[1].sectionData), + hBitStream, + tnsInfo[1]); + + return(0); +} + + + +/***************************************************************************** +* +* function name: writeFillElement +* description: write fill elements to bitstream +* returns: none +* +*****************************************************************************/ +static void writeFillElement( const UWord8 *ancBytes, + Word16 totFillBits, + HANDLE_BIT_BUF hBitStream) +{ + Word16 i; + Word16 cnt,esc_count; + + /* + Write fill Element(s): + amount of a fill element can be 7+X*8 Bits, X element of [0..270] + */ + + while(totFillBits >= (3+4)) { + cnt = min(((totFillBits - (3+4)) >> 3), ((1<<4)-1)); + + WriteBits(hBitStream,ID_FIL,3); + WriteBits(hBitStream,cnt,4); + + totFillBits = totFillBits - (3+4); + + + if ((cnt == (1<<4)-1)) { + + esc_count = min( ((totFillBits >> 3) - ((1<<4)-1)), (1<<8)-1); + WriteBits(hBitStream,esc_count,8); + totFillBits = (totFillBits - 8); + cnt = cnt + (esc_count - 1); + } + + for(i=0;iqcElement.adtsUsed) /* write adts header*/ + { + WriteBits(hBitStream, 0xFFF, 12); /* 12 bit Syncword */ + WriteBits(hBitStream, 1, 1); /* ID == 0 for MPEG4 AAC, 1 for MPEG2 AAC */ + WriteBits(hBitStream, 0, 2); /* layer == 0 */ + WriteBits(hBitStream, 1, 1); /* protection absent */ + WriteBits(hBitStream, 1, 2); /* profile */ + WriteBits(hBitStream, sampindex, 4); /* sampling rate */ + WriteBits(hBitStream, 0, 1); /* private bit */ + WriteBits(hBitStream, elInfo.nChannelsInEl, 3); /* ch. config (must be > 0) */ + /* simply using numChannels only works for + 6 channels or less, else a channel + configuration should be written */ + WriteBits(hBitStream, 0, 1); /* original/copy */ + WriteBits(hBitStream, 0, 1); /* home */ + + /* Variable ADTS header */ + WriteBits(hBitStream, 0, 1); /* copyr. id. bit */ + WriteBits(hBitStream, 0, 1); /* copyr. id. start */ + WriteBits(hBitStream, *globUsedBits >> 3, 13); + WriteBits(hBitStream, 0x7FF, 11); /* buffer fullness (0x7FF for VBR) */ + WriteBits(hBitStream, 0, 2); /* raw data blocks (0+1=1) */ + } + + *globUsedBits=0; + + { + + Word16 *sfbOffset[2]; + TNS_INFO tnsInfo[2]; + elementUsedBits = 0; + + switch (elInfo.elType) { + + case ID_SCE: /* single channel */ + sfbOffset[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets; + tnsInfo[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo; + + writeSingleChannelElement(elInfo.instanceTag, + sfbOffset[0], + &qcOut->qcChannel[elInfo.ChannelIndex[0]], + hBitStream, + tnsInfo[0]); + break; + + case ID_CPE: /* channel pair */ + { + Word16 msDigest; + Word16 *msFlags = psyOut->psyOutElement.toolsInfo.msMask; + msDigest = psyOut->psyOutElement.toolsInfo.msDigest; + sfbOffset[0] = + psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets; + sfbOffset[1] = + psyOut->psyOutChannel[elInfo.ChannelIndex[1]].sfbOffsets; + + tnsInfo[0]= + psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo; + tnsInfo[1]= + psyOut->psyOutChannel[elInfo.ChannelIndex[1]].tnsInfo; + writeChannelPairElement(elInfo.instanceTag, + msDigest, + msFlags, + sfbOffset, + &qcOut->qcChannel[elInfo.ChannelIndex[0]], + hBitStream, + tnsInfo); + } + break; + + default: + return(1); + + } /* switch */ + + elementUsedBits = elementUsedBits - bitMarkUp; + bitMarkUp = GetBitsAvail(hBitStream); + frameBits = frameBits + elementUsedBits + bitMarkUp; + + } + + writeFillElement(NULL, + qcOut->totFillBits, + hBitStream); + + WriteBits(hBitStream,ID_END,3); + + /* byte alignement */ + WriteBits(hBitStream,0, (8 - (hBitStream->cntBits & 7)) & 7); + + *globUsedBits = *globUsedBits- bitMarkUp; + bitMarkUp = GetBitsAvail(hBitStream); + *globUsedBits = *globUsedBits + bitMarkUp; + frameBits = frameBits + *globUsedBits; + + + if (frameBits != (qcOut->totStaticBitsUsed+qcOut->totDynBitsUsed + qcOut->totAncBitsUsed + + qcOut->totFillBits + qcOut->alignBits)) { + return(-1); + } + return(0); +} diff --git a/media/libstagefright/codecs/aacenc/src/block_switch.c b/media/libstagefright/codecs/aacenc/src/block_switch.c new file mode 100644 index 0000000000000000000000000000000000000000..c0054f7c98f7a5b967884da67c4950b2e0dd5cb1 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/block_switch.c @@ -0,0 +1,431 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: block_switch.c + + Content: Block switching functions + +*******************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "psy_const.h" +#include "block_switch.h" + + +#define ENERGY_SHIFT (8 - 1) + +/**************** internal function prototypes ***********/ +static Word16 +IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[]); + +static Word32 +SrchMaxWithIndex(const Word32 *in, Word16 *index, Word16 n); + + +Word32 +CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, + Word16 *timeSignal, + Word16 chIncrement, + Word16 windowLen); + + + +/****************** Constants *****************************/ + + +/* + IIR high pass coeffs +*/ +Word32 hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = { + 0xbec8b439, 0x609d4952 /* -0.5095f, 0.7548f */ +}; + +static const Word32 accWindowNrgFac = 0x26666666; /* factor for accumulating filtered window energies 0.3 */ +static const Word32 oneMinusAccWindowNrgFac = 0x5999999a; /* 0.7 */ +static const Word32 invAttackRatioHighBr = 0x0ccccccd; /* inverted lower ratio limit for attacks 0.1*/ +static const Word32 invAttackRatioLowBr = 0x072b020c; /* 0.056 */ +static const Word32 minAttackNrg = 0x00001e84; /* minimum energy for attacks 1e+6 */ + + +/****************** Routines ****************************/ + + +/***************************************************************************** +* +* function name: InitBlockSwitching +* description: init Block Switching parameter. +* returns: TRUE if success +* +**********************************************************************************/ +Word16 InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, + const Word32 bitRate, const Word16 nChannels) +{ + /* select attackRatio */ + + if ((sub(nChannels,1)==0 && L_sub(bitRate, 24000) > 0) || + (sub(nChannels,1)>0 && bitRate > (nChannels * 16000))) { + blockSwitchingControl->invAttackRatio = invAttackRatioHighBr; + } + else { + blockSwitchingControl->invAttackRatio = invAttackRatioLowBr; + } + + return(TRUE); +} + +static Word16 suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = { + /* Attack in Window 0 */ {1, 3, 3, 1}, + /* Attack in Window 1 */ {1, 1, 3, 3}, + /* Attack in Window 2 */ {2, 1, 3, 2}, + /* Attack in Window 3 */ {3, 1, 3, 1}, + /* Attack in Window 4 */ {3, 1, 1, 3}, + /* Attack in Window 5 */ {3, 2, 1, 2}, + /* Attack in Window 6 */ {3, 3, 1, 1}, + /* Attack in Window 7 */ {3, 3, 1, 1} +}; + +/***************************************************************************** +* +* function name: BlockSwitching +* description: detect this frame whether there is an attack +* returns: TRUE if success +* +**********************************************************************************/ +Word16 BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, + Word16 *timeSignal, + Word32 sampleRate, + Word16 chIncrement) +{ + Word32 i, w; + Word32 enM1, enMax; + + /* Reset grouping info */ + for (i=0; igroupLen[i] = 0; + } + + + /* Search for position and amplitude of attack in last frame (1 windows delay) */ + blockSwitchingControl->maxWindowNrg = SrchMaxWithIndex( &blockSwitchingControl->windowNrg[0][BLOCK_SWITCH_WINDOWS-1], + &blockSwitchingControl->attackIndex, + BLOCK_SWITCH_WINDOWS); + + blockSwitchingControl->attackIndex = blockSwitchingControl->lastAttackIndex; + + /* Set grouping info */ + blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; + + for (i=0; igroupLen[i] = suggestedGroupingTable[blockSwitchingControl->attackIndex][i]; + } + + /* if the samplerate is less than 16000, it should be all the short block, avoid pre&post echo */ + if(sampleRate >= 16000) { + /* Save current window energy as last window energy */ + for (w=0; wwindowNrg[0][w] = blockSwitchingControl->windowNrg[1][w]; + blockSwitchingControl->windowNrgF[0][w] = blockSwitchingControl->windowNrgF[1][w]; + } + + + /* Calculate unfiltered and filtered energies in subwindows and combine to segments */ + CalcWindowEnergy(blockSwitchingControl, timeSignal, chIncrement, BLOCK_SWITCH_WINDOW_LEN); + + /* reset attack */ + blockSwitchingControl->attack = FALSE; + + enMax = 0; + enM1 = blockSwitchingControl->windowNrgF[0][BLOCK_SWITCH_WINDOWS-1]; + + for (w=0; waccWindowNrg); + enM1_Shf = norm_l(enM1); + windowNrgF_Shf = norm_l(blockSwitchingControl->windowNrgF[1][w]); + + accWindowNrg_Tmp = blockSwitchingControl->accWindowNrg << accWindowNrg_Shf; + enM1_Tmp = enM1 << enM1_Shf; + windowNrgF_Tmp = blockSwitchingControl->windowNrgF[1][w] << windowNrgF_Shf; + + /* a sliding average of the previous energies */ + blockSwitchingControl->accWindowNrg = (fixmul(oneMinusAccWindowNrgFac, accWindowNrg_Tmp) >> accWindowNrg_Shf) + + (fixmul(accWindowNrgFac, enM1_Tmp) >> enM1_Shf); + + + /* if the energy with the ratio is bigger than the average, and the attack and short block */ + if ((fixmul(windowNrgF_Tmp, blockSwitchingControl->invAttackRatio) >> windowNrgF_Shf) > + blockSwitchingControl->accWindowNrg ) { + blockSwitchingControl->attack = TRUE; + blockSwitchingControl->lastAttackIndex = w; + } + enM1 = blockSwitchingControl->windowNrgF[1][w]; + enMax = max(enMax, enM1); + } + + if (enMax < minAttackNrg) { + blockSwitchingControl->attack = FALSE; + } + } + else + { + blockSwitchingControl->attack = TRUE; + } + + /* Check if attack spreads over frame border */ + if ((!blockSwitchingControl->attack) && (blockSwitchingControl->lastattack)) { + + if (blockSwitchingControl->attackIndex == TRANS_FAC-1) { + blockSwitchingControl->attack = TRUE; + } + + blockSwitchingControl->lastattack = FALSE; + } + else { + blockSwitchingControl->lastattack = blockSwitchingControl->attack; + } + + blockSwitchingControl->windowSequence = blockSwitchingControl->nextwindowSequence; + + + if (blockSwitchingControl->attack) { + blockSwitchingControl->nextwindowSequence = SHORT_WINDOW; + } + else { + blockSwitchingControl->nextwindowSequence = LONG_WINDOW; + } + + /* update short block group */ + if (blockSwitchingControl->nextwindowSequence == SHORT_WINDOW) { + + if (blockSwitchingControl->windowSequence== LONG_WINDOW) { + blockSwitchingControl->windowSequence = START_WINDOW; + } + + if (blockSwitchingControl->windowSequence == STOP_WINDOW) { + blockSwitchingControl->windowSequence = SHORT_WINDOW; + blockSwitchingControl->noOfGroups = 3; + blockSwitchingControl->groupLen[0] = 3; + blockSwitchingControl->groupLen[1] = 3; + blockSwitchingControl->groupLen[2] = 2; + } + } + + /* update block type */ + if (blockSwitchingControl->nextwindowSequence == LONG_WINDOW) { + + if (blockSwitchingControl->windowSequence == SHORT_WINDOW) { + blockSwitchingControl->nextwindowSequence = STOP_WINDOW; + } + } + + return(TRUE); +} + + +/***************************************************************************** +* +* function name: SrchMaxWithIndex +* description: search for the biggest value in an array +* returns: the max value +* +**********************************************************************************/ +static Word32 SrchMaxWithIndex(const Word32 in[], Word16 *index, Word16 n) +{ + Word32 max; + Word32 i, idx; + + /* Search maximum value in array and return index and value */ + max = 0; + idx = 0; + + for (i = 0; i < n; i++) { + + if (in[i+1] > max) { + max = in[i+1]; + idx = i; + } + } + *index = idx; + + return(max); +} + +/***************************************************************************** +* +* function name: CalcWindowEnergy +* description: calculate the energy before iir-filter and after irr-filter +* returns: TRUE if success +* +**********************************************************************************/ +#ifndef ARMV5E +Word32 CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, + Word16 *timeSignal, + Word16 chIncrement, + Word16 windowLen) +{ + Word32 w, i, wOffset, tidx, ch; + Word32 accuUE, accuFE; + Word32 tempUnfiltered; + Word32 tempFiltered; + Word32 states0, states1; + Word32 Coeff0, Coeff1; + + + states0 = blockSwitchingControl->iirStates[0]; + states1 = blockSwitchingControl->iirStates[1]; + Coeff0 = hiPassCoeff[0]; + Coeff1 = hiPassCoeff[1]; + tidx = 0; + for (w=0; w < BLOCK_SWITCH_WINDOWS; w++) { + + accuUE = 0; + accuFE = 0; + + for(i=0; i> ENERGY_SHIFT; + accuFE += (tempFiltered * tempFiltered) >> ENERGY_SHIFT; + } + + blockSwitchingControl->windowNrg[1][w] = accuUE; + blockSwitchingControl->windowNrgF[1][w] = accuFE; + + } + + blockSwitchingControl->iirStates[0] = states0; + blockSwitchingControl->iirStates[1] = states1; + + return(TRUE); +} +#endif + +/***************************************************************************** +* +* function name: IIRFilter +* description: calculate the iir-filter for an array +* returns: the result after iir-filter +* +**********************************************************************************/ +static Word16 IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[]) +{ + Word32 accu1, accu2, accu3; + Word32 out; + + accu1 = L_mpy_ls(coeff[1], in); + accu3 = accu1 - states[0]; + accu2 = fixmul( coeff[0], states[1] ); + out = accu3 - accu2; + + states[0] = accu1; + states[1] = out; + + return round16(out); +} + + +static Word16 synchronizedBlockTypeTable[4][4] = { + /* LONG_WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW */ + /* LONG_WINDOW */{LONG_WINDOW, START_WINDOW, SHORT_WINDOW, STOP_WINDOW}, + /* START_WINDOW */{START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW}, + /* SHORT_WINDOW */{SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW}, + /* STOP_WINDOW */{STOP_WINDOW, SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW} +}; + + +/***************************************************************************** +* +* function name: SyncBlockSwitching +* description: update block type and group value +* returns: TRUE if success +* +**********************************************************************************/ +Word16 SyncBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, + BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, + const Word16 nChannels) +{ + Word16 i; + Word16 patchType = LONG_WINDOW; + + + if (nChannels == 1) { /* Mono */ + if (blockSwitchingControlLeft->windowSequence != SHORT_WINDOW) { + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; + + for (i=1; igroupLen[i] = 0; + } + } + } + else { /* Stereo common Window */ + patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft->windowSequence]; + patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight->windowSequence]; + + /* Set synchronized Blocktype */ + blockSwitchingControlLeft->windowSequence = patchType; + blockSwitchingControlRight->windowSequence = patchType; + + /* Synchronize grouping info */ + if(patchType != SHORT_WINDOW) { /* Long Blocks */ + /* Set grouping info */ + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlRight->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; + blockSwitchingControlRight->groupLen[0] = 1; + + for (i=1; igroupLen[i] = 0; + blockSwitchingControlRight->groupLen[i] = 0; + } + } + else { + + if (blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) { + /* Left Channel wins */ + blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups; + for (i=0; igroupLen[i] = blockSwitchingControlLeft->groupLen[i]; + } + } + else { + /* Right Channel wins */ + blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups; + for (i=0; igroupLen[i] = blockSwitchingControlRight->groupLen[i]; + } + } + } + } /*endif Mono or Stereo */ + + return(TRUE); +} diff --git a/media/libstagefright/codecs/aacenc/src/channel_map.c b/media/libstagefright/codecs/aacenc/src/channel_map.c new file mode 100644 index 0000000000000000000000000000000000000000..247293ba64ed85789d6aab494aedcb538a60443b --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/channel_map.c @@ -0,0 +1,123 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: channel_map.c + + Content: channel mapping functions + +*******************************************************************************/ + +#include "channel_map.h" +#include "bitenc.h" +#include "psy_const.h" +#include "qc_data.h" + +static const Word16 maxChannelBits = MAXBITS_COEF; + +static Word16 initElement(ELEMENT_INFO* elInfo, ELEMENT_TYPE elType) +{ + Word16 error=0; + + elInfo->elType=elType; + + switch(elInfo->elType) { + + case ID_SCE: + elInfo->nChannelsInEl=1; + + elInfo->ChannelIndex[0]=0; + + elInfo->instanceTag=0; + break; + + case ID_CPE: + + elInfo->nChannelsInEl=2; + + elInfo->ChannelIndex[0]=0; + elInfo->ChannelIndex[1]=1; + + elInfo->instanceTag=0; + break; + + default: + error=1; + } + + return error; +} + + +Word16 InitElementInfo (Word16 nChannels, ELEMENT_INFO* elInfo) +{ + Word16 error; + error = 0; + + switch(nChannels) { + + case 1: + initElement(elInfo, ID_SCE); + break; + + case 2: + initElement(elInfo, ID_CPE); + break; + + default: + error=4; + } + + return error; +} + + +Word16 InitElementBits(ELEMENT_BITS *elementBits, + ELEMENT_INFO elInfo, + Word32 bitrateTot, + Word16 averageBitsTot, + Word16 staticBitsTot) +{ + Word16 error; + error = 0; + + switch(elInfo.nChannelsInEl) { + case 1: + elementBits->chBitrate = bitrateTot; + elementBits->averageBits = averageBitsTot - staticBitsTot; + elementBits->maxBits = maxChannelBits; + + elementBits->maxBitResBits = maxChannelBits - averageBitsTot; + elementBits->maxBitResBits = elementBits->maxBitResBits - (elementBits->maxBitResBits & 7); + elementBits->bitResLevel = elementBits->maxBitResBits; + elementBits->relativeBits = 0x4000; /* 1.0f/2 */ + break; + + case 2: + elementBits->chBitrate = bitrateTot >> 1; + elementBits->averageBits = averageBitsTot - staticBitsTot; + elementBits->maxBits = maxChannelBits << 1; + + elementBits->maxBitResBits = (maxChannelBits << 1) - averageBitsTot; + elementBits->maxBitResBits = elementBits->maxBitResBits - (elementBits->maxBitResBits & 7); + elementBits->bitResLevel = elementBits->maxBitResBits; + elementBits->relativeBits = 0x4000; /* 1.0f/2 */ + break; + + default: + error = 1; + } + return error; +} diff --git a/media/libstagefright/codecs/aacenc/src/dyn_bits.c b/media/libstagefright/codecs/aacenc/src/dyn_bits.c new file mode 100644 index 0000000000000000000000000000000000000000..3deaccaa8386e7c2a178f92c13b1d5419fe5f907 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/dyn_bits.c @@ -0,0 +1,545 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: dyn_bits.c + + Content: Noiseless coder module functions + +*******************************************************************************/ + +#include "aac_rom.h" +#include "dyn_bits.h" +#include "bit_cnt.h" +#include "psy_const.h" + + +/***************************************************************************** +* +* function name: buildBitLookUp +* description: count bits using all possible tables +* +*****************************************************************************/ +static void +buildBitLookUp(const Word16 *quantSpectrum, + const Word16 maxSfb, + const Word16 *sfbOffset, + const UWord16 *sfbMax, + Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + SECTION_INFO * sectionInfo) +{ + Word32 i; + + for (i=0; i maxMergeGain) { + maxMergeGain = mergeGainLookUp[i]; + *maxNdx = i; + } + } + return extract_l(maxMergeGain); +} + + + +static Word16 +CalcMergeGain(const SECTION_INFO *sectionInfo, + Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const Word16 *sideInfoTab, + const Word16 ndx1, + const Word16 ndx2) +{ + Word32 SplitBits; + Word32 MergeBits; + Word32 MergeGain; + + /* + Bit amount for splitted sections + */ + SplitBits = sectionInfo[ndx1].sectionBits + sectionInfo[ndx2].sectionBits; + + MergeBits = sideInfoTab[sectionInfo[ndx1].sfbCnt + sectionInfo[ndx2].sfbCnt] + + findMinMergeBits(bitLookUp[ndx1], bitLookUp[ndx2]); + MergeGain = (SplitBits - MergeBits); + + return extract_l(MergeGain); +} + +/* + sectioning Stage 0:find minimum codbooks +*/ + +static void +gmStage0(SECTION_INFO * sectionInfo, + Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const Word16 maxSfb) +{ + Word32 i; + + for (i=0; icodeBook != sectionInfo_e->codeBook) + break; + sectionInfo_s->sfbCnt += 1; + sectionInfo_s->sectionBits += sectionInfo_e->sectionBits; + + mergeBitLookUp(bitLookUp[mergeStart], bitLookUp[mergeEnd]); + } + + sectionInfo_s->sectionBits += sideInfoTab[sectionInfo_s->sfbCnt]; + sectionInfo[mergeEnd - 1].sfbStart = sectionInfo_s->sfbStart; /* speed up prev search */ + + mergeStart = mergeEnd; + + + } while (mergeStart - maxSfb < 0); +} + +/* + sectioning Stage 2:greedy merge algorithm, merge connected sections with + maximum bit gain until no more gain is possible +*/ +static void +gmStage2(SECTION_INFO *sectionInfo, + Word16 mergeGainLookUp[MAX_SFB_LONG], + Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const Word16 maxSfb, + const Word16 *sideInfoTab) +{ + Word16 i; + + for (i=0; i+sectionInfo[i].sfbCntnoOfSections = 0; + sectionData->huffmanBits = 0; + sectionData->sideInfoBits = 0; + + + if (sectionData->maxSfbPerGroup == 0) + return; + + /* + loop trough groups + */ + for (grpNdx=0; grpNdxsfbCnt; grpNdx+=sectionData->sfbPerGroup) { + + sectionInfo = sectionData->sectionInfo + sectionData->noOfSections; + + buildBitLookUp(quantSpectrum, + sectionData->maxSfbPerGroup, + sfbOffset + grpNdx, + maxValueInSfb + grpNdx, + bitLookUp, + sectionInfo); + + /* + 0.Stage + */ + gmStage0(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup); + + /* + 1.Stage + */ + gmStage1(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup, sideInfoTab); + + + /* + 2.Stage + */ + gmStage2(sectionInfo, + mergeGainLookUp, + bitLookUp, + sectionData->maxSfbPerGroup, + sideInfoTab); + + + /* + compress output, calculate total huff and side bits + */ + for (i=0; imaxSfbPerGroup; i+=sectionInfo[i].sfbCnt) { + findBestBook(bitLookUp[i], &(sectionInfo[i].codeBook)); + sectionInfo[i].sfbStart = sectionInfo[i].sfbStart + grpNdx; + + sectionData->huffmanBits = (sectionData->huffmanBits + + (sectionInfo[i].sectionBits - sideInfoTab[sectionInfo[i].sfbCnt])); + sectionData->sideInfoBits = (sectionData->sideInfoBits + sideInfoTab[sectionInfo[i].sfbCnt]); + sectionData->sectionInfo[sectionData->noOfSections] = sectionInfo[i]; + sectionData->noOfSections = sectionData->noOfSections + 1; + } + } +} + + +/******************************************************************************* +* +* functionname: scfCount +* returns : --- +* description : count bits used by scalefactors. +* +********************************************************************************/ +static void scfCount(const Word16 *scalefacGain, + const UWord16 *maxValueInSfb, + SECTION_DATA * sectionData) + +{ + SECTION_INFO *psectionInfo; + SECTION_INFO *psectionInfom; + + /* counter */ + Word32 i = 0; /* section counter */ + Word32 j = 0; /* sfb counter */ + Word32 k = 0; /* current section auxiliary counter */ + Word32 m = 0; /* other section auxiliary counter */ + Word32 n = 0; /* other sfb auxiliary counter */ + + /* further variables */ + Word32 lastValScf = 0; + Word32 deltaScf = 0; + Flag found = 0; + Word32 scfSkipCounter = 0; + + + sectionData->scalefacBits = 0; + + + if (scalefacGain == NULL) { + return; + } + + lastValScf = 0; + sectionData->firstScf = 0; + + psectionInfo = sectionData->sectionInfo; + for (i=0; inoOfSections; i++) { + + if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO) { + sectionData->firstScf = psectionInfo->sfbStart; + lastValScf = scalefacGain[sectionData->firstScf]; + break; + } + psectionInfo += 1; + } + + psectionInfo = sectionData->sectionInfo; + for (i=0; inoOfSections; i++, psectionInfo += 1) { + + if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO + && psectionInfo->codeBook != CODE_BOOK_PNS_NO) { + for (j = psectionInfo->sfbStart; + j < (psectionInfo->sfbStart + psectionInfo->sfbCnt); j++) { + /* check if we can repeat the last value to save bits */ + + if (maxValueInSfb[j] == 0) { + found = 0; + + if (scfSkipCounter == 0) { + /* end of section */ + + if (j - ((psectionInfo->sfbStart + psectionInfo->sfbCnt) - 1) == 0) { + found = 0; + } + else { + for (k = j + 1; k < psectionInfo->sfbStart + psectionInfo->sfbCnt; k++) { + + if (maxValueInSfb[k] != 0) { + int tmp = L_abs(scalefacGain[k] - lastValScf); + found = 1; + + if ( tmp < CODE_BOOK_SCF_LAV) { + /* save bits */ + deltaScf = 0; + } + else { + /* do not save bits */ + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + scfSkipCounter = 0; + } + break; + } + /* count scalefactor skip */ + scfSkipCounter = scfSkipCounter + 1; + } + } + + psectionInfom = psectionInfo + 1; + /* search for the next maxValueInSfb[] != 0 in all other sections */ + for (m = i + 1; (m < sectionData->noOfSections) && (found == 0); m++) { + + if ((psectionInfom->codeBook != CODE_BOOK_ZERO_NO) && + (psectionInfom->codeBook != CODE_BOOK_PNS_NO)) { + for (n = psectionInfom->sfbStart; + n < (psectionInfom->sfbStart + psectionInfom->sfbCnt); n++) { + + if (maxValueInSfb[n] != 0) { + found = 1; + + if ( (abs_s(scalefacGain[n] - lastValScf) < CODE_BOOK_SCF_LAV)) { + deltaScf = 0; + } + else { + deltaScf = (lastValScf - scalefacGain[j]); + lastValScf = scalefacGain[j]; + scfSkipCounter = 0; + } + break; + } + /* count scalefactor skip */ + scfSkipCounter = scfSkipCounter + 1; + } + } + + psectionInfom += 1; + } + + if (found == 0) { + deltaScf = 0; + scfSkipCounter = 0; + } + } + else { + deltaScf = 0; + scfSkipCounter = scfSkipCounter - 1; + } + } + else { + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + } + sectionData->scalefacBits += bitCountScalefactorDelta(deltaScf); + } + } + } +} + + +typedef Word16 (*lookUpTable)[CODE_BOOK_ESC_NDX + 1]; + + +Word16 +dynBitCount(const Word16 *quantSpectrum, + const UWord16 *maxValueInSfb, + const Word16 *scalefac, + const Word16 blockType, + const Word16 sfbCnt, + const Word16 maxSfbPerGroup, + const Word16 sfbPerGroup, + const Word16 *sfbOffset, + SECTION_DATA *sectionData) +{ + sectionData->blockType = blockType; + sectionData->sfbCnt = sfbCnt; + sectionData->sfbPerGroup = sfbPerGroup; + if(sfbPerGroup) + sectionData->noOfGroups = sfbCnt/sfbPerGroup; + else + sectionData->noOfGroups = 0x7fff; + sectionData->maxSfbPerGroup = maxSfbPerGroup; + + noiselessCounter(sectionData, + sectionData->mergeGainLookUp, + (lookUpTable)sectionData->bitLookUp, + quantSpectrum, + maxValueInSfb, + sfbOffset, + blockType); + + scfCount(scalefac, + maxValueInSfb, + sectionData); + + + return (sectionData->huffmanBits + sectionData->sideInfoBits + + sectionData->scalefacBits); +} + diff --git a/media/libstagefright/codecs/aacenc/src/grp_data.c b/media/libstagefright/codecs/aacenc/src/grp_data.c new file mode 100644 index 0000000000000000000000000000000000000000..08d9a762a35bc50e112906771328dff45e21aa95 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/grp_data.c @@ -0,0 +1,188 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: grp_data.c + + Content: Short block grouping function + +*******************************************************************************/ + +#include "basic_op.h" +#include "psy_const.h" +#include "interface.h" +#include "grp_data.h" + +/***************************************************************************** +* +* function name: groupShortData +* description: group short data for next quantization and coding +* +**********************************************************************************/ +void +groupShortData(Word32 *mdctSpectrum, + Word32 *tmpSpectrum, + SFB_THRESHOLD *sfbThreshold, + SFB_ENERGY *sfbEnergy, + SFB_ENERGY *sfbEnergyMS, + SFB_ENERGY *sfbSpreadedEnergy, + const Word16 sfbCnt, + const Word16 *sfbOffset, + const Word16 *sfbMinSnr, + Word16 *groupedSfbOffset, + Word16 *maxSfbPerGroup, + Word16 *groupedSfbMinSnr, + const Word16 noOfGroups, + const Word16 *groupLen) +{ + Word32 i, j; + Word32 line; + Word32 sfb; + Word32 grp; + Word32 wnd; + Word32 offset; + Word32 highestSfb; + + /* for short: regroup and */ + /* cumulate energies und thresholds group-wise . */ + + /* calculate sfbCnt */ + highestSfb = 0; + for (wnd=0; wnd=highestSfb; sfb--) { + for (line=(sfbOffset[sfb + 1] - 1); line>=sfbOffset[sfb]; line--) { + + if (mdctSpectrum[wnd*FRAME_LEN_SHORT+line] != 0) break; + } + + if (line >= sfbOffset[sfb]) break; + } + highestSfb = max(highestSfb, sfb); + } + + if (highestSfb < 0) { + highestSfb = 0; + } + *maxSfbPerGroup = highestSfb + 1; + + /* calculate sfbOffset */ + i = 0; + offset = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbCnt; sfb++) { + groupedSfbOffset[i] = offset + sfbOffset[sfb] * groupLen[grp]; + i += 1; + } + offset += groupLen[grp] * FRAME_LEN_SHORT; + } + groupedSfbOffset[i] = FRAME_LEN_LONG; + i += 1; + + /* calculate minSnr */ + i = 0; + offset = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbCnt; sfb++) { + groupedSfbMinSnr[i] = sfbMinSnr[sfb]; + i += 1; + } + offset += groupLen[grp] * FRAME_LEN_SHORT; + } + + + /* sum up sfbThresholds */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbCnt; sfb++) { + Word32 thresh = sfbThreshold->sfbShort[wnd][sfb]; + for (j=1; jsfbShort[wnd+j][sfb]); + } + sfbThreshold->sfbLong[i] = thresh; + i += 1; + } + wnd += groupLen[grp]; + } + + /* sum up sfbEnergies left/right */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbCnt; sfb++) { + Word32 energy = sfbEnergy->sfbShort[wnd][sfb]; + for (j=1; jsfbShort[wnd+j][sfb]); + } + sfbEnergy->sfbLong[i] = energy; + i += 1; + } + wnd += groupLen[grp]; + } + + /* sum up sfbEnergies mid/side */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbCnt; sfb++) { + Word32 energy = sfbEnergyMS->sfbShort[wnd][sfb]; + for (j=1; jsfbShort[wnd+j][sfb]); + } + sfbEnergyMS->sfbLong[i] = energy; + i += 1; + } + wnd += groupLen[grp]; + } + + /* sum up sfbSpreadedEnergies */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbCnt; sfb++) { + Word32 energy = sfbSpreadedEnergy->sfbShort[wnd][sfb]; + for (j=1; jsfbShort[wnd+j][sfb]); + } + sfbSpreadedEnergy->sfbLong[i] = energy; + i += 1; + } + wnd += groupLen[grp]; + } + + /* re-group spectrum */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbCnt; sfb++) { + for (j = 0; j < groupLen[grp]; j++) { + Word16 lineOffset = FRAME_LEN_SHORT * (wnd + j); + for (line = lineOffset + sfbOffset[sfb]; line < lineOffset + sfbOffset[sfb+1]; line++) { + tmpSpectrum[i] = mdctSpectrum[line]; + i = i + 1; + } + } + } + wnd += groupLen[grp]; + } + + for(i=0;imaxSfbPerGroup = maxSfbPerGroup; + psyOutCh->sfbCnt = groupedSfbCnt; + if(noOfGroups) + psyOutCh->sfbPerGroup = groupedSfbCnt/ noOfGroups; + else + psyOutCh->sfbPerGroup = 0x7fff; + psyOutCh->windowSequence = windowSequence; + psyOutCh->windowShape = windowShape; + psyOutCh->mdctScale = mdctScale; + psyOutCh->mdctSpectrum = groupedMdctSpectrum; + psyOutCh->sfbEnergy = groupedSfbEnergy->sfbLong; + psyOutCh->sfbThreshold = groupedSfbThreshold->sfbLong; + psyOutCh->sfbSpreadedEnergy = groupedSfbSpreadedEnergy->sfbLong; + + tmpV = psyOutCh->sfbOffsets; + for(j=0; jsfbMinSnr; + for(j=0;jgroupingMask = mask; + + if (windowSequence != SHORT_WINDOW) { + psyOutCh->sfbEnSumLR = sfbEnergySumLR.sfbLong; + psyOutCh->sfbEnSumMS = sfbEnergySumMS.sfbLong; + } + else { + Word32 i; + Word32 accuSumMS=0; + Word32 accuSumLR=0; + Word32 *pSumMS = sfbEnergySumMS.sfbShort; + Word32 *pSumLR = sfbEnergySumLR.sfbShort; + + for (i=TRANS_FAC; i; i--) { + accuSumLR = L_add(accuSumLR, *pSumLR); pSumLR++; + accuSumMS = L_add(accuSumMS, *pSumMS); pSumMS++; + } + psyOutCh->sfbEnSumMS = accuSumMS; + psyOutCh->sfbEnSumLR = accuSumLR; + } +} diff --git a/media/libstagefright/codecs/aacenc/src/line_pe.c b/media/libstagefright/codecs/aacenc/src/line_pe.c new file mode 100644 index 0000000000000000000000000000000000000000..da5764777a22321fced5e406104a0a252db0b001 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/line_pe.c @@ -0,0 +1,145 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: line_pe.c + + Content: Perceptual entropie module functions + +*******************************************************************************/ + +#include "basic_op.h" +#include "oper_32b.h" +#include "typedef.h" +#include "line_pe.h" + + +static const Word16 C1_I = 12; /* log(8.0)/log(2) *4 */ +static const Word32 C2_I = 10830; /* log(2.5)/log(2) * 1024 * 4 * 2 */ +static const Word16 C3_I = 573; /* (1-C2/C1) *1024 */ + + +/***************************************************************************** +* +* function name: prepareSfbPe +* description: constants that do not change during successive pe calculations +* +**********************************************************************************/ +void prepareSfbPe(PE_DATA *peData, + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], + Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB], + const Word16 nChannels, + const Word16 peOffset) +{ + Word32 sfbGrp, sfb; + Word32 ch; + + for(ch=0; chpeChannelData[ch]; + for(sfbGrp=0;sfbGrpsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + peChanData->sfbNLines4[sfbGrp+sfb] = sfbNRelevantLines[ch][sfbGrp+sfb]; + sfbNRelevantLines[ch][sfbGrp+sfb] = sfbNRelevantLines[ch][sfbGrp+sfb] >> 2; + peChanData->sfbLdEnergy[sfbGrp+sfb] = logSfbEnergy[ch][sfbGrp+sfb]; + } + } + } + peData->offset = peOffset; +} + + +/***************************************************************************** +* +* function name: calcSfbPe +* description: constPart is sfbPe without the threshold part n*ld(thr) or n*C3*ld(thr) +* +**********************************************************************************/ +void calcSfbPe(PE_DATA *peData, + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + const Word16 nChannels) +{ + Word32 ch; + Word32 sfbGrp, sfb; + Word32 nLines4; + Word32 ldThr, ldRatio; + Word32 pe, constPart, nActiveLines; + + peData->pe = peData->offset; + peData->constPart = 0; + peData->nActiveLines = 0; + for(ch=0; chpeChannelData[ch]; + const Word32 *sfbEnergy = psyOutChan->sfbEnergy; + const Word32 *sfbThreshold = psyOutChan->sfbThreshold; + + pe = 0; + constPart = 0; + nActiveLines = 0; + + for(sfbGrp=0; sfbGrpsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + Word32 nrg = sfbEnergy[sfbGrp+sfb]; + Word32 thres = sfbThreshold[sfbGrp+sfb]; + Word32 sfbLDEn = peChanData->sfbLdEnergy[sfbGrp+sfb]; + + if (nrg > thres) { + ldThr = iLog4(thres); + + ldRatio = sfbLDEn - ldThr; + + nLines4 = peChanData->sfbNLines4[sfbGrp+sfb]; + + /* sfbPe = nl*log2(en/thr)*/ + if (ldRatio >= C1_I) { + peChanData->sfbPe[sfbGrp+sfb] = (nLines4*ldRatio + 8) >> 4; + peChanData->sfbConstPart[sfbGrp+sfb] = ((nLines4*sfbLDEn)) >> 4; + } + else { + /* sfbPe = nl*(c2 + c3*log2(en/thr))*/ + peChanData->sfbPe[sfbGrp+sfb] = extract_l((L_mpy_wx( + (C2_I + C3_I * ldRatio * 2) << 4, nLines4) + 4) >> 3); + peChanData->sfbConstPart[sfbGrp+sfb] = extract_l(( L_mpy_wx( + (C2_I + C3_I * sfbLDEn * 2) << 4, nLines4) + 4) >> 3); + nLines4 = (nLines4 * C3_I + (1024<<1)) >> 10; + } + peChanData->sfbNActiveLines[sfbGrp+sfb] = nLines4 >> 2; + } + else { + peChanData->sfbPe[sfbGrp+sfb] = 0; + peChanData->sfbConstPart[sfbGrp+sfb] = 0; + peChanData->sfbNActiveLines[sfbGrp+sfb] = 0; + } + pe = pe + peChanData->sfbPe[sfbGrp+sfb]; + constPart = constPart + peChanData->sfbConstPart[sfbGrp+sfb]; + nActiveLines = nActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb]; + } + } + + peChanData->pe = saturate(pe); + peChanData->constPart = saturate(constPart); + peChanData->nActiveLines = saturate(nActiveLines); + + + pe += peData->pe; + peData->pe = saturate(pe); + constPart += peData->constPart; + peData->constPart = saturate(constPart); + nActiveLines += peData->nActiveLines; + peData->nActiveLines = saturate(nActiveLines); + } +} diff --git a/media/libstagefright/codecs/aacenc/src/memalign.c b/media/libstagefright/codecs/aacenc/src/memalign.c new file mode 100644 index 0000000000000000000000000000000000000000..7d2035274cf82324a6d04d209082b0f36b0cb8a9 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/memalign.c @@ -0,0 +1,107 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/******************************************************************************* + File: mem_align.c + + Content: Memory alloc alignments functions + +*******************************************************************************/ + + +#include "memalign.h" + +/***************************************************************************** +* +* function name: mem_malloc +* description: malloc the alignments memory +* returns: the point of the memory +* +**********************************************************************************/ +void * +mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID) +{ + int ret; + unsigned char *mem_ptr; + VO_MEM_INFO MemInfo; + + if (!alignment) { + + MemInfo.Flag = 0; + MemInfo.Size = size + 1; + ret = pMemop->Alloc(CodecID, &MemInfo); + if(ret != 0) + return 0; + mem_ptr = (unsigned char *)MemInfo.VBuffer; + + pMemop->Set(CodecID, mem_ptr, 0, size + 1); + + *mem_ptr = (unsigned char)1; + + return ((void *)(mem_ptr+1)); + } else { + unsigned char *tmp; + + MemInfo.Flag = 0; + MemInfo.Size = size + alignment; + ret = pMemop->Alloc(CodecID, &MemInfo); + if(ret != 0) + return 0; + + tmp = (unsigned char *)MemInfo.VBuffer; + + pMemop->Set(CodecID, tmp, 0, size + alignment); + + mem_ptr = + (unsigned char *) ((unsigned int) (tmp + alignment - 1) & + (~((unsigned int) (alignment - 1)))); + + if (mem_ptr == tmp) + mem_ptr += alignment; + + *(mem_ptr - 1) = (unsigned char) (mem_ptr - tmp); + + return ((void *)mem_ptr); + } + + return(0); +} + + +/***************************************************************************** +* +* function name: mem_free +* description: free the memory +* +*******************************************************************************/ +void +mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID) +{ + + unsigned char *ptr; + + if (mem_ptr == 0) + return; + + ptr = mem_ptr; + + ptr -= *(ptr - 1); + + pMemop->Free(CodecID, ptr); +} + + + diff --git a/media/libstagefright/codecs/aacenc/src/ms_stereo.c b/media/libstagefright/codecs/aacenc/src/ms_stereo.c new file mode 100644 index 0000000000000000000000000000000000000000..c83d07bf9f7fb1fb1a35e2ff21d5bcab4990d8e6 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/ms_stereo.c @@ -0,0 +1,139 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: ms_stereo.c + + Content: MS stereo processing function + +*******************************************************************************/ + +#include "basic_op.h" +#include "oper_32b.h" +#include "psy_const.h" +#include "ms_stereo.h" + + +/******************************************************************************** +* +* function name: MsStereoProcessing +* description: detect use ms stereo or not +* if ((min(thrLn, thrRn)*min(thrLn, thrRn))/(enMn*enSn)) +* >= ((thrLn *thrRn)/(enLn*enRn)) then ms stereo +* +**********************************************************************************/ +void MsStereoProcessing(Word32 *sfbEnergyLeft, + Word32 *sfbEnergyRight, + const Word32 *sfbEnergyMid, + const Word32 *sfbEnergySide, + Word32 *mdctSpectrumLeft, + Word32 *mdctSpectrumRight, + Word32 *sfbThresholdLeft, + Word32 *sfbThresholdRight, + Word32 *sfbSpreadedEnLeft, + Word32 *sfbSpreadedEnRight, + Word16 *msDigest, + Word16 *msMask, + const Word16 sfbCnt, + const Word16 sfbPerGroup, + const Word16 maxSfbPerGroup, + const Word16 *sfbOffset) { + Word32 temp; + Word32 sfb,sfboffs, j; + Word32 msMaskTrueSomewhere = 0; + Word32 msMaskFalseSomewhere = 0; + + for (sfb=0; sfb> 8) + 1); + + temp = pnms - pnlr; + if( temp > 0 ){ + + msMask[idx] = 1; + msMaskTrueSomewhere = 1; + + for (j=sfbOffset[idx]; j> 1); + right = (mdctSpectrumRight[j] >> 1); + mdctSpectrumLeft[j] = left + right; + mdctSpectrumRight[j] = left - right; + } + + sfbThresholdLeft[idx] = minThreshold; + sfbThresholdRight[idx] = minThreshold; + sfbEnergyLeft[idx] = sfbEnergyMid[idx]; + sfbEnergyRight[idx] = sfbEnergySide[idx]; + + sfbSpreadedEnRight[idx] = min(sfbSpreadedEnLeft[idx],sfbSpreadedEnRight[idx]) >> 1; + sfbSpreadedEnLeft[idx] = sfbSpreadedEnRight[idx]; + + } + else { + msMask[idx] = 0; + msMaskFalseSomewhere = 1; + } + } + if ( msMaskTrueSomewhere ) { + if(msMaskFalseSomewhere ) { + *msDigest = SI_MS_MASK_SOME; + } else { + *msDigest = SI_MS_MASK_ALL; + } + } else { + *msDigest = SI_MS_MASK_NONE; + } + } + +} diff --git a/media/libstagefright/codecs/aacenc/src/pre_echo_control.c b/media/libstagefright/codecs/aacenc/src/pre_echo_control.c new file mode 100644 index 0000000000000000000000000000000000000000..f59216e2a44289c30a1ad458bd4a96a35de170c7 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/pre_echo_control.c @@ -0,0 +1,113 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: pre_echo_control.c + + Content: Pre echo control functions + +*******************************************************************************/ + +#include "basic_op.h" +#include "oper_32b.h" + +#include "oper_32b.h" +#include "pre_echo_control.h" + + +/***************************************************************************** +* +* function name:InitPreEchoControl +* description: init pre echo control parameter +* +*****************************************************************************/ +void InitPreEchoControl(Word32 *pbThresholdNm1, + Word16 numPb, + Word32 *pbThresholdQuiet) +{ + Word16 pb; + + for(pb=0; pb 0 ) { + for(i = 0; i < numPb; i++) { + tmpThreshold1 = pbThresholdNm1[i] >> (scaling-1); + tmpThreshold2 = L_mpy_ls(pbThreshold[i], minRemainingThresholdFactor); + + /* copy thresholds to internal memory */ + pbThresholdNm1[i] = pbThreshold[i]; + + + if(pbThreshold[i] > tmpThreshold1) { + pbThreshold[i] = tmpThreshold1; + } + + if(tmpThreshold2 > pbThreshold[i]) { + pbThreshold[i] = tmpThreshold2; + } + + } + } + else { + scaling = -scaling; + for(i = 0; i < numPb; i++) { + + tmpThreshold1 = pbThresholdNm1[i] << 1; + tmpThreshold2 = L_mpy_ls(pbThreshold[i], minRemainingThresholdFactor); + + /* copy thresholds to internal memory */ + pbThresholdNm1[i] = pbThreshold[i]; + + + if(((pbThreshold[i] >> scaling) > tmpThreshold1)) { + pbThreshold[i] = tmpThreshold1 << scaling; + } + + if(tmpThreshold2 > pbThreshold[i]) { + pbThreshold[i] = tmpThreshold2; + } + + } + } +} + diff --git a/media/libstagefright/codecs/aacenc/src/psy_configuration.c b/media/libstagefright/codecs/aacenc/src/psy_configuration.c new file mode 100644 index 0000000000000000000000000000000000000000..586e00ff085f1546a5a42a1e9b720757bbffb8fe --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/psy_configuration.c @@ -0,0 +1,505 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: psy_configuration.c + + Content: Psychoaccoustic configuration functions + +*******************************************************************************/ + +#include "basic_op.h" +#include "oper_32b.h" +#include "psy_configuration.h" +#include "adj_thr.h" +#include "aac_rom.h" + + + +#define BARC_SCALE 100 /* integer barc values are scaled with 100 */ +#define LOG2_1000 301 /* log2*1000 */ +#define PI2_1000 1571 /* pi/2*1000*/ +#define ATAN_COEF1 3560 /* 1000/0.280872f*/ +#define ATAN_COEF2 281 /* 1000*0.280872f*/ + + +typedef struct{ + Word32 sampleRate; + const UWord8 *paramLong; + const UWord8 *paramShort; +}SFB_INFO_TAB; + +static const Word16 ABS_LEV = 20; +static const Word16 BARC_THR_QUIET[] = {15, 10, 7, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 5, 10, 20, 30}; + + + +static const Word16 max_bark = 24; /* maximum bark-value */ +static const Word16 maskLow = 30; /* in 1dB/bark */ +static const Word16 maskHigh = 15; /* in 1*dB/bark */ +static const Word16 c_ratio = 0x0029; /* pow(10.0f, -(29.0f/10.0f)) */ + +static const Word16 maskLowSprEnLong = 30; /* in 1dB/bark */ +static const Word16 maskHighSprEnLong = 20; /* in 1dB/bark */ +static const Word16 maskHighSprEnLongLowBr = 15; /* in 1dB/bark */ +static const Word16 maskLowSprEnShort = 20; /* in 1dB/bark */ +static const Word16 maskHighSprEnShort = 15; /* in 1dB/bark */ +static const Word16 c_minRemainingThresholdFactor = 0x0148; /* 0.01 *(1 << 15)*/ +static const Word32 c_maxsnr = 0x66666666; /* upper limit is -1 dB */ +static const Word32 c_minsnr = 0x00624dd3; /* lower limit is -25 dB */ + +static const Word32 c_maxClipEnergyLong = 0x77359400; /* 2.0e9f*/ +static const Word32 c_maxClipEnergyShort = 0x01dcd650; /* 2.0e9f/(AACENC_TRANS_FAC*AACENC_TRANS_FAC)*/ + + +Word32 GetSRIndex(Word32 sampleRate) +{ + if (92017 <= sampleRate) return 0; + if (75132 <= sampleRate) return 1; + if (55426 <= sampleRate) return 2; + if (46009 <= sampleRate) return 3; + if (37566 <= sampleRate) return 4; + if (27713 <= sampleRate) return 5; + if (23004 <= sampleRate) return 6; + if (18783 <= sampleRate) return 7; + if (13856 <= sampleRate) return 8; + if (11502 <= sampleRate) return 9; + if (9391 <= sampleRate) return 10; + + return 11; +} + + +/********************************************************************************* +* +* function name: atan_1000 +* description: calculates 1000*atan(x/1000) +* based on atan approx for x > 0 +* atan(x) = x/((float)1.0f+(float)0.280872f*x*x) if x < 1 +* = pi/2 - x/((float)0.280872f +x*x) if x >= 1 +* return: 1000*atan(x/1000) +* +**********************************************************************************/ +static Word16 atan_1000(Word32 val) +{ + Word32 y; + + + if(L_sub(val, 1000) < 0) { + y = extract_l(((1000 * val) / (1000 + ((val * val) / ATAN_COEF1)))); + } + else { + y = PI2_1000 - ((1000 * val) / (ATAN_COEF2 + ((val * val) / 1000))); + } + + return extract_l(y); +} + + +/***************************************************************************** +* +* function name: BarcLineValue +* description: Calculates barc value for one frequency line +* returns: barc value of line * BARC_SCALE +* input: number of lines in transform, index of line to check, Fs +* output: +* +*****************************************************************************/ +static Word16 BarcLineValue(Word16 noOfLines, Word16 fftLine, Word32 samplingFreq) +{ + Word32 center_freq, temp, bvalFFTLine; + + /* center frequency of fft line */ + center_freq = (fftLine * samplingFreq) / (noOfLines << 1); + temp = atan_1000((center_freq << 2) / (3*10)); + bvalFFTLine = + (26600 * atan_1000((center_freq*76) / 100) + 7*temp*temp) / (2*1000*1000 / BARC_SCALE); + + return saturate(bvalFFTLine); +} + +/***************************************************************************** +* +* function name: initThrQuiet +* description: init thredhold in quiet +* +*****************************************************************************/ +static void initThrQuiet(Word16 numPb, + Word16 *pbOffset, + Word16 *pbBarcVal, + Word32 *pbThresholdQuiet) { + Word16 i; + Word16 barcThrQuiet; + + for(i=0; i0) + bv1 = (pbBarcVal[i] + pbBarcVal[i-1]) >> 1; + else + bv1 = pbBarcVal[i] >> 1; + + + if (i < (numPb - 1)) + bv2 = (pbBarcVal[i] + pbBarcVal[i+1]) >> 1; + else { + bv2 = pbBarcVal[i]; + } + + bv1 = min((bv1 / BARC_SCALE), max_bark); + bv2 = min((bv2 / BARC_SCALE), max_bark); + + barcThrQuiet = min(BARC_THR_QUIET[bv1], BARC_THR_QUIET[bv2]); + + + /* + we calculate + pow(10.0f,(float)(barcThrQuiet - ABS_LEV)*0.1)*(float)ABS_LOW*(pbOffset[i+1] - pbOffset[i]); + */ + + pbThresholdQuiet[i] = pow2_xy((((barcThrQuiet - ABS_LEV) * 100) + + LOG2_1000*(14+2*LOG_NORM_PCM)), LOG2_1000) * (pbOffset[i+1] - pbOffset[i]); + } +} + + +/***************************************************************************** +* +* function name: initSpreading +* description: init energy spreading parameter +* +*****************************************************************************/ +static void initSpreading(Word16 numPb, + Word16 *pbBarcValue, + Word16 *pbMaskLoFactor, + Word16 *pbMaskHiFactor, + Word16 *pbMaskLoFactorSprEn, + Word16 *pbMaskHiFactorSprEn, + const Word32 bitrate, + const Word16 blockType) +{ + Word16 i; + Word16 maskLowSprEn, maskHighSprEn; + + + if (sub(blockType, SHORT_WINDOW) != 0) { + maskLowSprEn = maskLowSprEnLong; + + if (bitrate > 22000) + maskHighSprEn = maskHighSprEnLong; + else + maskHighSprEn = maskHighSprEnLongLowBr; + } + else { + maskLowSprEn = maskLowSprEnShort; + maskHighSprEn = maskHighSprEnShort; + } + + for(i=0; i 0) { + Word32 dbVal; + Word16 dbark = pbBarcValue[i] - pbBarcValue[i-1]; + + /* + we calulate pow(10.0f, -0.1*dbVal/BARC_SCALE) + */ + dbVal = (maskHigh * dbark); + pbMaskHiFactor[i] = round16(pow2_xy(L_negate(dbVal), (Word32)LOG2_1000)); /* 0.301 log10(2) */ + + dbVal = (maskLow * dbark); + pbMaskLoFactor[i-1] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000)); + + + dbVal = (maskHighSprEn * dbark); + pbMaskHiFactorSprEn[i] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000)); + dbVal = (maskLowSprEn * dbark); + pbMaskLoFactorSprEn[i-1] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000)); + } + else { + pbMaskHiFactor[i] = 0; + pbMaskLoFactor[numPb-1] = 0; + + pbMaskHiFactorSprEn[i] = 0; + pbMaskLoFactorSprEn[numPb-1] = 0; + } + } + +} + + +/***************************************************************************** +* +* function name: initBarcValues +* description: init bark value +* +*****************************************************************************/ +static void initBarcValues(Word16 numPb, + Word16 *pbOffset, + Word16 numLines, + Word32 samplingFrequency, + Word16 *pbBval) +{ + Word16 i; + Word16 pbBval0, pbBval1; + + pbBval0 = 0; + + for(i=0; i> 1; + pbBval0 = pbBval1; + } +} + + +/***************************************************************************** +* +* function name: initMinSnr +* description: calculate min snr parameter +* minSnr(n) = 1/(2^sfbPemin(n)/w(n) - 1.5) +* +*****************************************************************************/ +static void initMinSnr(const Word32 bitrate, + const Word32 samplerate, + const Word16 numLines, + const Word16 *sfbOffset, + const Word16 *pbBarcVal, + const Word16 sfbActive, + Word16 *sfbMinSnr) +{ + Word16 sfb; + Word16 barcWidth; + Word16 pePerWindow; + Word32 pePart; + Word32 snr; + Word16 pbVal0, pbVal1, shift; + + /* relative number of active barks */ + + + pePerWindow = bits2pe(extract_l((bitrate * numLines) / samplerate)); + + pbVal0 = 0; + + for (sfb=0; sfb 0x00008000) + { + shift = norm_l(snr); + snr = Div_32(0x00008000 << shift, snr << shift); + } + else + { + snr = 0x7fffffff; + } + + /* upper limit is -1 dB */ + snr = min(snr, c_maxsnr); + /* lower limit is -25 dB */ + snr = max(snr, c_minsnr); + sfbMinSnr[sfb] = round16(snr); + } + +} + +/***************************************************************************** +* +* function name: InitPsyConfigurationLong +* description: init long block psychoacoustic configuration +* +*****************************************************************************/ +Word16 InitPsyConfigurationLong(Word32 bitrate, + Word32 samplerate, + Word16 bandwidth, + PSY_CONFIGURATION_LONG *psyConf) +{ + Word32 samplerateindex; + Word16 sfbBarcVal[MAX_SFB_LONG]; + Word16 sfb; + + /* + init sfb table + */ + samplerateindex = GetSRIndex(samplerate); + psyConf->sfbCnt = sfBandTotalLong[samplerateindex]; + psyConf->sfbOffset = sfBandTabLong + sfBandTabLongOffset[samplerateindex]; + psyConf->sampRateIdx = samplerateindex; + + /* + calculate barc values for each pb + */ + initBarcValues(psyConf->sfbCnt, + psyConf->sfbOffset, + psyConf->sfbOffset[psyConf->sfbCnt], + samplerate, + sfbBarcVal); + + /* + init thresholds in quiet + */ + initThrQuiet(psyConf->sfbCnt, + psyConf->sfbOffset, + sfbBarcVal, + psyConf->sfbThresholdQuiet); + + /* + calculate spreading function + */ + initSpreading(psyConf->sfbCnt, + sfbBarcVal, + psyConf->sfbMaskLowFactor, + psyConf->sfbMaskHighFactor, + psyConf->sfbMaskLowFactorSprEn, + psyConf->sfbMaskHighFactorSprEn, + bitrate, + LONG_WINDOW); + + /* + init ratio + */ + psyConf->ratio = c_ratio; + + psyConf->maxAllowedIncreaseFactor = 2; + psyConf->minRemainingThresholdFactor = c_minRemainingThresholdFactor; /* 0.01 *(1 << 15)*/ + + psyConf->clipEnergy = c_maxClipEnergyLong; + psyConf->lowpassLine = extract_l((bandwidth<<1) * FRAME_LEN_LONG / samplerate); + + for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) { + if (sub(psyConf->sfbOffset[sfb], psyConf->lowpassLine) >= 0) + break; + } + psyConf->sfbActive = sfb; + + /* + calculate minSnr + */ + initMinSnr(bitrate, + samplerate, + psyConf->sfbOffset[psyConf->sfbCnt], + psyConf->sfbOffset, + sfbBarcVal, + psyConf->sfbActive, + psyConf->sfbMinSnr); + + + return(0); +} + +/***************************************************************************** +* +* function name: InitPsyConfigurationShort +* description: init short block psychoacoustic configuration +* +*****************************************************************************/ +Word16 InitPsyConfigurationShort(Word32 bitrate, + Word32 samplerate, + Word16 bandwidth, + PSY_CONFIGURATION_SHORT *psyConf) +{ + Word32 samplerateindex; + Word16 sfbBarcVal[MAX_SFB_SHORT]; + Word16 sfb; + /* + init sfb table + */ + samplerateindex = GetSRIndex(samplerate); + psyConf->sfbCnt = sfBandTotalShort[samplerateindex]; + psyConf->sfbOffset = sfBandTabShort + sfBandTabShortOffset[samplerateindex]; + psyConf->sampRateIdx = samplerateindex; + /* + calculate barc values for each pb + */ + initBarcValues(psyConf->sfbCnt, + psyConf->sfbOffset, + psyConf->sfbOffset[psyConf->sfbCnt], + samplerate, + sfbBarcVal); + + /* + init thresholds in quiet + */ + initThrQuiet(psyConf->sfbCnt, + psyConf->sfbOffset, + sfbBarcVal, + psyConf->sfbThresholdQuiet); + + /* + calculate spreading function + */ + initSpreading(psyConf->sfbCnt, + sfbBarcVal, + psyConf->sfbMaskLowFactor, + psyConf->sfbMaskHighFactor, + psyConf->sfbMaskLowFactorSprEn, + psyConf->sfbMaskHighFactorSprEn, + bitrate, + SHORT_WINDOW); + + /* + init ratio + */ + psyConf->ratio = c_ratio; + + psyConf->maxAllowedIncreaseFactor = 2; + psyConf->minRemainingThresholdFactor = c_minRemainingThresholdFactor; + + psyConf->clipEnergy = c_maxClipEnergyShort; + + psyConf->lowpassLine = extract_l(((bandwidth << 1) * FRAME_LEN_SHORT) / samplerate); + + for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) { + + if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine) + break; + } + psyConf->sfbActive = sfb; + + /* + calculate minSnr + */ + initMinSnr(bitrate, + samplerate, + psyConf->sfbOffset[psyConf->sfbCnt], + psyConf->sfbOffset, + sfbBarcVal, + psyConf->sfbActive, + psyConf->sfbMinSnr); + + return(0); +} + diff --git a/media/libstagefright/codecs/aacenc/src/psy_main.c b/media/libstagefright/codecs/aacenc/src/psy_main.c new file mode 100644 index 0000000000000000000000000000000000000000..8746a725d4f49366c98aa8240c3616a5573c3d44 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/psy_main.c @@ -0,0 +1,810 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: psy_main.c + + Content: Psychoacoustic major functions + +*******************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "psy_const.h" +#include "block_switch.h" +#include "transform.h" +#include "spreading.h" +#include "pre_echo_control.h" +#include "band_nrg.h" +#include "psy_configuration.h" +#include "psy_data.h" +#include "ms_stereo.h" +#include "interface.h" +#include "psy_main.h" +#include "grp_data.h" +#include "tns_func.h" +#include "memalign.h" + +/* long start short stop */ +static Word16 blockType2windowShape[] = {KBD_WINDOW,SINE_WINDOW,SINE_WINDOW,KBD_WINDOW}; + +/* + forward definitions +*/ +static Word16 advancePsychLong(PSY_DATA* psyData, + TNS_DATA* tnsData, + PSY_CONFIGURATION_LONG *hPsyConfLong, + PSY_OUT_CHANNEL* psyOutChannel, + Word32 *pScratchTns, + const TNS_DATA *tnsData2, + const Word16 ch); + +static Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS], + const PSY_CONFIGURATION_LONG *hPsyConfLong); + +static Word16 advancePsychShort(PSY_DATA* psyData, + TNS_DATA* tnsData, + const PSY_CONFIGURATION_SHORT *hPsyConfShort, + PSY_OUT_CHANNEL* psyOutChannel, + Word32 *pScratchTns, + const TNS_DATA *tnsData2, + const Word16 ch); + +static Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS], + const PSY_CONFIGURATION_SHORT *hPsyConfShort); + + +/***************************************************************************** +* +* function name: PsyNew +* description: allocates memory for psychoacoustic +* returns: an error code +* input: pointer to a psych handle +* +*****************************************************************************/ +Word16 PsyNew(PSY_KERNEL *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP) +{ + Word16 i; + Word32 *mdctSpectrum; + Word32 *scratchTNS; + Word16 *mdctDelayBuffer; + + mdctSpectrum = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC); + if(NULL == mdctSpectrum) + return 1; + + scratchTNS = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC); + if(NULL == scratchTNS) + { + return 1; + } + + mdctDelayBuffer = (Word16 *)mem_malloc(pMemOP, nChan * BLOCK_SWITCHING_OFFSET * sizeof(Word16), 32, VO_INDEX_ENC_AAC); + if(NULL == mdctDelayBuffer) + { + return 1; + } + + for (i=0; ipsyData[i].mdctDelayBuffer = mdctDelayBuffer + i*BLOCK_SWITCHING_OFFSET; + hPsy->psyData[i].mdctSpectrum = mdctSpectrum + i*FRAME_LEN_LONG; + } + + hPsy->pScratchTns = scratchTNS; + + return 0; +} + + +/***************************************************************************** +* +* function name: PsyDelete +* description: allocates memory for psychoacoustic +* returns: an error code +* +*****************************************************************************/ +Word16 PsyDelete(PSY_KERNEL *hPsy, VO_MEM_OPERATOR *pMemOP) +{ + Word32 nch; + + if(hPsy) + { + if(hPsy->psyData[0].mdctDelayBuffer) + mem_free(pMemOP, hPsy->psyData[0].mdctDelayBuffer, VO_INDEX_ENC_AAC); + + if(hPsy->psyData[0].mdctSpectrum) + mem_free(pMemOP, hPsy->psyData[0].mdctSpectrum, VO_INDEX_ENC_AAC); + + for (nch=0; nchpsyData[nch].mdctDelayBuffer = NULL; + hPsy->psyData[nch].mdctSpectrum = NULL; + } + + if(hPsy->pScratchTns) + { + mem_free(pMemOP, hPsy->pScratchTns, VO_INDEX_ENC_AAC); + hPsy->pScratchTns = NULL; + } + } + + return 0; +} + + +/***************************************************************************** +* +* function name: PsyOutNew +* description: allocates memory for psyOut struc +* returns: an error code +* input: pointer to a psych handle +* +*****************************************************************************/ +Word16 PsyOutNew(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP) +{ + pMemOP->Set(VO_INDEX_ENC_AAC, hPsyOut, 0, sizeof(PSY_OUT)); + /* + alloc some more stuff, tbd + */ + return 0; +} + +/***************************************************************************** +* +* function name: PsyOutDelete +* description: allocates memory for psychoacoustic +* returns: an error code +* +*****************************************************************************/ +Word16 PsyOutDelete(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP) +{ + hPsyOut=NULL; + return 0; +} + + +/***************************************************************************** +* +* function name: psyMainInit +* description: initializes psychoacoustic +* returns: an error code +* +*****************************************************************************/ + +Word16 psyMainInit(PSY_KERNEL *hPsy, + Word32 sampleRate, + Word32 bitRate, + Word16 channels, + Word16 tnsMask, + Word16 bandwidth) +{ + Word16 ch, err; + Word32 channelBitRate = bitRate/channels; + + err = InitPsyConfigurationLong(channelBitRate, + sampleRate, + bandwidth, + &(hPsy->psyConfLong)); + + if (!err) { + hPsy->sampleRateIdx = hPsy->psyConfLong.sampRateIdx; + err = InitTnsConfigurationLong(bitRate, sampleRate, channels, + &hPsy->psyConfLong.tnsConf, &hPsy->psyConfLong, tnsMask&2); + } + + if (!err) + err = InitPsyConfigurationShort(channelBitRate, + sampleRate, + bandwidth, + &hPsy->psyConfShort); + if (!err) { + err = InitTnsConfigurationShort(bitRate, sampleRate, channels, + &hPsy->psyConfShort.tnsConf, &hPsy->psyConfShort, tnsMask&1); + } + + if (!err) + for(ch=0;ch < channels;ch++){ + + InitBlockSwitching(&hPsy->psyData[ch].blockSwitchingControl, + bitRate, channels); + + InitPreEchoControl(hPsy->psyData[ch].sfbThresholdnm1, + hPsy->psyConfLong.sfbCnt, + hPsy->psyConfLong.sfbThresholdQuiet); + hPsy->psyData[ch].mdctScalenm1 = 0; + } + + return(err); +} + +/***************************************************************************** +* +* function name: psyMain +* description: psychoacoustic main function +* returns: an error code +* +* This function assumes that enough input data is in the modulo buffer. +* +*****************************************************************************/ + +Word16 psyMain(Word16 nChannels, + ELEMENT_INFO *elemInfo, + Word16 *timeSignal, + PSY_DATA psyData[MAX_CHANNELS], + TNS_DATA tnsData[MAX_CHANNELS], + PSY_CONFIGURATION_LONG *hPsyConfLong, + PSY_CONFIGURATION_SHORT *hPsyConfShort, + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT *psyOutElement, + Word32 *pScratchTns, + Word32 sampleRate) +{ + Word16 maxSfbPerGroup[MAX_CHANNELS]; + Word16 mdctScalingArray[MAX_CHANNELS]; + + Word16 ch; /* counts through channels */ + Word16 sfb; /* counts through scalefactor bands */ + Word16 line; /* counts through lines */ + Word16 channels; + Word16 maxScale; + + channels = elemInfo->nChannelsInEl; + maxScale = 0; + + /* block switching */ + for(ch = 0; ch < channels; ch++) { + BlockSwitching(&psyData[ch].blockSwitchingControl, + timeSignal+elemInfo->ChannelIndex[ch], + sampleRate, + nChannels); + } + + /* synch left and right block type */ + SyncBlockSwitching(&psyData[0].blockSwitchingControl, + &psyData[1].blockSwitchingControl, + channels); + + /* transform + and get maxScale (max mdctScaling) for all channels */ + for(ch=0; chChannelIndex[ch], + nChannels, + psyData[ch].mdctSpectrum, + &(mdctScalingArray[ch]), + psyData[ch].blockSwitchingControl.windowSequence); + maxScale = max(maxScale, mdctScalingArray[ch]); + } + + /* common scaling for all channels */ + for (ch=0; ch 0) { + Word32 *Spectrum = psyData[ch].mdctSpectrum; + for(line=0; line> scaleDiff; + Spectrum++; + } + } + psyData[ch].mdctScale = maxScale; + } + + for (ch=0; chsfbCnt-1; sfb>=0; sfb--) { + for (line=hPsyConfLong->sfbOffset[sfb+1] - 1; line>=hPsyConfLong->sfbOffset[sfb]; line--) { + + if (psyData[ch].mdctSpectrum[line] != 0) break; + } + if (line >= hPsyConfLong->sfbOffset[sfb]) break; + } + maxSfbPerGroup[ch] = sfb + 1; + + /* Calc bandwise energies for mid and side channel + Do it only if 2 channels exist */ + + if (ch == 1) + advancePsychLongMS(psyData, hPsyConfLong); + } + else { + advancePsychShort(&psyData[ch], + &tnsData[ch], + hPsyConfShort, + &psyOutChannel[ch], + pScratchTns, + &tnsData[1 - ch], + ch); + + /* Calc bandwise energies for mid and side channel + Do it only if 2 channels exist */ + + if (ch == 1) + advancePsychShortMS (psyData, hPsyConfShort); + } + } + + /* group short data */ + for(ch=0; chsfbCnt, + hPsyConfShort->sfbOffset, + hPsyConfShort->sfbMinSnr, + psyOutElement->groupedSfbOffset[ch], + &maxSfbPerGroup[ch], + psyOutElement->groupedSfbMinSnr[ch], + psyData[ch].blockSwitchingControl.noOfGroups, + psyData[ch].blockSwitchingControl.groupLen); + } + } + + +#if (MAX_CHANNELS>1) + /* + stereo Processing + */ + if (channels == 2) { + psyOutElement->toolsInfo.msDigest = MS_NONE; + maxSfbPerGroup[0] = maxSfbPerGroup[1] = max(maxSfbPerGroup[0], maxSfbPerGroup[1]); + + + if (psyData[0].blockSwitchingControl.windowSequence != SHORT_WINDOW) + MsStereoProcessing(psyData[0].sfbEnergy.sfbLong, + psyData[1].sfbEnergy.sfbLong, + psyData[0].sfbEnergyMS.sfbLong, + psyData[1].sfbEnergyMS.sfbLong, + psyData[0].mdctSpectrum, + psyData[1].mdctSpectrum, + psyData[0].sfbThreshold.sfbLong, + psyData[1].sfbThreshold.sfbLong, + psyData[0].sfbSpreadedEnergy.sfbLong, + psyData[1].sfbSpreadedEnergy.sfbLong, + (Word16*)&psyOutElement->toolsInfo.msDigest, + (Word16*)psyOutElement->toolsInfo.msMask, + hPsyConfLong->sfbCnt, + hPsyConfLong->sfbCnt, + maxSfbPerGroup[0], + (const Word16*)hPsyConfLong->sfbOffset); + else + MsStereoProcessing(psyData[0].sfbEnergy.sfbLong, + psyData[1].sfbEnergy.sfbLong, + psyData[0].sfbEnergyMS.sfbLong, + psyData[1].sfbEnergyMS.sfbLong, + psyData[0].mdctSpectrum, + psyData[1].mdctSpectrum, + psyData[0].sfbThreshold.sfbLong, + psyData[1].sfbThreshold.sfbLong, + psyData[0].sfbSpreadedEnergy.sfbLong, + psyData[1].sfbSpreadedEnergy.sfbLong, + (Word16*)&psyOutElement->toolsInfo.msDigest, + (Word16*)psyOutElement->toolsInfo.msMask, + psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt, + hPsyConfShort->sfbCnt, + maxSfbPerGroup[0], + (const Word16*)psyOutElement->groupedSfbOffset[0]); + } + +#endif /* (MAX_CHANNELS>1) */ + + /* + build output + */ + for(ch=0;chsfbCnt, + hPsyConfLong->sfbOffset, + maxSfbPerGroup[ch], + hPsyConfLong->sfbMinSnr, + psyData[ch].blockSwitchingControl.noOfGroups, + psyData[ch].blockSwitchingControl.groupLen, + &psyOutChannel[ch]); + else + BuildInterface(psyData[ch].mdctSpectrum, + psyData[ch].mdctScale, + &psyData[ch].sfbThreshold, + &psyData[ch].sfbEnergy, + &psyData[ch].sfbSpreadedEnergy, + psyData[ch].sfbEnergySum, + psyData[ch].sfbEnergySumMS, + SHORT_WINDOW, + SINE_WINDOW, + psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt, + psyOutElement->groupedSfbOffset[ch], + maxSfbPerGroup[ch], + psyOutElement->groupedSfbMinSnr[ch], + psyData[ch].blockSwitchingControl.noOfGroups, + psyData[ch].blockSwitchingControl.groupLen, + &psyOutChannel[ch]); + } + + return(0); /* no error */ +} + +/***************************************************************************** +* +* function name: advancePsychLong +* description: psychoacoustic for long blocks +* +*****************************************************************************/ + +static Word16 advancePsychLong(PSY_DATA* psyData, + TNS_DATA* tnsData, + PSY_CONFIGURATION_LONG *hPsyConfLong, + PSY_OUT_CHANNEL* psyOutChannel, + Word32 *pScratchTns, + const TNS_DATA* tnsData2, + const Word16 ch) +{ + Word32 i; + Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */ + Word32 clipEnergy = hPsyConfLong->clipEnergy >> normEnergyShift; + Word32 *data0, *data1, tdata; + + /* low pass */ + data0 = psyData->mdctSpectrum + hPsyConfLong->lowpassLine; + for(i=hPsyConfLong->lowpassLine; imdctSpectrum, + hPsyConfLong->sfbOffset, + hPsyConfLong->sfbActive, + psyData->sfbEnergy.sfbLong, + &psyData->sfbEnergySum.sfbLong); + + /* + TNS detect + */ + TnsDetect(tnsData, + hPsyConfLong->tnsConf, + pScratchTns, + (const Word16*)hPsyConfLong->sfbOffset, + psyData->mdctSpectrum, + 0, + psyData->blockSwitchingControl.windowSequence, + psyData->sfbEnergy.sfbLong); + + /* TnsSync */ + if (ch == 1) { + TnsSync(tnsData, + tnsData2, + hPsyConfLong->tnsConf, + 0, + psyData->blockSwitchingControl.windowSequence); + } + + /* Tns Encoder */ + TnsEncode(&psyOutChannel->tnsInfo, + tnsData, + hPsyConfLong->sfbCnt, + hPsyConfLong->tnsConf, + hPsyConfLong->lowpassLine, + psyData->mdctSpectrum, + 0, + psyData->blockSwitchingControl.windowSequence); + + /* first part of threshold calculation */ + data0 = psyData->sfbEnergy.sfbLong; + data1 = psyData->sfbThreshold.sfbLong; + for (i=hPsyConfLong->sfbCnt; i; i--) { + tdata = L_mpy_ls(*data0++, hPsyConfLong->ratio); + *data1++ = min(tdata, clipEnergy); + } + + /* Calc sfb-bandwise mdct-energies for left and right channel again */ + if (tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive!=0) { + Word16 tnsStartBand = hPsyConfLong->tnsConf.tnsStartBand; + CalcBandEnergy( psyData->mdctSpectrum, + hPsyConfLong->sfbOffset+tnsStartBand, + hPsyConfLong->sfbActive - tnsStartBand, + psyData->sfbEnergy.sfbLong+tnsStartBand, + &psyData->sfbEnergySum.sfbLong); + + data0 = psyData->sfbEnergy.sfbLong; + tdata = psyData->sfbEnergySum.sfbLong; + for (i=0; isfbEnergySum.sfbLong = tdata; + } + + + /* spreading energy */ + SpreadingMax(hPsyConfLong->sfbCnt, + hPsyConfLong->sfbMaskLowFactor, + hPsyConfLong->sfbMaskHighFactor, + psyData->sfbThreshold.sfbLong); + + /* threshold in quiet */ + data0 = psyData->sfbThreshold.sfbLong; + data1 = hPsyConfLong->sfbThresholdQuiet; + for (i=hPsyConfLong->sfbCnt; i; i--) + { + *data0 = max(*data0, (*data1 >> normEnergyShift)); + data0++; data1++; + } + + /* preecho control */ + if (psyData->blockSwitchingControl.windowSequence == STOP_WINDOW) { + data0 = psyData->sfbThresholdnm1; + for (i=hPsyConfLong->sfbCnt; i; i--) { + *data0++ = MAX_32; + } + psyData->mdctScalenm1 = 0; + } + + PreEchoControl( psyData->sfbThresholdnm1, + hPsyConfLong->sfbCnt, + hPsyConfLong->maxAllowedIncreaseFactor, + hPsyConfLong->minRemainingThresholdFactor, + psyData->sfbThreshold.sfbLong, + psyData->mdctScale, + psyData->mdctScalenm1); + psyData->mdctScalenm1 = psyData->mdctScale; + + + if (psyData->blockSwitchingControl.windowSequence== START_WINDOW) { + data0 = psyData->sfbThresholdnm1; + for (i=hPsyConfLong->sfbCnt; i; i--) { + *data0++ = MAX_32; + } + psyData->mdctScalenm1 = 0; + } + + /* apply tns mult table on cb thresholds */ + ApplyTnsMultTableToRatios(hPsyConfLong->tnsConf.tnsRatioPatchLowestCb, + hPsyConfLong->tnsConf.tnsStartBand, + tnsData->dataRaw.tnsLong.subBlockInfo, + psyData->sfbThreshold.sfbLong); + + + /* spreaded energy */ + data0 = psyData->sfbSpreadedEnergy.sfbLong; + data1 = psyData->sfbEnergy.sfbLong; + for (i=hPsyConfLong->sfbCnt; i; i--) { + //psyData->sfbSpreadedEnergy.sfbLong[i] = psyData->sfbEnergy.sfbLong[i]; + *data0++ = *data1++; + } + + /* spreading energy */ + SpreadingMax(hPsyConfLong->sfbCnt, + hPsyConfLong->sfbMaskLowFactorSprEn, + hPsyConfLong->sfbMaskHighFactorSprEn, + psyData->sfbSpreadedEnergy.sfbLong); + + return 0; +} + +/***************************************************************************** +* +* function name: advancePsychLongMS +* description: update mdct-energies for left add or minus right channel +* for long block +* +*****************************************************************************/ +static Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS], + const PSY_CONFIGURATION_LONG *hPsyConfLong) +{ + CalcBandEnergyMS(psyData[0].mdctSpectrum, + psyData[1].mdctSpectrum, + hPsyConfLong->sfbOffset, + hPsyConfLong->sfbActive, + psyData[0].sfbEnergyMS.sfbLong, + &psyData[0].sfbEnergySumMS.sfbLong, + psyData[1].sfbEnergyMS.sfbLong, + &psyData[1].sfbEnergySumMS.sfbLong); + + return 0; +} + + +/***************************************************************************** +* +* function name: advancePsychShort +* description: psychoacoustic for short blocks +* +*****************************************************************************/ + +static Word16 advancePsychShort(PSY_DATA* psyData, + TNS_DATA* tnsData, + const PSY_CONFIGURATION_SHORT *hPsyConfShort, + PSY_OUT_CHANNEL* psyOutChannel, + Word32 *pScratchTns, + const TNS_DATA *tnsData2, + const Word16 ch) +{ + Word32 w; + Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */ + Word32 clipEnergy = hPsyConfShort->clipEnergy >> normEnergyShift; + Word32 wOffset = 0; + Word32 *data0, *data1; + + for(w = 0; w < TRANS_FAC; w++) { + Word32 i, tdata; + + /* low pass */ + data0 = psyData->mdctSpectrum + wOffset + hPsyConfShort->lowpassLine; + for(i=hPsyConfShort->lowpassLine; imdctSpectrum+wOffset, + hPsyConfShort->sfbOffset, + hPsyConfShort->sfbActive, + psyData->sfbEnergy.sfbShort[w], + &psyData->sfbEnergySum.sfbShort[w]); + /* + TNS + */ + TnsDetect(tnsData, + hPsyConfShort->tnsConf, + pScratchTns, + (const Word16*)hPsyConfShort->sfbOffset, + psyData->mdctSpectrum+wOffset, + w, + psyData->blockSwitchingControl.windowSequence, + psyData->sfbEnergy.sfbShort[w]); + + /* TnsSync */ + if (ch == 1) { + TnsSync(tnsData, + tnsData2, + hPsyConfShort->tnsConf, + w, + psyData->blockSwitchingControl.windowSequence); + } + + TnsEncode(&psyOutChannel->tnsInfo, + tnsData, + hPsyConfShort->sfbCnt, + hPsyConfShort->tnsConf, + hPsyConfShort->lowpassLine, + psyData->mdctSpectrum+wOffset, + w, + psyData->blockSwitchingControl.windowSequence); + + /* first part of threshold calculation */ + data0 = psyData->sfbThreshold.sfbShort[w]; + data1 = psyData->sfbEnergy.sfbShort[w]; + for (i=hPsyConfShort->sfbCnt; i; i--) { + tdata = L_mpy_ls(*data1++, hPsyConfShort->ratio); + *data0++ = min(tdata, clipEnergy); + } + + /* Calc sfb-bandwise mdct-energies for left and right channel again */ + if (tnsData->dataRaw.tnsShort.subBlockInfo[w].tnsActive != 0) { + Word16 tnsStartBand = hPsyConfShort->tnsConf.tnsStartBand; + CalcBandEnergy( psyData->mdctSpectrum+wOffset, + hPsyConfShort->sfbOffset+tnsStartBand, + (hPsyConfShort->sfbActive - tnsStartBand), + psyData->sfbEnergy.sfbShort[w]+tnsStartBand, + &psyData->sfbEnergySum.sfbShort[w]); + + tdata = psyData->sfbEnergySum.sfbShort[w]; + data0 = psyData->sfbEnergy.sfbShort[w]; + for (i=tnsStartBand; i; i--) + tdata += *data0++; + + psyData->sfbEnergySum.sfbShort[w] = tdata; + } + + /* spreading */ + SpreadingMax(hPsyConfShort->sfbCnt, + hPsyConfShort->sfbMaskLowFactor, + hPsyConfShort->sfbMaskHighFactor, + psyData->sfbThreshold.sfbShort[w]); + + + /* threshold in quiet */ + data0 = psyData->sfbThreshold.sfbShort[w]; + data1 = hPsyConfShort->sfbThresholdQuiet; + for (i=hPsyConfShort->sfbCnt; i; i--) + { + *data0 = max(*data0, (*data1 >> normEnergyShift)); + + data0++; data1++; + } + + + /* preecho */ + PreEchoControl( psyData->sfbThresholdnm1, + hPsyConfShort->sfbCnt, + hPsyConfShort->maxAllowedIncreaseFactor, + hPsyConfShort->minRemainingThresholdFactor, + psyData->sfbThreshold.sfbShort[w], + psyData->mdctScale, + w==0 ? psyData->mdctScalenm1 : psyData->mdctScale); + + /* apply tns mult table on cb thresholds */ + ApplyTnsMultTableToRatios( hPsyConfShort->tnsConf.tnsRatioPatchLowestCb, + hPsyConfShort->tnsConf.tnsStartBand, + tnsData->dataRaw.tnsShort.subBlockInfo[w], + psyData->sfbThreshold.sfbShort[w]); + + /* spreaded energy */ + data0 = psyData->sfbSpreadedEnergy.sfbShort[w]; + data1 = psyData->sfbEnergy.sfbShort[w]; + for (i=hPsyConfShort->sfbCnt; i; i--) { + *data0++ = *data1++; + } + SpreadingMax(hPsyConfShort->sfbCnt, + hPsyConfShort->sfbMaskLowFactorSprEn, + hPsyConfShort->sfbMaskHighFactorSprEn, + psyData->sfbSpreadedEnergy.sfbShort[w]); + + wOffset += FRAME_LEN_SHORT; + } /* for TRANS_FAC */ + + psyData->mdctScalenm1 = psyData->mdctScale; + + return 0; +} + +/***************************************************************************** +* +* function name: advancePsychShortMS +* description: update mdct-energies for left add or minus right channel +* for short block +* +*****************************************************************************/ +static Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS], + const PSY_CONFIGURATION_SHORT *hPsyConfShort) +{ + Word32 w, wOffset; + wOffset = 0; + for(w=0; wsfbOffset, + hPsyConfShort->sfbActive, + psyData[0].sfbEnergyMS.sfbShort[w], + &psyData[0].sfbEnergySumMS.sfbShort[w], + psyData[1].sfbEnergyMS.sfbShort[w], + &psyData[1].sfbEnergySumMS.sfbShort[w]); + wOffset += FRAME_LEN_SHORT; + } + + return 0; +} diff --git a/media/libstagefright/codecs/aacenc/src/qc_main.c b/media/libstagefright/codecs/aacenc/src/qc_main.c new file mode 100644 index 0000000000000000000000000000000000000000..a568020496d056cc873ef7f1b909e0a8ada6e59d --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/qc_main.c @@ -0,0 +1,580 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: qc_main.c + + Content: Quantizing & coding functions + +*******************************************************************************/ + +#include "basic_op.h" +#include "oper_32b.h" +#include "qc_main.h" +#include "quantize.h" +#include "interface.h" +#include "adj_thr.h" +#include "sf_estim.h" +#include "stat_bits.h" +#include "bit_cnt.h" +#include "dyn_bits.h" +#include "channel_map.h" +#include "memalign.h" + + +typedef enum{ + FRAME_LEN_BYTES_MODULO = 1, + FRAME_LEN_BYTES_INT = 2 +}FRAME_LEN_RESULT_MODE; + +static const Word16 maxFillElemBits = 7 + 270*8; + +/* forward declarations */ + +static Word16 calcMaxValueInSfb(Word16 sfbCnt, + Word16 maxSfbPerGroup, + Word16 sfbPerGroup, + Word16 sfbOffset[MAX_GROUPED_SFB], + Word16 quantSpectrum[FRAME_LEN_LONG], + UWord16 maxValue[MAX_GROUPED_SFB]); + + +/***************************************************************************** +* +* function name: calcFrameLen +* description: estimate the frame length according the bitrates +* +*****************************************************************************/ +static Word16 calcFrameLen(Word32 bitRate, + Word32 sampleRate, + FRAME_LEN_RESULT_MODE mode) +{ + + Word32 result; + Word32 quot; + + result = (FRAME_LEN_LONG >> 3) * bitRate; + quot = result / sampleRate; + + + if (mode == FRAME_LEN_BYTES_MODULO) { + result -= quot * sampleRate; + } + else { /* FRAME_LEN_BYTES_INT */ + result = quot; + } + + return result; +} + +/***************************************************************************** +* +* function name:framePadding +* description: Calculates if padding is needed for actual frame +* returns: paddingOn or not +* +*****************************************************************************/ +static Word16 framePadding(Word32 bitRate, + Word32 sampleRate, + Word32 *paddingRest) +{ + Word16 paddingOn; + Word16 difference; + + paddingOn = 0; + + difference = calcFrameLen( bitRate, + sampleRate, + FRAME_LEN_BYTES_MODULO ); + *paddingRest = *paddingRest - difference; + + + if (*paddingRest <= 0 ) { + paddingOn = 1; + *paddingRest = *paddingRest + sampleRate; + } + + return paddingOn; +} + + +/********************************************************************************* +* +* function name: QCOutNew +* description: init qcout parameter +* returns: 0 if success +* +**********************************************************************************/ + +Word16 QCOutNew(QC_OUT *hQC, Word16 nChannels, VO_MEM_OPERATOR *pMemOP) +{ + Word32 i; + Word16 *quantSpec; + Word16 *scf; + UWord16 *maxValueInSfb; + + quantSpec = (Word16 *)mem_malloc(pMemOP, nChannels * FRAME_LEN_LONG * sizeof(Word16), 32, VO_INDEX_ENC_AAC); + if(NULL == quantSpec) + return 1; + scf = (Word16 *)mem_malloc(pMemOP, nChannels * MAX_GROUPED_SFB * sizeof(Word16), 32, VO_INDEX_ENC_AAC); + if(NULL == scf) + { + return 1; + } + maxValueInSfb = (UWord16 *)mem_malloc(pMemOP, nChannels * MAX_GROUPED_SFB * sizeof(UWord16), 32, VO_INDEX_ENC_AAC); + if(NULL == maxValueInSfb) + { + return 1; + } + + for (i=0; iqcChannel[i].quantSpec = quantSpec + i*FRAME_LEN_LONG; + + hQC->qcChannel[i].maxValueInSfb = maxValueInSfb + i*MAX_GROUPED_SFB; + + hQC->qcChannel[i].scf = scf + i*MAX_GROUPED_SFB; + } + + return 0; +} + + +/********************************************************************************* +* +* function name: QCOutDelete +* description: unint qcout parameter +* returns: 0 if success +* +**********************************************************************************/ +void QCOutDelete(QC_OUT* hQC, VO_MEM_OPERATOR *pMemOP) +{ + Word32 i; + if(hQC) + { + if(hQC->qcChannel[0].quantSpec); + mem_free(pMemOP, hQC->qcChannel[0].quantSpec, VO_INDEX_ENC_AAC); + + if(hQC->qcChannel[0].maxValueInSfb) + mem_free(pMemOP, hQC->qcChannel[0].maxValueInSfb, VO_INDEX_ENC_AAC); + + if(hQC->qcChannel[0].scf) + mem_free(pMemOP, hQC->qcChannel[0].scf, VO_INDEX_ENC_AAC); + + for (i=0; iqcChannel[i].quantSpec = NULL; + + hQC->qcChannel[i].maxValueInSfb = NULL; + + hQC->qcChannel[i].scf = NULL; + } + } +} + +/********************************************************************************* +* +* function name: QCNew +* description: set QC to zero +* returns: 0 if success +* +**********************************************************************************/ +Word16 QCNew(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP) +{ + pMemOP->Set(VO_INDEX_ENC_AAC, hQC,0,sizeof(QC_STATE)); + + return (0); +} + +/********************************************************************************* +* +* function name: QCDelete +* description: unint qcout parameter +* +**********************************************************************************/ +void QCDelete(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP) +{ + + /* + nothing to do + */ + hQC=NULL; +} + +/********************************************************************************* +* +* function name: QCInit +* description: init QD parameter +* returns: 0 if success +* +**********************************************************************************/ +Word16 QCInit(QC_STATE *hQC, + struct QC_INIT *init) +{ + hQC->nChannels = init->elInfo->nChannelsInEl; + hQC->maxBitsTot = init->maxBits; + hQC->bitResTot = sub(init->bitRes, init->averageBits); + hQC->averageBitsTot = init->averageBits; + hQC->maxBitFac = init->maxBitFac; + + hQC->padding.paddingRest = init->padding.paddingRest; + + hQC->globStatBits = 3; /* for ID_END */ + + /* channel elements init */ + InitElementBits(&hQC->elementBits, + *init->elInfo, + init->bitrate, + init->averageBits, + hQC->globStatBits); + + /* threshold parameter init */ + AdjThrInit(&hQC->adjThr, + init->meanPe, + hQC->elementBits.chBitrate); + + return 0; +} + + +/********************************************************************************* +* +* function name: QCMain +* description: quantization and coding the spectrum +* returns: 0 if success +* +**********************************************************************************/ +Word16 QCMain(QC_STATE* hQC, + ELEMENT_BITS* elBits, + ATS_ELEMENT* adjThrStateElement, + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], /* may be modified in-place */ + PSY_OUT_ELEMENT* psyOutElement, + QC_OUT_CHANNEL qcOutChannel[MAX_CHANNELS], /* out */ + QC_OUT_ELEMENT* qcOutElement, + Word16 nChannels, + Word16 ancillaryDataBytes) +{ + Word16 maxChDynBits[MAX_CHANNELS]; + Word16 chBitDistribution[MAX_CHANNELS]; + Word32 ch; + + if (elBits->bitResLevel < 0) { + return -1; + } + + if (elBits->bitResLevel > elBits->maxBitResBits) { + return -1; + } + + qcOutElement->staticBitsUsed = countStaticBitdemand(psyOutChannel, + psyOutElement, + nChannels, + qcOutElement->adtsUsed); + + + if (ancillaryDataBytes) { + qcOutElement->ancBitsUsed = 7 + (ancillaryDataBytes << 3); + + if (ancillaryDataBytes >= 15) + qcOutElement->ancBitsUsed = qcOutElement->ancBitsUsed + 8; + } + else { + qcOutElement->ancBitsUsed = 0; + } + + CalcFormFactor(hQC->logSfbFormFactor, hQC->sfbNRelevantLines, hQC->logSfbEnergy, psyOutChannel, nChannels); + + /*adjust thresholds for the desired bitrate */ + AdjustThresholds(&hQC->adjThr, + adjThrStateElement, + psyOutChannel, + psyOutElement, + chBitDistribution, + hQC->logSfbEnergy, + hQC->sfbNRelevantLines, + qcOutElement, + elBits, + nChannels, + hQC->maxBitFac); + + /*estimate scale factors */ + EstimateScaleFactors(psyOutChannel, + qcOutChannel, + hQC->logSfbEnergy, + hQC->logSfbFormFactor, + hQC->sfbNRelevantLines, + nChannels); + + /* condition to prevent empty bitreservoir */ + for (ch = 0; ch < nChannels; ch++) { + Word32 maxDynBits; + maxDynBits = elBits->averageBits + elBits->bitResLevel - 7; /* -7 bec. of align bits */ + maxDynBits = maxDynBits - qcOutElement->staticBitsUsed + qcOutElement->ancBitsUsed; + maxChDynBits[ch] = extract_l(chBitDistribution[ch] * maxDynBits / 1000); + } + + qcOutElement->dynBitsUsed = 0; + for (ch = 0; ch < nChannels; ch++) { + Word32 chDynBits; + Flag constraintsFulfilled; + Word32 iter; + iter = 0; + do { + constraintsFulfilled = 1; + + QuantizeSpectrum(psyOutChannel[ch].sfbCnt, + psyOutChannel[ch].maxSfbPerGroup, + psyOutChannel[ch].sfbPerGroup, + psyOutChannel[ch].sfbOffsets, + psyOutChannel[ch].mdctSpectrum, + qcOutChannel[ch].globalGain, + qcOutChannel[ch].scf, + qcOutChannel[ch].quantSpec); + + if (calcMaxValueInSfb(psyOutChannel[ch].sfbCnt, + psyOutChannel[ch].maxSfbPerGroup, + psyOutChannel[ch].sfbPerGroup, + psyOutChannel[ch].sfbOffsets, + qcOutChannel[ch].quantSpec, + qcOutChannel[ch].maxValueInSfb) > MAX_QUANT) { + constraintsFulfilled = 0; + } + + chDynBits = dynBitCount(qcOutChannel[ch].quantSpec, + qcOutChannel[ch].maxValueInSfb, + qcOutChannel[ch].scf, + psyOutChannel[ch].windowSequence, + psyOutChannel[ch].sfbCnt, + psyOutChannel[ch].maxSfbPerGroup, + psyOutChannel[ch].sfbPerGroup, + psyOutChannel[ch].sfbOffsets, + &qcOutChannel[ch].sectionData); + + if (chDynBits >= maxChDynBits[ch]) { + constraintsFulfilled = 0; + } + + if (!constraintsFulfilled) { + qcOutChannel[ch].globalGain = qcOutChannel[ch].globalGain + 1; + } + + iter = iter + 1; + + } while(!constraintsFulfilled); + + qcOutElement->dynBitsUsed = qcOutElement->dynBitsUsed + chDynBits; + + qcOutChannel[ch].mdctScale = psyOutChannel[ch].mdctScale; + qcOutChannel[ch].groupingMask = psyOutChannel[ch].groupingMask; + qcOutChannel[ch].windowShape = psyOutChannel[ch].windowShape; + } + + /* save dynBitsUsed for correction of bits2pe relation */ + AdjThrUpdate(adjThrStateElement, qcOutElement->dynBitsUsed); + + { + Word16 bitResSpace = elBits->maxBitResBits - elBits->bitResLevel; + Word16 deltaBitRes = elBits->averageBits - + (qcOutElement->staticBitsUsed + + qcOutElement->dynBitsUsed + qcOutElement->ancBitsUsed); + + qcOutElement->fillBits = max(0, (deltaBitRes - bitResSpace)); + } + + return 0; /* OK */ +} + + +/********************************************************************************* +* +* function name: calcMaxValueInSfb +* description: search the max Spectrum in one sfb +* +**********************************************************************************/ +static Word16 calcMaxValueInSfb(Word16 sfbCnt, + Word16 maxSfbPerGroup, + Word16 sfbPerGroup, + Word16 sfbOffset[MAX_GROUPED_SFB], + Word16 quantSpectrum[FRAME_LEN_LONG], + UWord16 maxValue[MAX_GROUPED_SFB]) +{ + Word16 sfbOffs, sfb; + Word16 maxValueAll; + + maxValueAll = 0; + + for(sfbOffs=0;sfbOffsbitResTot = 0; + + elBits = &qcKernel->elementBits; + + + if (elBits->averageBits > 0) { + /* constant bitrate */ + Word16 bitsUsed; + bitsUsed = (qcOut->qcElement.staticBitsUsed + qcOut->qcElement.dynBitsUsed) + + (qcOut->qcElement.ancBitsUsed + qcOut->qcElement.fillBits); + elBits->bitResLevel = elBits->bitResLevel + (elBits->averageBits - bitsUsed); + qcKernel->bitResTot = qcKernel->bitResTot + elBits->bitResLevel; + } + else { + /* variable bitrate */ + elBits->bitResLevel = elBits->maxBits; + qcKernel->bitResTot = qcKernel->maxBitsTot; + } +} + +/********************************************************************************* +* +* function name: FinalizeBitConsumption +* description: count bits used +* +**********************************************************************************/ +Word16 FinalizeBitConsumption(QC_STATE *qcKernel, + QC_OUT* qcOut) +{ + Word32 nFullFillElem; + Word32 totFillBits; + Word16 diffBits; + Word16 bitsUsed; + + totFillBits = 0; + + qcOut->totStaticBitsUsed = qcKernel->globStatBits; + qcOut->totStaticBitsUsed += qcOut->qcElement.staticBitsUsed; + qcOut->totDynBitsUsed = qcOut->qcElement.dynBitsUsed; + qcOut->totAncBitsUsed = qcOut->qcElement.ancBitsUsed; + qcOut->totFillBits = qcOut->qcElement.fillBits; + + if (qcOut->qcElement.fillBits) { + totFillBits += qcOut->qcElement.fillBits; + } + + nFullFillElem = (max((qcOut->totFillBits - 1), 0) / maxFillElemBits) * maxFillElemBits; + + qcOut->totFillBits = qcOut->totFillBits - nFullFillElem; + + /* check fill elements */ + + if (qcOut->totFillBits > 0) { + /* minimum Fillelement contains 7 (TAG + byte cnt) bits */ + qcOut->totFillBits = max(7, qcOut->totFillBits); + /* fill element size equals n*8 + 7 */ + qcOut->totFillBits = qcOut->totFillBits + ((8 - ((qcOut->totFillBits - 7) & 0x0007)) & 0x0007); + } + + qcOut->totFillBits = qcOut->totFillBits + nFullFillElem; + + /* now distribute extra fillbits and alignbits over channel elements */ + qcOut->alignBits = 7 - ((qcOut->totDynBitsUsed + qcOut->totStaticBitsUsed + + qcOut->totAncBitsUsed + qcOut->totFillBits - 1) & 0x0007); + + + if ( (qcOut->alignBits + qcOut->totFillBits - totFillBits == 8) && + (qcOut->totFillBits > 8)) + qcOut->totFillBits = qcOut->totFillBits - 8; + + + diffBits = qcOut->alignBits + qcOut->totFillBits - totFillBits; + + if(diffBits>=0) { + qcOut->qcElement.fillBits += diffBits; + } + + bitsUsed = qcOut->totDynBitsUsed + qcOut->totStaticBitsUsed + qcOut->totAncBitsUsed; + bitsUsed = bitsUsed + qcOut->totFillBits + qcOut->alignBits; + + if (bitsUsed > qcKernel->maxBitsTot) { + return -1; + } + return bitsUsed; +} + + +/********************************************************************************* +* +* function name: AdjustBitrate +* description: adjusts framelength via padding on a frame to frame basis, +* to achieve a bitrate that demands a non byte aligned +* framelength +* return: errorcode +* +**********************************************************************************/ +Word16 AdjustBitrate(QC_STATE *hQC, + Word32 bitRate, /* total bitrate */ + Word32 sampleRate) /* output sampling rate */ +{ + Word16 paddingOn; + Word16 frameLen; + Word16 codeBits; + Word16 codeBitsLast; + + /* Do we need a extra padding byte? */ + paddingOn = framePadding(bitRate, + sampleRate, + &hQC->padding.paddingRest); + + /* frame length */ + frameLen = paddingOn + calcFrameLen(bitRate, + sampleRate, + FRAME_LEN_BYTES_INT); + + frameLen = frameLen << 3; + codeBitsLast = hQC->averageBitsTot - hQC->globStatBits; + codeBits = frameLen - hQC->globStatBits; + + /* calculate bits for every channel element */ + if (codeBits != codeBitsLast) { + Word16 totalBits = 0; + + hQC->elementBits.averageBits = (hQC->elementBits.relativeBits * codeBits) >> 16; /* relativeBits was scaled down by 2 */ + totalBits += hQC->elementBits.averageBits; + + hQC->elementBits.averageBits = hQC->elementBits.averageBits + (codeBits - totalBits); + } + + hQC->averageBitsTot = frameLen; + + return 0; +} diff --git a/media/libstagefright/codecs/aacenc/src/quantize.c b/media/libstagefright/codecs/aacenc/src/quantize.c new file mode 100644 index 0000000000000000000000000000000000000000..205f1678262611825c7067c06bd0a0529dd15270 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/quantize.c @@ -0,0 +1,445 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: quantize.c + + Content: quantization functions + +*******************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "quantize.h" +#include "aac_rom.h" + +#define MANT_DIGITS 9 +#define MANT_SIZE (1<> (INT_BITS-2-MANT_DIGITS)) & (MANT_SIZE-1)]; +} + + +/***************************************************************************** +* +* function name:quantizeSingleLine +* description: quantizes spectrum +* quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain) +* +*****************************************************************************/ +static Word16 quantizeSingleLine(const Word16 gain, const Word32 absSpectrum) +{ + Word32 e, minusFinalExp, finalShift; + Word32 x; + Word16 qua = 0; + + + if (absSpectrum) { + e = norm_l(absSpectrum); + x = pow34(absSpectrum << e); + + /* calculate the final fractional exponent times 16 (was 3*(4*e + gain) + (INT_BITS-1)*16) */ + minusFinalExp = (e << 2) + gain; + minusFinalExp = (minusFinalExp << 1) + minusFinalExp; + minusFinalExp = minusFinalExp + ((INT_BITS-1) << 4); + + /* separate the exponent into a shift, and a multiply */ + finalShift = minusFinalExp >> 4; + + if (finalShift < INT_BITS) { + x = L_mpy_wx(x, pow2tominusNover16[minusFinalExp & 15]); + + x += XROUND >> (INT_BITS - finalShift); + + /* shift and quantize */ + finalShift--; + + if(finalShift >= 0) + x >>= finalShift; + else + x <<= (-finalShift); + + qua = saturate(x); + } + } + + return qua; +} + +/***************************************************************************** +* +* function name:quantizeLines +* description: quantizes spectrum lines +* quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain) +* input: global gain, number of lines to process, spectral data +* output: quantized spectrum +* +*****************************************************************************/ +static void quantizeLines(const Word16 gain, + const Word16 noOfLines, + const Word32 *mdctSpectrum, + Word16 *quaSpectrum) +{ + Word32 line; + Word32 m = gain&3; + Word32 g = (gain >> 2) + 4; + Word32 mdctSpeL; + Word16 *pquat; + /* gain&3 */ + + pquat = quantBorders[m]; + + g += 16; + + if(g >= 0) + { + for (line=0; line> g; + + if (saShft > pquat[0]) { + + if (saShft < pquat[1]) { + + qua = mdctSpeL>0 ? 1 : -1; + } + else { + + if (saShft < pquat[2]) { + + qua = mdctSpeL>0 ? 2 : -2; + } + else { + + if (saShft < pquat[3]) { + + qua = mdctSpeL>0 ? 3 : -3; + } + else { + qua = quantizeSingleLine(gain, sa); + /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */ + + if (mdctSpeL < 0) + qua = -qua; + } + } + } + } + } + quaSpectrum[line] = qua ; + } + } + else + { + for (line=0; line pquat[0]) { + + if (saShft < pquat[1]) { + + qua = mdctSpeL>0 ? 1 : -1; + } + else { + + if (saShft < pquat[2]) { + + qua = mdctSpeL>0 ? 2 : -2; + } + else { + + if (saShft < pquat[3]) { + + qua = mdctSpeL>0 ? 3 : -3; + } + else { + qua = quantizeSingleLine(gain, sa); + /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */ + + if (mdctSpeL < 0) + qua = -qua; + } + } + } + } + } + quaSpectrum[line] = qua ; + } + } + +} + + +/***************************************************************************** +* +* function name:iquantizeLines +* description: iquantizes spectrum lines without sign +* mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain) +* input: global gain, number of lines to process,quantized spectrum +* output: spectral data +* +*****************************************************************************/ +static void iquantizeLines(const Word16 gain, + const Word16 noOfLines, + const Word16 *quantSpectrum, + Word32 *mdctSpectrum) +{ + Word32 iquantizermod; + Word32 iquantizershift; + Word32 line; + + iquantizermod = gain & 3; + iquantizershift = gain >> 2; + + for (line=0; line> (INT_BITS-2-MANT_DIGITS)) & (~MANT_SIZE); + + /* calculate "mantissa" ^4/3 */ + s = mTab_4_3[tabIndex]; + + /* get approperiate exponent multiplier for specExp^3/4 combined with scfMod */ + t = specExpMantTableComb_enc[iquantizermod][specExp]; + + /* multiply "mantissa" ^4/3 with exponent multiplier */ + accu = MULHIGH(s, t); + + /* get approperiate exponent shifter */ + specExp = specExpTableComb_enc[iquantizermod][specExp]; + + specExp += iquantizershift + 1; + if(specExp >= 0) + mdctSpectrum[line] = accu << specExp; + else + mdctSpectrum[line] = accu >> (-specExp); + } + else { + mdctSpectrum[line] = 0; + } + } +} + +/***************************************************************************** +* +* function name: QuantizeSpectrum +* description: quantizes the entire spectrum +* returns: +* input: number of scalefactor bands to be quantized, ... +* output: quantized spectrum +* +*****************************************************************************/ +void QuantizeSpectrum(Word16 sfbCnt, + Word16 maxSfbPerGroup, + Word16 sfbPerGroup, + Word16 *sfbOffset, + Word32 *mdctSpectrum, + Word16 globalGain, + Word16 *scalefactors, + Word16 *quantizedSpectrum) +{ + Word32 sfbOffs, sfb; + + for(sfbOffs=0;sfbOffs> 2) + 4; + Word32 g2 = (g << 1) + 1; + Word16 *pquat, *repquat; + /* gain&3 */ + + pquat = quantBorders[m]; + repquat = quantRecon[m]; + + dist = 0; + g += 16; + if(g2 < 0 && g >= 0) + { + g2 = -g2; + for(line=0; line> g; + + if (saShft < pquat[0]) { + distSingle = (saShft * saShft) >> g2; + } + else { + + if (saShft < pquat[1]) { + diff = saShft - repquat[0]; + distSingle = (diff * diff) >> g2; + } + else { + + if (saShft < pquat[2]) { + diff = saShft - repquat[1]; + distSingle = (diff * diff) >> g2; + } + else { + + if (saShft < pquat[3]) { + diff = saShft - repquat[2]; + distSingle = (diff * diff) >> g2; + } + else { + Word16 qua = quantizeSingleLine(gain, sa); + Word32 iqval, diff32; + /* now that we have quantized x, re-quantize it. */ + iquantizeLines(gain, 1, &qua, &iqval); + diff32 = sa - iqval; + distSingle = fixmul(diff32, diff32); + } + } + } + } + + dist = L_add(dist, distSingle); + } + } + } + else + { + for(line=0; line> 1; + preshift = postshift << 1; + postshift = postshift + 8; /* sqrt/256 */ + if(preshift >= 0) + y = x << preshift; /* now 1/4 <= y < 1 */ + else + y = x >> (-preshift); + y = formfac_sqrttable[y-32]; + + if(postshift >= 0) + y = y >> postshift; + else + y = y << (-postshift); + + return y; +} + + +/********************************************************************************* +* +* function name: CalcFormFactorChannel +* description: calculate the form factor one channel +* ffac(n) = sqrt(abs(X(k)) + sqrt(abs(X(k+1)) + .... +* +**********************************************************************************/ +static void +CalcFormFactorChannel(Word16 *logSfbFormFactor, + Word16 *sfbNRelevantLines, + Word16 *logSfbEnergy, + PSY_OUT_CHANNEL *psyOutChan) +{ + Word32 sfbw, sfbw1; + Word32 i, j; + Word32 sfbOffs, sfb, shift; + + sfbw = sfbw1 = 0; + for (sfbOffs=0; sfbOffssfbCnt; sfbOffs+=psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + i = sfbOffs+sfb; + + if (psyOutChan->sfbEnergy[i] > psyOutChan->sfbThreshold[i]) { + Word32 accu, avgFormFactor,iSfbWidth; + Word32 *mdctSpec; + sfbw = psyOutChan->sfbOffsets[i+1] - psyOutChan->sfbOffsets[i]; + iSfbWidth = invSBF[(sfbw >> 2) - 1]; + mdctSpec = psyOutChan->mdctSpectrum + psyOutChan->sfbOffsets[i]; + accu = 0; + /* calc sum of sqrt(spec) */ + for (j=sfbw; j; j--) { + accu += formfac_sqrt(L_abs(*mdctSpec)); mdctSpec++; + } + logSfbFormFactor[i] = iLog4(accu); + logSfbEnergy[i] = iLog4(psyOutChan->sfbEnergy[i]); + avgFormFactor = fixmul(rsqrt(psyOutChan->sfbEnergy[i],INT_BITS), iSfbWidth); + avgFormFactor = rsqrt((Word32)avgFormFactor,INT_BITS) >> 10; + /* result is multiplied by 4 */ + if(avgFormFactor) + sfbNRelevantLines[i] = accu / avgFormFactor; + else + sfbNRelevantLines[i] = 0x7fff; + } + else { + /* set number of lines to zero */ + sfbNRelevantLines[i] = 0; + } + } + } +} + +/********************************************************************************* +* +* function name: improveScf +* description: find better scalefactor with analysis by synthesis +* +**********************************************************************************/ +static Word16 improveScf(Word32 *spec, + Word16 sfbWidth, + Word32 thresh, + Word16 scf, + Word16 minScf, + Word32 *dist, + Word16 *minScfCalculated) +{ + Word32 cnt; + Word32 sfbDist; + Word32 scfBest; + Word32 thresh125 = L_add(thresh, (thresh >> 2)); + + scfBest = scf; + + /* calc real distortion */ + sfbDist = calcSfbDist(spec, sfbWidth, scf); + *minScfCalculated = scf; + if(!sfbDist) + return scfBest; + + if (sfbDist > thresh125) { + Word32 scfEstimated; + Word32 sfbDistBest; + scfEstimated = scf; + sfbDistBest = sfbDist; + + cnt = 0; + while (sfbDist > thresh125 && (cnt < 3)) { + + scf = scf + 1; + sfbDist = calcSfbDist(spec, sfbWidth, scf); + + if (sfbDist < sfbDistBest) { + scfBest = scf; + sfbDistBest = sfbDist; + } + cnt = cnt + 1; + } + cnt = 0; + scf = scfEstimated; + sfbDist = sfbDistBest; + while ((sfbDist > thresh125) && (cnt < 1) && (scf > minScf)) { + + scf = scf - 1; + sfbDist = calcSfbDist(spec, sfbWidth, scf); + + if (sfbDist < sfbDistBest) { + scfBest = scf; + sfbDistBest = sfbDist; + } + *minScfCalculated = scf; + cnt = cnt + 1; + } + *dist = sfbDistBest; + } + else { + Word32 sfbDistBest; + Word32 sfbDistAllowed; + Word32 thresh08 = fixmul(COEF08_31, thresh); + sfbDistBest = sfbDist; + + if (sfbDist < thresh08) + sfbDistAllowed = sfbDist; + else + sfbDistAllowed = thresh08; + for (cnt=0; cnt<3; cnt++) { + scf = scf + 1; + sfbDist = calcSfbDist(spec, sfbWidth, scf); + + if (fixmul(COEF08_31,sfbDist) < sfbDistAllowed) { + *minScfCalculated = scfBest + 1; + scfBest = scf; + sfbDistBest = sfbDist; + } + } + *dist = sfbDistBest; + } + + /* return best scalefactor */ + return scfBest; +} + +/********************************************************************************* +* +* function name: countSingleScfBits +* description: count single scf bits in huffum +* +**********************************************************************************/ +static Word16 countSingleScfBits(Word16 scf, Word16 scfLeft, Word16 scfRight) +{ + Word16 scfBits; + + scfBits = bitCountScalefactorDelta(scfLeft - scf) + + bitCountScalefactorDelta(scf - scfRight); + + return scfBits; +} + +/********************************************************************************* +* +* function name: calcSingleSpecPe +* description: ldRatio = log2(en(n)) - 0,375*scfGain(n) +* nbits = 0.7*nLines*ldRation for ldRation >= c1 +* nbits = 0.7*nLines*(c2 + c3*ldRatio) for ldRation < c1 +* +**********************************************************************************/ +static Word16 calcSingleSpecPe(Word16 scf, Word16 sfbConstPePart, Word16 nLines) +{ + Word32 specPe; + Word32 ldRatio; + Word32 scf3; + + ldRatio = sfbConstPePart << 3; /* (sfbConstPePart -0.375*scf)*8 */ + scf3 = scf + scf + scf; + ldRatio = ldRatio - scf3; + + if (ldRatio < PE_C1_8) { + /* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/ + ldRatio = (ldRatio + PE_C2_16) >> 1; + } + specPe = nLines * ldRatio; + specPe = (specPe * PE_SCALE) >> 14; + + return saturate(specPe); +} + + +/********************************************************************************* +* +* function name: countScfBitsDiff +* description: count different scf bits used +* +**********************************************************************************/ +static Word16 countScfBitsDiff(Word16 *scfOld, Word16 *scfNew, + Word16 sfbCnt, Word16 startSfb, Word16 stopSfb) +{ + Word32 scfBitsDiff; + Word32 sfb, sfbLast; + Word32 sfbPrev, sfbNext; + + scfBitsDiff = 0; + sfb = 0; + + /* search for first relevant sfb */ + sfbLast = startSfb; + while (sfbLast < stopSfb && scfOld[sfbLast] == VOAAC_SHRT_MIN) { + + sfbLast = sfbLast + 1; + } + /* search for previous relevant sfb and count diff */ + sfbPrev = startSfb - 1; + while ((sfbPrev>=0) && scfOld[sfbPrev] == VOAAC_SHRT_MIN) { + + sfbPrev = sfbPrev - 1; + } + + if (sfbPrev>=0) { + scfBitsDiff += bitCountScalefactorDelta(scfNew[sfbPrev] - scfNew[sfbLast]) - + bitCountScalefactorDelta(scfOld[sfbPrev] - scfOld[sfbLast]); + } + /* now loop through all sfbs and count diffs of relevant sfbs */ + for (sfb=sfbLast+1; sfb> 2; + } + + + ldRatioOld = sfbConstPePart[sfb] << 3; + scf3 = scfOld[sfb] + scfOld[sfb] + scfOld[sfb]; + ldRatioOld = ldRatioOld - scf3; + ldRatioNew = sfbConstPePart[sfb] << 3; + scf3 = scfNew[sfb] + scfNew[sfb] + scfNew[sfb]; + ldRatioNew = ldRatioNew - scf3; + + if (ldRatioOld < PE_C1_8) { + /* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/ + ldRatioOld = (ldRatioOld + PE_C2_16) >> 1; + } + + if (ldRatioNew < PE_C1_8) { + /* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/ + ldRatioNew = (ldRatioNew + PE_C2_16) >> 1; + } + + specPeDiff += sfbNRelevantLines[sfb] * (ldRatioNew - ldRatioOld); + } + } + + specPeDiff = (specPeDiff * PE_SCALE) >> 14; + + return saturate(specPeDiff); +} + + +/********************************************************************************* +* +* function name: assimilateSingleScf +* description: searched for single scalefactor bands, where the number of bits gained +* by using a smaller scfgain(n) is greater than the estimated increased +* bit demand +* +**********************************************************************************/ +static void assimilateSingleScf(PSY_OUT_CHANNEL *psyOutChan, + Word16 *scf, + Word16 *minScf, + Word32 *sfbDist, + Word16 *sfbConstPePart, + Word16 *logSfbEnergy, + Word16 *logSfbFormFactor, + Word16 *sfbNRelevantLines, + Word16 *minScfCalculated, + Flag restartOnSuccess) +{ + Word32 sfbLast, sfbAct, sfbNext, scfAct, scfMin; + Word16 *scfLast, *scfNext; + Word32 sfbPeOld, sfbPeNew; + Word32 sfbDistNew; + Word32 j; + Flag success; + Word16 deltaPe, deltaPeNew, deltaPeTmp; + Word16 *prevScfLast = psyOutChan->prevScfLast; + Word16 *prevScfNext = psyOutChan->prevScfNext; + Word16 *deltaPeLast = psyOutChan->deltaPeLast; + Flag updateMinScfCalculated; + + success = 0; + deltaPe = 0; + + for(j=0;jsfbCnt;j++){ + prevScfLast[j] = MAX_16; + prevScfNext[j] = MAX_16; + deltaPeLast[j] = MAX_16; + } + + sfbLast = -1; + sfbAct = -1; + sfbNext = -1; + scfLast = 0; + scfNext = 0; + scfMin = MAX_16; + do { + /* search for new relevant sfb */ + sfbNext = sfbNext + 1; + while (sfbNext < psyOutChan->sfbCnt && scf[sfbNext] == MIN_16) { + + sfbNext = sfbNext + 1; + } + + if ((sfbLast>=0) && (sfbAct>=0) && sfbNext < psyOutChan->sfbCnt) { + /* relevant scfs to the left and to the right */ + scfAct = scf[sfbAct]; + scfLast = scf + sfbLast; + scfNext = scf + sfbNext; + scfMin = min(*scfLast, *scfNext); + } + else { + + if (sfbLast == -1 && (sfbAct>=0) && sfbNext < psyOutChan->sfbCnt) { + /* first relevant scf */ + scfAct = scf[sfbAct]; + scfLast = &scfAct; + scfNext = scf + sfbNext; + scfMin = *scfNext; + } + else { + + if ((sfbLast>=0) && (sfbAct>=0) && sfbNext == psyOutChan->sfbCnt) { + /* last relevant scf */ + scfAct = scf[sfbAct]; + scfLast = scf + sfbLast; + scfNext = &scfAct; + scfMin = *scfLast; + } + } + } + + if (sfbAct>=0) + scfMin = max(scfMin, minScf[sfbAct]); + + if ((sfbAct >= 0) && + (sfbLast>=0 || sfbNext < psyOutChan->sfbCnt) && + scfAct > scfMin && + (*scfLast != prevScfLast[sfbAct] || + *scfNext != prevScfNext[sfbAct] || + deltaPe < deltaPeLast[sfbAct])) { + success = 0; + + /* estimate required bits for actual scf */ + if (sfbConstPePart[sfbAct] == MIN_16) { + sfbConstPePart[sfbAct] = logSfbEnergy[sfbAct] - + logSfbFormFactor[sfbAct] + 11-8*4; /* 4*log2(6.75) - 32 */ + + if (sfbConstPePart[sfbAct] < 0) + sfbConstPePart[sfbAct] = sfbConstPePart[sfbAct] + 3; + sfbConstPePart[sfbAct] = sfbConstPePart[sfbAct] >> 2; + } + + sfbPeOld = calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], sfbNRelevantLines[sfbAct]) + + countSingleScfBits(scfAct, *scfLast, *scfNext); + deltaPeNew = deltaPe; + updateMinScfCalculated = 1; + do { + scfAct = scfAct - 1; + /* check only if the same check was not done before */ + + if (scfAct < minScfCalculated[sfbAct]) { + sfbPeNew = calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], sfbNRelevantLines[sfbAct]) + + countSingleScfBits(scfAct, *scfLast, *scfNext); + /* use new scf if no increase in pe and + quantization error is smaller */ + deltaPeTmp = deltaPe + sfbPeNew - sfbPeOld; + + if (deltaPeTmp < 10) { + sfbDistNew = calcSfbDist(psyOutChan->mdctSpectrum+ + psyOutChan->sfbOffsets[sfbAct], + (psyOutChan->sfbOffsets[sfbAct+1] - psyOutChan->sfbOffsets[sfbAct]), + scfAct); + if (sfbDistNew < sfbDist[sfbAct]) { + /* success, replace scf by new one */ + scf[sfbAct] = scfAct; + sfbDist[sfbAct] = sfbDistNew; + deltaPeNew = deltaPeTmp; + success = 1; + } + /* mark as already checked */ + + if (updateMinScfCalculated) { + minScfCalculated[sfbAct] = scfAct; + } + } + else { + updateMinScfCalculated = 0; + } + } + + } while (scfAct > scfMin); + deltaPe = deltaPeNew; + /* save parameters to avoid multiple computations of the same sfb */ + prevScfLast[sfbAct] = *scfLast; + prevScfNext[sfbAct] = *scfNext; + deltaPeLast[sfbAct] = deltaPe; + } + + if (success && restartOnSuccess) { + /* start again at first sfb */ + sfbLast = -1; + sfbAct = -1; + sfbNext = -1; + scfLast = 0; + scfNext = 0; + scfMin = MAX_16; + success = 0; + } + else { + /* shift sfbs for next band */ + sfbLast = sfbAct; + sfbAct = sfbNext; + } + + } while (sfbNext < psyOutChan->sfbCnt); +} + + +/********************************************************************************* +* +* function name: assimilateMultipleScf +* description: scalefactor difference reduction +* +**********************************************************************************/ +static void assimilateMultipleScf(PSY_OUT_CHANNEL *psyOutChan, + Word16 *scf, + Word16 *minScf, + Word32 *sfbDist, + Word16 *sfbConstPePart, + Word16 *logSfbEnergy, + Word16 *logSfbFormFactor, + Word16 *sfbNRelevantLines) +{ + Word32 sfb, startSfb, stopSfb, scfMin, scfMax, scfAct; + Flag possibleRegionFound; + Word32 deltaScfBits; + Word32 deltaSpecPe; + Word32 deltaPe, deltaPeNew; + Word32 sfbCnt; + Word32 *sfbDistNew = psyOutChan->sfbDistNew; + Word16 *scfTmp = psyOutChan->prevScfLast; + + deltaPe = 0; + sfbCnt = psyOutChan->sfbCnt; + + /* calc min and max scalfactors */ + scfMin = MAX_16; + scfMax = MIN_16; + for (sfb=0; sfb scfAct)) { + sfb = sfb + 1; + } + stopSfb = sfb; + + possibleRegionFound = 0; + + if (startSfb < sfbCnt) { + possibleRegionFound = 1; + for (sfb=startSfb; sfbmdctSpectrum + + psyOutChan->sfbOffsets[sfb], + (psyOutChan->sfbOffsets[sfb+1] - psyOutChan->sfbOffsets[sfb]), + scfAct); + + + if (sfbDistNew[sfb] > psyOutChan->sfbThreshold[sfb]) { + distNewSum = distOldSum << 1; + break; + } + distNewSum = L_add(distNewSum, sfbDistNew[sfb]); + } + } + + if (distNewSum < distOldSum) { + deltaPe = deltaPeNew; + for (sfb=startSfb; sfb scfMin); + } +} + +/********************************************************************************* +* +* function name: EstimateScaleFactorsChannel +* description: estimate scale factors for one channel +* +**********************************************************************************/ +static void +EstimateScaleFactorsChannel(PSY_OUT_CHANNEL *psyOutChan, + Word16 *scf, + Word16 *globalGain, + Word16 *logSfbEnergy, + Word16 *logSfbFormFactor, + Word16 *sfbNRelevantLines) +{ + Word32 i, j; + Word32 thresh, energy; + Word32 energyPart, thresholdPart; + Word32 scfInt, minScf, maxScf, maxAllowedScf, lastSf; + Word32 maxSpec; + Word32 *sfbDist = psyOutChan->sfbDist; + Word16 *minSfMaxQuant = psyOutChan->minSfMaxQuant; + Word16 *minScfCalculated = psyOutChan->minScfCalculated; + + + for (i=0; isfbCnt; i++) { + Word32 sbfwith, sbfStart; + Word32 *mdctSpec; + thresh = psyOutChan->sfbThreshold[i]; + energy = psyOutChan->sfbEnergy[i]; + + sbfStart = psyOutChan->sfbOffsets[i]; + sbfwith = psyOutChan->sfbOffsets[i+1] - sbfStart; + mdctSpec = psyOutChan->mdctSpectrum+sbfStart; + + maxSpec = 0; + /* maximum of spectrum */ + for (j=sbfwith; j; j-- ) { + Word32 absSpec = L_abs(*mdctSpec); mdctSpec++; + maxSpec |= absSpec; + } + + /* scfs without energy or with thresh>energy are marked with MIN_16 */ + scf[i] = MIN_16; + minSfMaxQuant[i] = MIN_16; + + if ((maxSpec > 0) && (energy > thresh)) { + + energyPart = logSfbFormFactor[i]; + thresholdPart = iLog4(thresh); + /* -20 = 4*log2(6.75) - 32 */ + scfInt = ((thresholdPart - energyPart - 20) * SCALE_ESTIMATE_COEF) >> 15; + + minSfMaxQuant[i] = iLog4(maxSpec) - 68; /* 68 -16/3*log(MAX_QUANT+0.5-logCon)/log(2) + 1 */ + + + if (minSfMaxQuant[i] > scfInt) { + scfInt = minSfMaxQuant[i]; + } + + /* find better scalefactor with analysis by synthesis */ + scfInt = improveScf(psyOutChan->mdctSpectrum+sbfStart, + sbfwith, + thresh, scfInt, minSfMaxQuant[i], + &sfbDist[i], &minScfCalculated[i]); + + scf[i] = scfInt; + } + } + + + /* scalefactor differece reduction */ + { + Word16 sfbConstPePart[MAX_GROUPED_SFB]; + for(i=0;isfbCnt;i++) { + sfbConstPePart[i] = MIN_16; + } + + assimilateSingleScf(psyOutChan, scf, + minSfMaxQuant, sfbDist, sfbConstPePart, logSfbEnergy, + logSfbFormFactor, sfbNRelevantLines, minScfCalculated, 1); + + assimilateMultipleScf(psyOutChan, scf, + minSfMaxQuant, sfbDist, sfbConstPePart, logSfbEnergy, + logSfbFormFactor, sfbNRelevantLines); + } + + /* get max scalefac for global gain */ + maxScf = MIN_16; + minScf = MAX_16; + for (i=0; isfbCnt; i++) { + + if (maxScf < scf[i]) { + maxScf = scf[i]; + } + + if ((scf[i] != MIN_16) && (minScf > scf[i])) { + minScf = scf[i]; + } + } + /* limit scf delta */ + maxAllowedScf = minScf + MAX_SCF_DELTA; + for(i=0; isfbCnt; i++) { + + if ((scf[i] != MIN_16) && (maxAllowedScf < scf[i])) { + scf[i] = maxAllowedScf; + } + } + /* new maxScf if any scf has been limited */ + + if (maxAllowedScf < maxScf) { + maxScf = maxAllowedScf; + } + + /* calc loop scalefactors */ + + if (maxScf > MIN_16) { + *globalGain = maxScf; + lastSf = 0; + + for(i=0; isfbCnt; i++) { + + if (scf[i] == MIN_16) { + scf[i] = lastSf; + /* set band explicitely to zero */ + for (j=psyOutChan->sfbOffsets[i]; jsfbOffsets[i+1]; j++) { + psyOutChan->mdctSpectrum[j] = 0; + } + } + else { + scf[i] = maxScf - scf[i]; + lastSf = scf[i]; + } + } + } + else{ + *globalGain = 0; + /* set spectrum explicitely to zero */ + for(i=0; isfbCnt; i++) { + scf[i] = 0; + for (j=psyOutChan->sfbOffsets[i]; jsfbOffsets[i+1]; j++) { + psyOutChan->mdctSpectrum[j] = 0; + } + } + } +} + +/********************************************************************************* +* +* function name: CalcFormFactor +* description: estimate Form factors for all channel +* +**********************************************************************************/ +void +CalcFormFactor(Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB], + Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB], + Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB], + PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + const Word16 nChannels) +{ + Word16 j; + + for (j=0; j=0; i--) { + pbSpreadedEnergy[i] = max(pbSpreadedEnergy[i], + L_mpy_ls(pbSpreadedEnergy[i+1], maskLowFactor[i])); + } +} diff --git a/media/libstagefright/codecs/aacenc/src/stat_bits.c b/media/libstagefright/codecs/aacenc/src/stat_bits.c new file mode 100644 index 0000000000000000000000000000000000000000..556104ee378feb0940a345b808bdb3028ab7acf5 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/stat_bits.c @@ -0,0 +1,237 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: stat_bits.c + + Content: Static bit counter functions + +*******************************************************************************/ + +#include "stat_bits.h" +#include "bitenc.h" +#include "tns.h" + + +typedef enum { + SI_ID_BITS =(3), + SI_FILL_COUNT_BITS =(4), + SI_FILL_ESC_COUNT_BITS =(8), + SI_FILL_EXTENTION_BITS =(4), + SI_FILL_NIBBLE_BITS =(4), + SI_SCE_BITS =(4), + SI_CPE_BITS =(5), + SI_CPE_MS_MASK_BITS =(2) , + SI_ICS_INFO_BITS_LONG =(1+2+1+6+1), + SI_ICS_INFO_BITS_SHORT =(1+2+1+4+7), + SI_ICS_BITS =(8+1+1+1) +} SI_BITS; + + +/********************************************************************************* +* +* function name: countMsMaskBits +* description: count ms stereo bits demand +* +**********************************************************************************/ +static Word16 countMsMaskBits(Word16 sfbCnt, + Word16 sfbPerGroup, + Word16 maxSfbPerGroup, + struct TOOLSINFO *toolsInfo) +{ + Word16 msBits, sfbOff, sfb; + msBits = 0; + + + switch(toolsInfo->msDigest) { + case MS_NONE: + case MS_ALL: + break; + + case MS_SOME: + for(sfbOff=0; sfbOfftnsActive[i]!=0) { + tnsPresent = 1; + } + } + + if (tnsPresent) { + /* there is data to be written*/ + /*count += 1; */ + for (i=0; itnsActive[i]) { + count += 1; + + if (blockType == 2) { + count += 4; + count += 3; + } + else { + count += 6; + count += 5; + } + + if (tnsInfo->order[i]) { + count += 1; /*direction*/ + count += 1; /*coef_compression */ + + if (tnsInfo->coefRes[i] == 4) { + ptcoef = tnsInfo->coef + i*TNS_MAX_ORDER_SHORT; + coefBits = 3; + for(k=0; korder[i]; k++) { + + if ((ptcoef[k] > 3) || (ptcoef[k] < -4)) { + coefBits = 4; + break; + } + } + } + else { + coefBits = 2; + ptcoef = tnsInfo->coef + i*TNS_MAX_ORDER_SHORT; + for(k=0; korder[i]; k++) { + + if ((ptcoef[k] > 1) || (ptcoef[k] < -2)) { + coefBits = 3; + break; + } + } + } + for (k=0; korder[i]; k++ ) { + count += coefBits; + } + } + } + } + } + + return count; +} + +/********************************************************************************** +* +* function name: countTnsBits +* description: count tns bit demand +* +**********************************************************************************/ +static Word16 countTnsBits(TNS_INFO *tnsInfo,Word16 blockType) +{ + return(tnsCount(tnsInfo, blockType)); +} + +/********************************************************************************* +* +* function name: countStaticBitdemand +* description: count static bit demand include tns +* +**********************************************************************************/ +Word16 countStaticBitdemand(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], + PSY_OUT_ELEMENT *psyOutElement, + Word16 channels, + Word16 adtsUsed) +{ + Word32 statBits; + Word32 ch; + + statBits = 0; + + /* if adts used, add 56 bits */ + if(adtsUsed) statBits += 56; + + + switch (channels) { + case 1: + statBits += SI_ID_BITS+SI_SCE_BITS+SI_ICS_BITS; + statBits += countTnsBits(&(psyOutChannel[0].tnsInfo), + psyOutChannel[0].windowSequence); + + switch(psyOutChannel[0].windowSequence){ + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + statBits += SI_ICS_INFO_BITS_LONG; + break; + case SHORT_WINDOW: + statBits += SI_ICS_INFO_BITS_SHORT; + break; + } + break; + case 2: + statBits += SI_ID_BITS+SI_CPE_BITS+2*SI_ICS_BITS; + + statBits += SI_CPE_MS_MASK_BITS; + statBits += countMsMaskBits(psyOutChannel[0].sfbCnt, + psyOutChannel[0].sfbPerGroup, + psyOutChannel[0].maxSfbPerGroup, + &psyOutElement->toolsInfo); + + switch (psyOutChannel[0].windowSequence) { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + statBits += SI_ICS_INFO_BITS_LONG; + break; + case SHORT_WINDOW: + statBits += SI_ICS_INFO_BITS_SHORT; + break; + } + for(ch=0; ch<2; ch++) + statBits += countTnsBits(&(psyOutChannel[ch].tnsInfo), + psyOutChannel[ch].windowSequence); + break; + } + + return statBits; +} + diff --git a/media/libstagefright/codecs/aacenc/src/tns.c b/media/libstagefright/codecs/aacenc/src/tns.c new file mode 100644 index 0000000000000000000000000000000000000000..96d890e62b1e3e077576323da2af635db7a93863 --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/tns.c @@ -0,0 +1,932 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: tns.c + + Content: Definition TNS tools functions + +*******************************************************************************/ + +#include "basic_op.h" +#include "oper_32b.h" +#include "assert.h" +#include "aac_rom.h" +#include "psy_const.h" +#include "tns.h" +#include "tns_param.h" +#include "psy_configuration.h" +#include "tns_func.h" + +#define TNS_MODIFY_BEGIN 2600 /* Hz */ +#define RATIO_PATCH_LOWER_BORDER 380 /* Hz */ +#define TNS_GAIN_THRESH 141 /* 1.41*100 */ +#define NORM_COEF 0x028f5c28 + +static const Word32 TNS_PARCOR_THRESH = 0x0ccccccd; /* 0.1*(1 << 31) */ +/* Limit bands to > 2.0 kHz */ +static unsigned short tnsMinBandNumberLong[12] = +{ 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 }; +static unsigned short tnsMinBandNumberShort[12] = +{ 2, 2, 2, 3, 3, 4, 6, 6, 8, 10, 10, 12 }; + +/**************************************/ +/* Main/Low Profile TNS Parameters */ +/**************************************/ +static unsigned short tnsMaxBandsLongMainLow[12] = +{ 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 }; + +static unsigned short tnsMaxBandsShortMainLow[12] = +{ 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 }; + + +static void CalcWeightedSpectrum(const Word32 spectrum[], + Word16 weightedSpectrum[], + Word32* sfbEnergy, + const Word16* sfbOffset, Word16 lpcStartLine, + Word16 lpcStopLine, Word16 lpcStartBand,Word16 lpcStopBand, + Word32 *pWork32); + + + +void AutoCorrelation(const Word16 input[], Word32 corr[], + Word16 samples, Word16 corrCoeff); +static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff); + +static Word16 CalcTnsFilter(const Word16* signal, const Word32 window[], Word16 numOfLines, + Word16 tnsOrder, Word32 parcor[]); + + +static void Parcor2Index(const Word32 parcor[], Word16 index[], Word16 order, + Word16 bitsPerCoeff); + +static void Index2Parcor(const Word16 index[], Word32 parcor[], Word16 order, + Word16 bitsPerCoeff); + + + +static void AnalysisFilterLattice(const Word32 signal[], Word16 numOfLines, + const Word32 parCoeff[], Word16 order, + Word32 output[]); + + +/** +* +* function name: FreqToBandWithRounding +* description: Retrieve index of nearest band border +* returnt: index +* +*/ +static Word16 FreqToBandWithRounding(Word32 freq, /*!< frequency in Hertz */ + Word32 fs, /*!< Sampling frequency in Hertz */ + Word16 numOfBands, /*!< total number of bands */ + const Word16 *bandStartOffset) /*!< table of band borders */ +{ + Word32 lineNumber, band; + Word32 temp, shift; + + /* assert(freq >= 0); */ + shift = norm_l(fs); + lineNumber = (extract_l(fixmul((bandStartOffset[numOfBands] << 2),Div_32(freq << shift,fs << shift))) + 1) >> 1; + + /* freq > fs/2 */ + temp = lineNumber - bandStartOffset[numOfBands] ; + if (temp >= 0) + return numOfBands; + + /* find band the line number lies in */ + for (band=0; band 0) break; + } + + temp = (lineNumber - bandStartOffset[band]); + temp = (temp - (bandStartOffset[band + 1] - lineNumber)); + if ( temp > 0 ) + { + band = band + 1; + } + + return extract_l(band); +} + + +/** +* +* function name: InitTnsConfigurationLong +* description: Fill TNS_CONFIG structure with sensible content for long blocks +* returns: 0 if success +* +*/ +Word16 InitTnsConfigurationLong(Word32 bitRate, /*!< bitrate */ + Word32 sampleRate, /*!< Sampling frequency */ + Word16 channels, /*!< number of channels */ + TNS_CONFIG *tC, /*!< TNS Config struct (modified) */ + PSY_CONFIGURATION_LONG *pC, /*!< psy config struct */ + Word16 active) /*!< tns active flag */ +{ + + Word32 bitratePerChannel; + tC->maxOrder = TNS_MAX_ORDER; + tC->tnsStartFreq = 1275; + tC->coefRes = 4; + + /* to avoid integer division */ + if ( sub(channels,2) == 0 ) { + bitratePerChannel = bitRate >> 1; + } + else { + bitratePerChannel = bitRate; + } + + tC->tnsMaxSfb = tnsMaxBandsLongMainLow[pC->sampRateIdx]; + + tC->tnsActive = active; + + /* now calc band and line borders */ + tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb); + tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand]; + + tC->tnsStartBand = FreqToBandWithRounding(tC->tnsStartFreq, sampleRate, + pC->sfbCnt, (const Word16*)pC->sfbOffset); + + tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN, + sampleRate, + pC->sfbCnt, + (const Word16*)pC->sfbOffset); + + tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER, + sampleRate, + pC->sfbCnt, + (const Word16*)pC->sfbOffset); + + + tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand]; + + tC->lpcStopBand = tnsMaxBandsLongMainLow[pC->sampRateIdx]; + tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive); + + tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand]; + + tC->lpcStartBand = tnsMinBandNumberLong[pC->sampRateIdx]; + + tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand]; + + tC->threshold = TNS_GAIN_THRESH; + + + return(0); +} + +/** +* +* function name: InitTnsConfigurationShort +* description: Fill TNS_CONFIG structure with sensible content for short blocks +* returns: 0 if success +* +*/ +Word16 InitTnsConfigurationShort(Word32 bitRate, /*!< bitrate */ + Word32 sampleRate, /*!< Sampling frequency */ + Word16 channels, /*!< number of channels */ + TNS_CONFIG *tC, /*!< TNS Config struct (modified) */ + PSY_CONFIGURATION_SHORT *pC, /*!< psy config struct */ + Word16 active) /*!< tns active flag */ +{ + Word32 bitratePerChannel; + tC->maxOrder = TNS_MAX_ORDER_SHORT; + tC->tnsStartFreq = 2750; + tC->coefRes = 3; + + /* to avoid integer division */ + if ( sub(channels,2) == 0 ) { + bitratePerChannel = L_shr(bitRate,1); + } + else { + bitratePerChannel = bitRate; + } + + tC->tnsMaxSfb = tnsMaxBandsShortMainLow[pC->sampRateIdx]; + + tC->tnsActive = active; + + /* now calc band and line borders */ + tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb); + tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand]; + + tC->tnsStartBand=FreqToBandWithRounding(tC->tnsStartFreq, sampleRate, + pC->sfbCnt, (const Word16*)pC->sfbOffset); + + tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN, + sampleRate, + pC->sfbCnt, + (const Word16*)pC->sfbOffset); + + tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER, + sampleRate, + pC->sfbCnt, + (const Word16*)pC->sfbOffset); + + + tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand]; + + tC->lpcStopBand = tnsMaxBandsShortMainLow[pC->sampRateIdx]; + + tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive); + + tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand]; + + tC->lpcStartBand = tnsMinBandNumberShort[pC->sampRateIdx]; + + tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand]; + + tC->threshold = TNS_GAIN_THRESH; + + return(0); +} + +/** +* +* function name: TnsDetect +* description: Calculate TNS filter and decide on TNS usage +* returns: 0 if success +* +*/ +Word32 TnsDetect(TNS_DATA* tnsData, /*!< tns data structure (modified) */ + TNS_CONFIG tC, /*!< tns config structure */ + Word32* pScratchTns, /*!< pointer to scratch space */ + const Word16 sfbOffset[], /*!< scalefactor size and table */ + Word32* spectrum, /*!< spectral data */ + Word16 subBlockNumber, /*!< subblock num */ + Word16 blockType, /*!< blocktype (long or short) */ + Word32 * sfbEnergy) /*!< sfb-wise energy */ +{ + + Word32 predictionGain; + Word32 temp; + Word32* pWork32 = &pScratchTns[subBlockNumber >> 8]; + Word16* pWeightedSpectrum = (Word16 *)&pScratchTns[subBlockNumber >> 8]; + + + if (tC.tnsActive) { + CalcWeightedSpectrum(spectrum, + pWeightedSpectrum, + sfbEnergy, + sfbOffset, + tC.lpcStartLine, + tC.lpcStopLine, + tC.lpcStartBand, + tC.lpcStopBand, + pWork32); + + temp = blockType - SHORT_WINDOW; + if ( temp != 0 ) { + predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine], + tC.acfWindow, + tC.lpcStopLine - tC.lpcStartLine, + tC.maxOrder, + tnsData->dataRaw.tnsLong.subBlockInfo.parcor); + + + temp = predictionGain - tC.threshold; + if ( temp > 0 ) { + tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 1; + } + else { + tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0; + } + + tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = predictionGain; + } + else{ + + predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine], + tC.acfWindow, + tC.lpcStopLine - tC.lpcStartLine, + tC.maxOrder, + tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].parcor); + + temp = predictionGain - tC.threshold; + if ( temp > 0 ) { + tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 1; + } + else { + tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0; + } + + tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = predictionGain; + } + + } + else{ + + temp = blockType - SHORT_WINDOW; + if ( temp != 0 ) { + tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0; + tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = 0; + } + else { + tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0; + tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = 0; + } + } + + return(0); +} + + +/***************************************************************************** +* +* function name: TnsSync +* description: update tns parameter +* +*****************************************************************************/ +void TnsSync(TNS_DATA *tnsDataDest, + const TNS_DATA *tnsDataSrc, + const TNS_CONFIG tC, + const Word16 subBlockNumber, + const Word16 blockType) +{ + TNS_SUBBLOCK_INFO *sbInfoDest; + const TNS_SUBBLOCK_INFO *sbInfoSrc; + Word32 i, temp; + + temp = blockType - SHORT_WINDOW; + if ( temp != 0 ) { + sbInfoDest = &tnsDataDest->dataRaw.tnsLong.subBlockInfo; + sbInfoSrc = &tnsDataSrc->dataRaw.tnsLong.subBlockInfo; + } + else { + sbInfoDest = &tnsDataDest->dataRaw.tnsShort.subBlockInfo[subBlockNumber]; + sbInfoSrc = &tnsDataSrc->dataRaw.tnsShort.subBlockInfo[subBlockNumber]; + } + + if (100*abs_s(sbInfoDest->predictionGain - sbInfoSrc->predictionGain) < + (3 * sbInfoDest->predictionGain)) { + sbInfoDest->tnsActive = sbInfoSrc->tnsActive; + for ( i=0; i< tC.maxOrder; i++) { + sbInfoDest->parcor[i] = sbInfoSrc->parcor[i]; + } + } +} + +/***************************************************************************** +* +* function name: TnsEncode +* description: do TNS filtering +* returns: 0 if success +* +*****************************************************************************/ +Word16 TnsEncode(TNS_INFO* tnsInfo, /*!< tns info structure (modified) */ + TNS_DATA* tnsData, /*!< tns data structure (modified) */ + Word16 numOfSfb, /*!< number of scale factor bands */ + TNS_CONFIG tC, /*!< tns config structure */ + Word16 lowPassLine, /*!< lowpass line */ + Word32* spectrum, /*!< spectral data (modified) */ + Word16 subBlockNumber, /*!< subblock num */ + Word16 blockType) /*!< blocktype (long or short) */ +{ + Word32 i; + Word32 temp_s; + Word32 temp; + TNS_SUBBLOCK_INFO *psubBlockInfo; + + temp_s = blockType - SHORT_WINDOW; + if ( temp_s != 0) { + psubBlockInfo = &tnsData->dataRaw.tnsLong.subBlockInfo; + if (psubBlockInfo->tnsActive == 0) { + tnsInfo->tnsActive[subBlockNumber] = 0; + return(0); + } + else { + + Parcor2Index(psubBlockInfo->parcor, + tnsInfo->coef, + tC.maxOrder, + tC.coefRes); + + Index2Parcor(tnsInfo->coef, + psubBlockInfo->parcor, + tC.maxOrder, + tC.coefRes); + + for (i=tC.maxOrder - 1; i>=0; i--) { + temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH; + if ( temp > 0 ) + break; + temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH; + if ( temp < 0 ) + break; + } + tnsInfo->order[subBlockNumber] = i + 1; + + + tnsInfo->tnsActive[subBlockNumber] = 1; + for (i=subBlockNumber+1; itnsActive[i] = 0; + } + tnsInfo->coefRes[subBlockNumber] = tC.coefRes; + tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand; + + + AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]), + (min(tC.tnsStopLine,lowPassLine) - tC.tnsStartLine), + psubBlockInfo->parcor, + tnsInfo->order[subBlockNumber], + &(spectrum[tC.tnsStartLine])); + + } + } /* if (blockType!=SHORT_WINDOW) */ + else /*short block*/ { + psubBlockInfo = &tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber]; + if (psubBlockInfo->tnsActive == 0) { + tnsInfo->tnsActive[subBlockNumber] = 0; + return(0); + } + else { + + Parcor2Index(psubBlockInfo->parcor, + &tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT], + tC.maxOrder, + tC.coefRes); + + Index2Parcor(&tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT], + psubBlockInfo->parcor, + tC.maxOrder, + tC.coefRes); + for (i=(tC.maxOrder - 1); i>=0; i--) { + temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH; + if ( temp > 0 ) + break; + + temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH; + if ( temp < 0 ) + break; + } + tnsInfo->order[subBlockNumber] = i + 1; + + tnsInfo->tnsActive[subBlockNumber] = 1; + tnsInfo->coefRes[subBlockNumber] = tC.coefRes; + tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand; + + + AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]), (tC.tnsStopLine - tC.tnsStartLine), + psubBlockInfo->parcor, + tnsInfo->order[subBlockNumber], + &(spectrum[tC.tnsStartLine])); + + } + } + + return(0); +} + + +/***************************************************************************** +* +* function name: m_pow2_cordic +* description: Iterative power function +* +* Calculates pow(2.0,x-1.0*(scale+1)) with INT_BITS bit precision +* using modified cordic algorithm +* returns: the result of pow2 +* +*****************************************************************************/ +static Word32 m_pow2_cordic(Word32 x, Word16 scale) +{ + Word32 k; + + Word32 accu_y = 0x40000000; + accu_y = L_shr(accu_y,scale); + + for(k=1; k= 0) { + + x = L_sub(x, z); + accu_y = L_add(accu_y, (accu_y >> k)); + } + } + return(accu_y); +} + + +/***************************************************************************** +* +* function name: CalcWeightedSpectrum +* description: Calculate weighted spectrum for LPC calculation +* +*****************************************************************************/ +static void CalcWeightedSpectrum(const Word32 spectrum[], /*!< input spectrum */ + Word16 weightedSpectrum[], + Word32 *sfbEnergy, /*!< sfb energies */ + const Word16 *sfbOffset, + Word16 lpcStartLine, + Word16 lpcStopLine, + Word16 lpcStartBand, + Word16 lpcStopBand, + Word32 *pWork32) +{ + #define INT_BITS_SCAL 1<<(INT_BITS/2) + + Word32 i, sfb, shift; + Word32 maxShift; + Word32 tmp_s, tmp2_s; + Word32 tmp, tmp2; + Word32 maxWS; + Word32 tnsSfbMean[MAX_SFB]; /* length [lpcStopBand-lpcStartBand] should be sufficient here */ + + maxWS = 0; + + /* calc 1.0*2^-INT_BITS/2/sqrt(en) */ + for( sfb = lpcStartBand; sfb < lpcStopBand; sfb++) { + + tmp2 = sfbEnergy[sfb] - 2; + if( tmp2 > 0) { + tmp = rsqrt(sfbEnergy[sfb], INT_BITS); + if(tmp > INT_BITS_SCAL) + { + shift = norm_l(tmp); + tmp = Div_32( INT_BITS_SCAL << shift, tmp << shift ); + } + else + { + tmp = 0x7fffffff; + } + } + else { + tmp = 0x7fffffff; + } + tnsSfbMean[sfb] = tmp; + } + + /* spread normalized values from sfbs to lines */ + sfb = lpcStartBand; + tmp = tnsSfbMean[sfb]; + for ( i=lpcStartLine; i=lpcStartLine; i--){ + pWork32[i] = (pWork32[i] + pWork32[i + 1]) >> 1; + } + /* filter up */ + for (i=(lpcStartLine + 1); i> 1; + } + + /* weight and normalize */ + for (i=lpcStartLine; i= 0) + { + for (i=lpcStartLine; i> maxShift; + } + } + else + { + maxShift = -maxShift; + for (i=lpcStartLine; i> scf)); + } + corr[0] = accu; + + /* early termination if all corr coeffs are likely going to be zero */ + if(corr[0] == 0) return ; + + /* calc all other corrCoef: R[j] = sum { t[i] * t[i+j] } ; i = 0..(N-j-1), j=1..p */ + for(i=1; i> scf)); + } + corr[i] = accu; + } +} +#endif + +/***************************************************************************** +* +* function name: AutoToParcor +* description: conversion autocorrelation to reflection coefficients +* returns: prediction gain +* input: input values, no. of output values (=order), +* ptr. to workbuffer (required size: 2*order) +* output: reflection coefficients +* +*****************************************************************************/ +static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff) { + + Word32 i, j, shift; + Word32 *pWorkBuffer; /* temp pointer */ + Word32 predictionGain = 0; + Word32 num, denom; + Word32 temp, workBuffer0; + + + num = workBuffer[0]; + temp = workBuffer[numOfCoeff]; + + for(i=0; i 0) + index=i; + } + return extract_l(index - 4); +} + +static Word16 Search4(Word32 parcor) +{ + Word32 index = 0; + Word32 i; + Word32 temp; + + + for (i=0;i<16;i++) { + temp = L_sub(parcor, tnsCoeff4Borders[i]); + if (temp > 0) + index=i; + } + return extract_l(index - 8); +} + + + +/***************************************************************************** +* +* functionname: Parcor2Index +* description: quantization index for reflection coefficients +* +*****************************************************************************/ +static void Parcor2Index(const Word32 parcor[], /*!< parcor coefficients */ + Word16 index[], /*!< quantized coeff indices */ + Word16 order, /*!< filter order */ + Word16 bitsPerCoeff) { /*!< quantizer resolution */ + Word32 i; + Word32 temp; + + for(i=0; i> 1; + tmpSave = x; + + for (i=0; i<(order - 1); i++) { + + tmp = L_add(fixmul(coef_par[i], x), state_par[i]); + x = L_add(fixmul(coef_par[i], state_par[i]), x); + + state_par[i] = tmpSave; + tmpSave = tmp; + } + + /* last stage: only need half operations */ + accu = fixmul(state_par[order - 1], coef_par[(order - 1)]); + state_par[(order - 1)] = tmpSave; + + x = L_add(accu, x); + x = L_add(x, x); + + return x; +} + +/***************************************************************************** +* +* functionname: AnalysisFilterLattice +* description: filters spectral lines with TNS filter +* +*****************************************************************************/ +static void AnalysisFilterLattice(const Word32 signal[], /*!< input spectrum */ + Word16 numOfLines, /*!< no. of lines */ + const Word32 parCoeff[],/*!< PARC coefficients */ + Word16 order, /*!< filter order */ + Word32 output[]) /*!< filtered signal values */ +{ + + Word32 state_par[TNS_MAX_ORDER]; + Word32 j; + + for ( j=0; j> 2); + } + } +} diff --git a/media/libstagefright/codecs/aacenc/src/transform.c b/media/libstagefright/codecs/aacenc/src/transform.c new file mode 100644 index 0000000000000000000000000000000000000000..af17b5a5a9a683fecabc708410e7c601340d979c --- /dev/null +++ b/media/libstagefright/codecs/aacenc/src/transform.c @@ -0,0 +1,672 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: transform.c + + Content: MDCT Transform functionss + +*******************************************************************************/ + +#include "basic_op.h" +#include "psy_const.h" +#include "transform.h" +#include "aac_rom.h" + + +#define LS_TRANS ((FRAME_LEN_LONG-FRAME_LEN_SHORT)/2) /* 448 */ +#define SQRT1_2 0x5a82799a /* sqrt(1/2) in Q31 */ +#define swap2(p0,p1) \ + t = p0; t1 = *(&(p0)+1); \ + p0 = p1; *(&(p0)+1) = *(&(p1)+1); \ + p1 = t; *(&(p1)+1) = t1 + +/********************************************************************************* +* +* function name: Shuffle +* description: Shuffle points prepared function for fft +* +**********************************************************************************/ +static void Shuffle(int *buf, int num, const unsigned char* bitTab) +{ + int *part0, *part1; + int i, j; + int t, t1; + + part0 = buf; + part1 = buf + num; + + while ((i = *bitTab++) != 0) { + j = *bitTab++; + + swap2(part0[4*i+0], part0[4*j+0]); + swap2(part0[4*i+2], part1[4*j+0]); + swap2(part1[4*i+0], part0[4*j+2]); + swap2(part1[4*i+2], part1[4*j+2]); + } + + do { + swap2(part0[4*i+2], part1[4*i+0]); + } while ((i = *bitTab++) != 0); +} + +#if !defined(ARMV5E) && !defined(ARMV7Neon) + +/***************************************************************************** +* +* function name: Radix4First +* description: Radix 4 point prepared function for fft +* +**********************************************************************************/ +static void Radix4First(int *buf, int num) +{ + int r0, r1, r2, r3; + int r4, r5, r6, r7; + + for (; num != 0; num--) + { + r0 = buf[0] + buf[2]; + r1 = buf[1] + buf[3]; + r2 = buf[0] - buf[2]; + r3 = buf[1] - buf[3]; + r4 = buf[4] + buf[6]; + r5 = buf[5] + buf[7]; + r6 = buf[4] - buf[6]; + r7 = buf[5] - buf[7]; + + buf[0] = r0 + r4; + buf[1] = r1 + r5; + buf[4] = r0 - r4; + buf[5] = r1 - r5; + buf[2] = r2 + r7; + buf[3] = r3 - r6; + buf[6] = r2 - r7; + buf[7] = r3 + r6; + + buf += 8; + } +} + +/***************************************************************************** +* +* function name: Radix8First +* description: Radix 8 point prepared function for fft +* +**********************************************************************************/ +static void Radix8First(int *buf, int num) +{ + int r0, r1, r2, r3; + int i0, i1, i2, i3; + int r4, r5, r6, r7; + int i4, i5, i6, i7; + int t0, t1, t2, t3; + + for ( ; num != 0; num--) + { + r0 = buf[0] + buf[2]; + i0 = buf[1] + buf[3]; + r1 = buf[0] - buf[2]; + i1 = buf[1] - buf[3]; + r2 = buf[4] + buf[6]; + i2 = buf[5] + buf[7]; + r3 = buf[4] - buf[6]; + i3 = buf[5] - buf[7]; + + r4 = (r0 + r2) >> 1; + i4 = (i0 + i2) >> 1; + r5 = (r0 - r2) >> 1; + i5 = (i0 - i2) >> 1; + r6 = (r1 - i3) >> 1; + i6 = (i1 + r3) >> 1; + r7 = (r1 + i3) >> 1; + i7 = (i1 - r3) >> 1; + + r0 = buf[ 8] + buf[10]; + i0 = buf[ 9] + buf[11]; + r1 = buf[ 8] - buf[10]; + i1 = buf[ 9] - buf[11]; + r2 = buf[12] + buf[14]; + i2 = buf[13] + buf[15]; + r3 = buf[12] - buf[14]; + i3 = buf[13] - buf[15]; + + t0 = (r0 + r2) >> 1; + t1 = (i0 + i2) >> 1; + t2 = (r0 - r2) >> 1; + t3 = (i0 - i2) >> 1; + + buf[ 0] = r4 + t0; + buf[ 1] = i4 + t1; + buf[ 8] = r4 - t0; + buf[ 9] = i4 - t1; + buf[ 4] = r5 + t3; + buf[ 5] = i5 - t2; + buf[12] = r5 - t3; + buf[13] = i5 + t2; + + r0 = r1 - i3; + i0 = i1 + r3; + r2 = r1 + i3; + i2 = i1 - r3; + + t0 = MULHIGH(SQRT1_2, r0 - i0); + t1 = MULHIGH(SQRT1_2, r0 + i0); + t2 = MULHIGH(SQRT1_2, r2 - i2); + t3 = MULHIGH(SQRT1_2, r2 + i2); + + buf[ 6] = r6 - t0; + buf[ 7] = i6 - t1; + buf[14] = r6 + t0; + buf[15] = i6 + t1; + buf[ 2] = r7 + t3; + buf[ 3] = i7 - t2; + buf[10] = r7 - t3; + buf[11] = i7 + t2; + + buf += 16; + } +} + +/***************************************************************************** +* +* function name: Radix4FFT +* description: Radix 4 point fft core function +* +**********************************************************************************/ +static void Radix4FFT(int *buf, int num, int bgn, int *twidTab) +{ + int r0, r1, r2, r3; + int r4, r5, r6, r7; + int t0, t1; + int sinx, cosx; + int i, j, step; + int *xptr, *csptr; + + for (num >>= 2; num != 0; num >>= 2) + { + step = 2*bgn; + xptr = buf; + + for (i = num; i != 0; i--) + { + csptr = twidTab; + + for (j = bgn; j != 0; j--) + { + r0 = xptr[0]; + r1 = xptr[1]; + xptr += step; + + t0 = xptr[0]; + t1 = xptr[1]; + cosx = csptr[0]; + sinx = csptr[1]; + r2 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1); /* cos*br + sin*bi */ + r3 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0); /* cos*bi - sin*br */ + xptr += step; + + t0 = r0 >> 2; + t1 = r1 >> 2; + r0 = t0 - r2; + r1 = t1 - r3; + r2 = t0 + r2; + r3 = t1 + r3; + + t0 = xptr[0]; + t1 = xptr[1]; + cosx = csptr[2]; + sinx = csptr[3]; + r4 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1); /* cos*cr + sin*ci */ + r5 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0); /* cos*ci - sin*cr */ + xptr += step; + + t0 = xptr[0]; + t1 = xptr[1]; + cosx = csptr[4]; + sinx = csptr[5]; + r6 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1); /* cos*cr + sin*ci */ + r7 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0); /* cos*ci - sin*cr */ + csptr += 6; + + t0 = r4; + t1 = r5; + r4 = t0 + r6; + r5 = r7 - t1; + r6 = t0 - r6; + r7 = r7 + t1; + + xptr[0] = r0 + r5; + xptr[1] = r1 + r6; + xptr -= step; + + xptr[0] = r2 - r4; + xptr[1] = r3 - r7; + xptr -= step; + + xptr[0] = r0 - r5; + xptr[1] = r1 - r6; + xptr -= step; + + xptr[0] = r2 + r4; + xptr[1] = r3 + r7; + xptr += 2; + } + xptr += 3*step; + } + twidTab += 3*step; + bgn <<= 2; + } +} + +/********************************************************************************* +* +* function name: PreMDCT +* description: prepare MDCT process for next FFT compute +* +**********************************************************************************/ +static void PreMDCT(int *buf0, int num, const int *csptr) +{ + int i; + int tr1, ti1, tr2, ti2; + int cosa, sina, cosb, sinb; + int *buf1; + + buf1 = buf0 + num - 1; + + for(i = num >> 2; i != 0; i--) + { + cosa = *csptr++; + sina = *csptr++; + cosb = *csptr++; + sinb = *csptr++; + + tr1 = *(buf0 + 0); + ti2 = *(buf0 + 1); + tr2 = *(buf1 - 1); + ti1 = *(buf1 + 0); + + *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1); + *buf0++ = MULHIGH(cosa, ti1) - MULHIGH(sina, tr1); + + *buf1-- = MULHIGH(cosb, ti2) - MULHIGH(sinb, tr2); + *buf1-- = MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2); + } +} + +/********************************************************************************* +* +* function name: PostMDCT +* description: post MDCT process after next FFT for MDCT +* +**********************************************************************************/ +static void PostMDCT(int *buf0, int num, const int *csptr) +{ + int i; + int tr1, ti1, tr2, ti2; + int cosa, sina, cosb, sinb; + int *buf1; + + buf1 = buf0 + num - 1; + + for(i = num >> 2; i != 0; i--) + { + cosa = *csptr++; + sina = *csptr++; + cosb = *csptr++; + sinb = *csptr++; + + tr1 = *(buf0 + 0); + ti1 = *(buf0 + 1); + ti2 = *(buf1 + 0); + tr2 = *(buf1 - 1); + + *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1); + *buf1-- = MULHIGH(sina, tr1) - MULHIGH(cosa, ti1); + + *buf0++ = MULHIGH(sinb, tr2) - MULHIGH(cosb, ti2); + *buf1-- = MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2); + } +} +#endif + + +/********************************************************************************** +* +* function name: Mdct_Long +* description: the long block mdct, include long_start block, end_long block +* +**********************************************************************************/ +void Mdct_Long(int *buf) +{ + PreMDCT(buf, 1024, cossintab + 128); + + Shuffle(buf, 512, bitrevTab + 17); + Radix8First(buf, 512 >> 3); + Radix4FFT(buf, 512 >> 3, 8, (int *)twidTab512); + + PostMDCT(buf, 1024, cossintab + 128); +} + + +/********************************************************************************** +* +* function name: Mdct_Short +* description: the short block mdct +* +**********************************************************************************/ +void Mdct_Short(int *buf) +{ + PreMDCT(buf, 128, cossintab); + + Shuffle(buf, 64, bitrevTab); + Radix4First(buf, 64 >> 2); + Radix4FFT(buf, 64 >> 2, 4, (int *)twidTab64); + + PostMDCT(buf, 128, cossintab); +} + + +/***************************************************************************** +* +* function name: shiftMdctDelayBuffer +* description: the mdct delay buffer has a size of 1600, +* so the calculation of LONG,STOP must be spilt in two +* passes with 1024 samples and a mid shift, +* the SHORT transforms can be completed in the delay buffer, +* and afterwards a shift +* +**********************************************************************************/ +static void shiftMdctDelayBuffer(Word16 *mdctDelayBuffer, /*! start of mdct delay buffer */ + Word16 *timeSignal, /*! pointer to new time signal samples, interleaved */ + Word16 chIncrement /*! number of channels */ + ) +{ + Word32 i; + Word16 *srBuf = mdctDelayBuffer; + Word16 *dsBuf = mdctDelayBuffer+FRAME_LEN_LONG; + + for(i = 0; i < BLOCK_SWITCHING_OFFSET-FRAME_LEN_LONG; i+= 8) + { + *srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++; + *srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++; + *srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++; + *srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++; + } + + srBuf = mdctDelayBuffer + BLOCK_SWITCHING_OFFSET-FRAME_LEN_LONG; + dsBuf = timeSignal; + + for(i=0; i> 16); + timeSignalSample = (*dctIn1--) << minSf; + ws2 = timeSignalSample * (*winPtr & 0xffff); + winPtr ++; + /* shift 2 to avoid overflow next */ + *outData0++ = (ws1 >> 2) - (ws2 >> 2); + } + + shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement); + + /* add windows and pre add for mdct to new buffer*/ + dctIn0 = mdctDelayBuffer; + dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1; + outData0 = realOut + FRAME_LEN_LONG/2 - 1; + winPtr = (int *)LongWindowKBD; + for(i=0;i> 16); + winPtr++; + /* shift 2 to avoid overflow next */ + *outData0-- = -((ws1 >> 2) + (ws2 >> 2)); + } + + Mdct_Long(realOut); + /* update scale factor */ + minSf = 14 - minSf; + *mdctScale=minSf; + break; + + case START_WINDOW: + /* + we access BLOCK_SWITCHING_OFFSET (1600 ) delay buffer samples + no timeSignal samples + and get the biggest scale factor for next calculate more precise + */ + minSf = getScalefactorOfShortVectorStride(mdctDelayBuffer,BLOCK_SWITCHING_OFFSET,1); + minSf = min(minSf,14); + + dctIn0 = mdctDelayBuffer; + dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1; + outData0 = realOut + FRAME_LEN_LONG/2; + winPtr = (int *)LongWindowKBD; + + /* add windows and pre add for mdct to last buffer*/ + for(i=0;i> 16); + timeSignalSample = (*dctIn1--) << minSf; + ws2 = timeSignalSample * (*winPtr & 0xffff); + winPtr ++; + *outData0++ = (ws1 >> 2) - (ws2 >> 2); /* shift 2 to avoid overflow next */ + } + + shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement); + + outData0 = realOut + FRAME_LEN_LONG/2 - 1; + for(i=0;i> 16); + winPtr++; + *outData0-- = -((ws1 >> 2) + (ws2 >> 2)); /* shift 2 to avoid overflow next */ + } + + Mdct_Long(realOut); + /* update scale factor */ + minSf = 14 - minSf; + *mdctScale= minSf; + break; + + case STOP_WINDOW: + /* + we access BLOCK_SWITCHING_OFFSET-LS_TRANS (1600-448 ) delay buffer samples + 448 new timeSignal samples + and get the biggest scale factor for next calculate more precise + */ + delayBufferSf = getScalefactorOfShortVectorStride(mdctDelayBuffer+LS_TRANS,BLOCK_SWITCHING_OFFSET-LS_TRANS,1); + timeSignalSf = getScalefactorOfShortVectorStride(timeSignal,2*FRAME_LEN_LONG-BLOCK_SWITCHING_OFFSET,chIncrement); + minSf = min(delayBufferSf,timeSignalSf); + minSf = min(minSf,13); + + outData0 = realOut + FRAME_LEN_LONG/2; + dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1; + for(i=0;i> 16); + timeSignalSample= (*dctIn1--) << minSf; + ws2 = timeSignalSample * (*winPtr & 0xffff); + winPtr++; + *outData0++ = (ws1 >> 2) - (ws2 >> 2); /* shift 2 to avoid overflow next */ + } + + shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement); + + /* add windows and pre add for mdct to new buffer*/ + dctIn0 = mdctDelayBuffer; + dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1; + outData0 = realOut + FRAME_LEN_LONG/2 - 1; + winPtr = (int *)LongWindowKBD; + for(i=0;i> 16); + *outData0-- = -((ws1 >> 2) + (ws2 >> 2)); /* shift 2 to avoid overflow next */ + winPtr++; + } + + Mdct_Long(realOut); + minSf = 14 - minSf; + *mdctScale= minSf; /* update scale factor */ + break; + + case SHORT_WINDOW: + /* + we access BLOCK_SWITCHING_OFFSET (1600 ) delay buffer samples + no new timeSignal samples + and get the biggest scale factor for next calculate more precise + */ + minSf = getScalefactorOfShortVectorStride(mdctDelayBuffer+TRANSFORM_OFFSET_SHORT,9*FRAME_LEN_SHORT,1); + minSf = min(minSf,10); + + + for(w=0;w> 16); + timeSignalSample= *dctIn1 << minSf; + ws2 = timeSignalSample * (*winPtr & 0xffff); + *outData0++ = (ws1 >> 2) - (ws2 >> 2); /* shift 2 to avoid overflow next */ + + timeSignalSample= *(dctIn0 + FRAME_LEN_SHORT) << minSf; + ws1 = timeSignalSample * (*winPtr & 0xffff); + timeSignalSample= *(dctIn1 + FRAME_LEN_SHORT) << minSf; + ws2 = timeSignalSample * (*winPtr >> 16); + *outData1-- = -((ws1 >> 2) + (ws2 >> 2)); /* shift 2 to avoid overflow next */ + + winPtr++; + dctIn0++; + dctIn1--; + } + + Mdct_Short(realOut); + realOut += FRAME_LEN_SHORT; + } + + minSf = 11 - minSf; + *mdctScale = minSf; /* update scale factor */ + + shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement); + break; + } +} + diff --git a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp index f34967170c7f57a8baf1101495292218edba5e17..cb680ba97fb4d31f64c53fceca57d7e4cd010cd0 100644 --- a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp +++ b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp @@ -29,8 +29,9 @@ namespace android { static const int32_t kNumSamplesPerFrame = 160; static const int32_t kSampleRate = 8000; -AMRNBEncoder::AMRNBEncoder(const sp &source) +AMRNBEncoder::AMRNBEncoder(const sp &source, const sp &meta) : mSource(source), + mMeta(meta), mStarted(false), mBufferGroup(NULL), mEncState(NULL), @@ -119,28 +120,16 @@ status_t AMRNBEncoder::stop() { sp AMRNBEncoder::getFormat() { sp srcFormat = mSource->getFormat(); - int32_t numChannels; - int32_t sampleRate; - - CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels)); - CHECK_EQ(numChannels, 1); - - CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); - CHECK_EQ(sampleRate, kSampleRate); - - sp meta = new MetaData; - meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB); - meta->setInt32(kKeyChannelCount, numChannels); - meta->setInt32(kKeySampleRate, sampleRate); + mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB); int64_t durationUs; if (srcFormat->findInt64(kKeyDuration, &durationUs)) { - meta->setInt64(kKeyDuration, durationUs); + mMeta->setInt64(kKeyDuration, durationUs); } - meta->setCString(kKeyDecoderComponent, "AMRNBEncoder"); + mMeta->setCString(kKeyDecoderComponent, "AMRNBEncoder"); - return meta; + return mMeta; } status_t AMRNBEncoder::read( diff --git a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d129255e61434f03662172638b668503bb07e29 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2010 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. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "AMRWBEncoder" +#include + +#include "AMRWBEncoder.h" +#include "voAMRWB.h" +#include "cmnMemory.h" + +#include +#include +#include +#include +#include + +namespace android { + +static const int32_t kNumSamplesPerFrame = 320; +static const int32_t kBitsPerSample = 16; +static const int32_t kInputBufferSize = (kBitsPerSample / 8) * kNumSamplesPerFrame; +static const int32_t kSampleRate = 16000; +static const int32_t kNumChannels = 1; + +AMRWBEncoder::AMRWBEncoder(const sp &source, const sp &meta) + : mSource(source), + mMeta(meta), + mStarted(false), + mBufferGroup(NULL), + mInputBuffer(NULL), + mEncoderHandle(NULL), + mApiHandle(NULL), + mMemOperator(NULL), + mAnchorTimeUs(0), + mNumFramesOutput(0), + mNumInputSamples(0) { +} + +static VOAMRWBMODE pickModeFromBitRate(int32_t bps) { + CHECK(bps >= 0); + if (bps <= 6600) { + return VOAMRWB_MD66; + } else if (bps <= 8850) { + return VOAMRWB_MD885; + } else if (bps <= 12650) { + return VOAMRWB_MD1265; + } else if (bps <= 14250) { + return VOAMRWB_MD1425; + } else if (bps <= 15850) { + return VOAMRWB_MD1585; + } else if (bps <= 18250) { + return VOAMRWB_MD1825; + } else if (bps <= 19850) { + return VOAMRWB_MD1985; + } else if (bps <= 23050) { + return VOAMRWB_MD2305; + } + return VOAMRWB_MD2385; +} + +status_t AMRWBEncoder::initCheck() { + CHECK(mApiHandle == NULL && mEncoderHandle == NULL); + CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate)); + + mApiHandle = new VO_AUDIO_CODECAPI; + CHECK(mApiHandle); + + if (VO_ERR_NONE != voGetAMRWBEncAPI(mApiHandle)) { + LOGE("Failed to get api handle"); + return UNKNOWN_ERROR; + } + + mMemOperator = new VO_MEM_OPERATOR; + CHECK(mMemOperator != NULL); + mMemOperator->Alloc = cmnMemAlloc; + mMemOperator->Copy = cmnMemCopy; + mMemOperator->Free = cmnMemFree; + mMemOperator->Set = cmnMemSet; + mMemOperator->Check = cmnMemCheck; + + VO_CODEC_INIT_USERDATA userData; + memset(&userData, 0, sizeof(userData)); + userData.memflag = VO_IMF_USERMEMOPERATOR; + userData.memData = (VO_PTR) mMemOperator; + if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &userData)) { + LOGE("Failed to init AMRWB encoder"); + return UNKNOWN_ERROR; + } + + // Configure AMRWB encoder$ + VOAMRWBMODE mode = pickModeFromBitRate(mBitRate); + if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_MODE, &mode)) { + LOGE("Failed to set AMRWB encoder mode to %d", mode); + return UNKNOWN_ERROR; + } + + VOAMRWBFRAMETYPE type = VOAMRWB_RFC3267; + if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &type)) { + LOGE("Failed to set AMRWB encoder frame type to %d", type); + return UNKNOWN_ERROR; + } + + return OK; +} + +AMRWBEncoder::~AMRWBEncoder() { + if (mStarted) { + stop(); + } +} + +status_t AMRWBEncoder::start(MetaData *params) { + CHECK(!mStarted); + + mBufferGroup = new MediaBufferGroup; + + // The largest buffer size is header + 477 bits + mBufferGroup->add_buffer(new MediaBuffer(1024)); + + CHECK_EQ(OK, initCheck()); + + mNumFramesOutput = 0; + mSource->start(); + + mStarted = true; + + return OK; +} + +status_t AMRWBEncoder::stop() { + CHECK(mStarted); + + + if (mInputBuffer) { + mInputBuffer->release(); + mInputBuffer = NULL; + } + + delete mBufferGroup; + mBufferGroup = NULL; + + + CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle)); + mEncoderHandle = NULL; + + delete mApiHandle; + mApiHandle = NULL; + + delete mMemOperator; + mMemOperator; + + mStarted = false; + + mSource->stop(); + return OK; +} + +sp AMRWBEncoder::getFormat() { + sp srcFormat = mSource->getFormat(); + + mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB); + + int64_t durationUs; + if (srcFormat->findInt64(kKeyDuration, &durationUs)) { + mMeta->setInt64(kKeyDuration, durationUs); + } + + mMeta->setCString(kKeyDecoderComponent, "AMRWBEncoder"); + + return mMeta; +} + +status_t AMRWBEncoder::read( + MediaBuffer **out, const ReadOptions *options) { + status_t err; + + *out = NULL; + + int64_t seekTimeUs; + CHECK(options == NULL || !options->getSeekTo(&seekTimeUs)); + + while (mNumInputSamples < kNumSamplesPerFrame) { + if (mInputBuffer == NULL) { + err = mSource->read(&mInputBuffer, options); + + if (err != OK) { + if (mNumInputSamples == 0) { + return ERROR_END_OF_STREAM; + } + memset(&mInputFrame[mNumInputSamples], + 0, + sizeof(int16_t) + * (kNumSamplesPerFrame - mNumInputSamples)); + mNumInputSamples = 0; + break; + } + + size_t align = mInputBuffer->range_length() % sizeof(int16_t); + CHECK_EQ(align, 0); + + int64_t timeUs; + if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { + mAnchorTimeUs = timeUs; + } + } + + size_t copy = + (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t); + + if (copy > mInputBuffer->range_length()) { + copy = mInputBuffer->range_length(); + } + + memcpy(&mInputFrame[mNumInputSamples], + (const uint8_t *)mInputBuffer->data() + + mInputBuffer->range_offset(), + copy); + + mInputBuffer->set_range( + mInputBuffer->range_offset() + copy, + mInputBuffer->range_length() - copy); + + if (mInputBuffer->range_length() == 0) { + mInputBuffer->release(); + mInputBuffer = NULL; + } + + mNumInputSamples += copy / sizeof(int16_t); + if (mNumInputSamples >= kNumSamplesPerFrame) { + mNumInputSamples %= kNumSamplesPerFrame; + break; // Get a whole input frame 640 bytes + } + } + + VO_CODECBUFFER inputData; + memset(&inputData, 0, sizeof(inputData)); + inputData.Buffer = (unsigned char*) mInputFrame; + inputData.Length = kInputBufferSize; + CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData)); + + MediaBuffer *buffer; + CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); + uint8_t *outPtr = (uint8_t *)buffer->data(); + + VO_CODECBUFFER outputData; + memset(&outputData, 0, sizeof(outputData)); + VO_AUDIO_OUTPUTINFO outputInfo; + memset(&outputInfo, 0, sizeof(outputInfo)); + + VO_U32 ret = VO_ERR_NONE; + outputData.Buffer = outPtr; + outputData.Length = buffer->size(); + ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo); + CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL); + + buffer->set_range(0, outputData.Length); + ++mNumFramesOutput; + + // XXX: fix timestamp calculation + int64_t timestampUs = mNumFramesOutput * 20000LL; + + buffer->meta_data()->setInt64(kKeyTime, timestampUs); + + *out = buffer; + return OK; +} + +} // namespace android diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..429328797134b457f3b00bff6994e289ef105c90 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/Android.mk @@ -0,0 +1,120 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +include frameworks/base/media/libstagefright/codecs/common/Config.mk + +LOCAL_PRELINK_MODULE := false + +LOCAL_SRC_FILES := \ + AMRWBEncoder.cpp \ + src/autocorr.c \ + src/az_isp.c \ + src/bits.c \ + src/c2t64fx.c \ + src/c4t64fx.c \ + src/convolve.c \ + src/cor_h_x.c \ + src/decim54.c \ + src/deemph.c \ + src/dtx.c \ + src/g_pitch.c \ + src/gpclip.c \ + src/homing.c \ + src/hp400.c \ + src/hp50.c \ + src/hp6k.c \ + src/hp_wsp.c \ + src/int_lpc.c \ + src/isp_az.c \ + src/isp_isf.c \ + src/lag_wind.c \ + src/levinson.c \ + src/log2.c \ + src/lp_dec2.c \ + src/math_op.c \ + src/oper_32b.c \ + src/p_med_ol.c \ + src/pit_shrp.c \ + src/pitch_f4.c \ + src/pred_lt4.c \ + src/preemph.c \ + src/q_gain2.c \ + src/q_pulse.c \ + src/qisf_ns.c \ + src/qpisf_2s.c \ + src/random.c \ + src/residu.c \ + src/scale.c \ + src/stream.c \ + src/syn_filt.c \ + src/updt_tar.c \ + src/util.c \ + src/voAMRWBEnc.c \ + src/voicefac.c \ + src/wb_vad.c \ + src/weight_a.c \ + src/mem_align.c + + +ifeq ($(VOTT), v5) +LOCAL_SRC_FILES += \ + src/asm/ARMV5E/convolve_opt.s \ + src/asm/ARMV5E/cor_h_vec_opt.s \ + src/asm/ARMV5E/Deemph_32_opt.s \ + src/asm/ARMV5E/Dot_p_opt.s \ + src/asm/ARMV5E/Filt_6k_7k_opt.s \ + src/asm/ARMV5E/Norm_Corr_opt.s \ + src/asm/ARMV5E/pred_lt4_1_opt.s \ + src/asm/ARMV5E/residu_asm_opt.s \ + src/asm/ARMV5E/scale_sig_opt.s \ + src/asm/ARMV5E/Syn_filt_32_opt.s \ + src/asm/ARMV5E/syn_filt_opt.s + +endif + +ifeq ($(VOTT), v7) +LOCAL_SRC_FILES += \ + src/asm/ARMV7/convolve_neon.s \ + src/asm/ARMV7/cor_h_vec_neon.s \ + src/asm/ARMV7/Deemph_32_neon.s \ + src/asm/ARMV7/Dot_p_neon.s \ + src/asm/ARMV7/Filt_6k_7k_neon.s \ + src/asm/ARMV7/Norm_Corr_neon.s \ + src/asm/ARMV7/pred_lt4_1_neon.s \ + src/asm/ARMV7/residu_asm_neon.s \ + src/asm/ARMV7/scale_sig_neon.s \ + src/asm/ARMV7/Syn_filt_32_neon.s \ + src/asm/ARMV7/syn_filt_neon.s + +endif + +LOCAL_MODULE := libstagefright_amrwbenc + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := + +LOCAL_SHARED_LIBRARIES := + +LOCAL_C_INCLUDES := \ + frameworks/base/media/libstagefright/include \ + frameworks/base/media/libstagefright/codecs/common/include \ + frameworks/base/include \ + $(LOCAL_PATH)/src \ + $(LOCAL_PATH)/inc + +LOCAL_CFLAGS := $(VO_CFLAGS) + +ifeq ($(VOTT), v5) +LOCAL_CFLAGS += -DARM -DASM_OPT +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E +endif + +ifeq ($(VOTT), v7) +LOCAL_CFLAGS += -DARM -DARMV7 -DASM_OPT +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7 +endif + +include $(BUILD_STATIC_LIBRARY) + + diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c new file mode 100644 index 0000000000000000000000000000000000000000..792d3cc1bb28391d9b82d36aa286b8b0e337e63c --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c @@ -0,0 +1,364 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +#ifdef LINUX +#include +#endif + +#include +#include +#include +#include "voAMRWB.h" +#include "cmnMemory.h" + +#define VOAMRWB_RFC3267_HEADER_INFO "#!AMR-WB\n" + +#define INPUT_SIZE 640 +#define OUTPUT_SIZE 1024 +unsigned char InputBuf[INPUT_SIZE]; +unsigned char OutputBuf[OUTPUT_SIZE]; + +void usage (void) { + printf ("AMR_WB Encoder HELP Displays this text\n"); + printf ("\n"); + printf ("Usage:\n"); + printf ("AMRWBEnc [options] Input_file output_file \n"); + printf ("\n"); + printf ("Options +M* +F* +DTX \n"); + printf ("Support \n"); + printf ("Options +M* for seting compression bitrate mode, default is 23.85kbps\n"); + printf (" +M0 = 6.6kbps \n"); + printf (" +M1 = 8.85kbps \n"); + printf (" +M2 = 12.65kbps \n"); + printf (" +M3 = 14.25kbps \n"); + printf (" +M4 = 15.58kbps \n"); + printf (" +M5 = 18.25kbps \n"); + printf (" +M6 = 19.85kbps \n"); + printf (" +M7 = 23.05kbps \n"); + printf (" +M8 = 23.85kbps \n"); + printf ("\n"); + printf ("Options +F* for setting output frame Type, default is RFC3267 \n"); + printf ("+F0 for AMR_WB Defualt bit extern short data frame type \n"); + printf ("+F1 for AMR_WB_ITU bit extern short data frame type \n"); + printf ("+F2 for RFC3267\n "); + printf ("\n"); + printf ("Options +DTX enable DTX mode, default is disable.\n"); + printf ("File names, input raw PCM data, and output is AMR_WB bit-stream file.\n"); + printf ("\n"); +} + +int GetNextBuf(FILE* inFile,unsigned char* dst,int size) +{ + int size2 = (int)fread(dst, sizeof(signed char), size,inFile); + return size2; +} + +typedef int (VO_API * VOGETAUDIOENCAPI) (VO_AUDIO_CODECAPI * pEncHandle); + +int encode( + int mode, + short allow_dtx, + VOAMRWBFRAMETYPE frameType, + const char* srcfile, + const char* dstfile + ) +{ + int ret = 0; + int returnCode; + FILE *fsrc = NULL; + FILE *fdst = NULL; + int framenum = 0; + int eofFile = 0; + int size1 = 0; + int Relens; + + VO_AUDIO_CODECAPI AudioAPI; + VO_MEM_OPERATOR moper; + VO_CODEC_INIT_USERDATA useData; + VO_HANDLE hCodec; + VO_CODECBUFFER inData; + VO_CODECBUFFER outData; + VO_AUDIO_OUTPUTINFO outFormat; + + unsigned char *inBuf = InputBuf; + unsigned char *outBuf = OutputBuf; + + +#ifdef LINUX + void *handle = NULL; + void *pfunc; + VOGETAUDIOENCAPI pGetAPI; +#endif + + clock_t start, finish; + double duration = 0.0; + + if ((fsrc = fopen (srcfile, "rb")) == NULL) + { + ret = -1; + goto safe_exit; + } + + if ((fdst = fopen (dstfile, "wb")) == NULL) + { + ret = -1; + goto safe_exit; + } + + moper.Alloc = cmnMemAlloc; + moper.Copy = cmnMemCopy; + moper.Free = cmnMemFree; + moper.Set = cmnMemSet; + moper.Check = cmnMemCheck; + + useData.memflag = VO_IMF_USERMEMOPERATOR; + useData.memData = (VO_PTR)(&moper); + +#ifdef LINUX + handle = dlopen("/data/local/tmp/voAMRWBEnc.so", RTLD_NOW); + if(handle == 0) + { + printf("open dll error......"); + return -1; + } + + pfunc = dlsym(handle, "voGetAMRWBEncAPI"); + if(pfunc == 0) + { + printf("open function error......"); + return -1; + } + + pGetAPI = (VOGETAUDIOENCAPI)pfunc; + + returnCode = pGetAPI(&AudioAPI); + if(returnCode) + { + printf("get APIs error......"); + return -1; + } +#else + ret = voGetAMRWBEncAPI(&AudioAPI); + if(ret) + { + ret = -1; + printf("get APIs error......"); + goto safe_exit; + } +#endif + + //####################################### Init Encoding Section ######################################### + ret = AudioAPI.Init(&hCodec, VO_AUDIO_CodingAMRWB, &useData); + + if(ret) + { + ret = -1; + printf("APIs init error......"); + goto safe_exit; + } + + Relens = GetNextBuf(fsrc,InputBuf,INPUT_SIZE); + if(Relens!=INPUT_SIZE && !feof(fsrc)) + { + ret = -1; //Invalid magic number + printf("get next buffer error......"); + goto safe_exit; + } + + //###################################### set encode Mode ################################################## + ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_FRAMETYPE, &frameType); + ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_MODE, &mode); + ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_DTX, &allow_dtx); + + if(frameType == VOAMRWB_RFC3267) + { + /* write RFC3267 Header info to indicate single channel AMR file storage format */ + size1 = (int)strlen(VOAMRWB_RFC3267_HEADER_INFO); + memcpy(outBuf, VOAMRWB_RFC3267_HEADER_INFO, size1); + outBuf += size1; + } + + //####################################### Encoding Section ######################################### + printf(" \n ---------------- Running -------------------------\n "); + + do{ + inData.Buffer = (unsigned char *)inBuf; + inData.Length = Relens; + outData.Buffer = outBuf; + + start = clock(); + + /* decode one amr block */ + returnCode = AudioAPI.SetInputData(hCodec,&inData); + + do { + returnCode = AudioAPI.GetOutputData(hCodec,&outData, &outFormat); + if(returnCode == 0) + { + framenum++; + printf(" Frames processed: %hd\r", framenum); + if(framenum == 1) + { + fwrite(OutputBuf, 1, outData.Length + size1, fdst); + fflush(fdst); + } + else + { + fwrite(outData.Buffer, 1, outData.Length, fdst); + fflush(fdst); + } + } + else if(returnCode == VO_ERR_LICENSE_ERROR) + { + printf("Encoder time reach upper limit......"); + goto safe_exit; + } + } while(returnCode != VO_ERR_INPUT_BUFFER_SMALL); + + finish = clock(); + duration += finish - start; + + if (!eofFile) { + Relens = GetNextBuf(fsrc, InputBuf, INPUT_SIZE); + inBuf = InputBuf; + if (feof(fsrc) && Relens == 0) + eofFile = 1; + } + } while (!eofFile && returnCode); + //####################################### End Encoding Section ######################################### + +safe_exit: + returnCode = AudioAPI.Uninit(hCodec); + + printf( "\n%2.5f seconds\n", (double)duration/CLOCKS_PER_SEC); + + if (fsrc) + fclose(fsrc); + if (fdst) + fclose(fdst); + +#ifdef LINUX + dlclose(handle); +#endif + + return ret; +} + +int main(int argc, char **argv) // for gcc compiler; +{ + int mode, r; + int arg, filename=0; + char *inFileName = NULL; + char *outFileName = NULL; + short allow_dtx; + VOAMRWBFRAMETYPE frameType; + + printf("\n"); + printf("************************Adaptive Multi-Rate Wide Band Encoder (AMR-WB)*******************************\n"); + printf("***********************************DEFINITIONS:*******************************************************\n"); + printf("AMR-WB encoder scheme is based on the principle of Algebraic Code Excited Linear Prediction algorithm\n"); + printf("The AMR-WB encoder compression MONO liner PCM speech input data at 16kHz sampling rate\n"); + printf("to one of nine data rate modes-6.60, 8.85, 12.65, 14.25, 15.85, 18.25, 19.25, 23.05 and 23.85kbps.\n"); + printf("The encoder supports output format AMRWB ITU, AMRWB RFC3267.\n"); + printf("\n"); + + /*Encoder Default setting */ + mode = VOAMRWB_MD2385; + allow_dtx = 0; + frameType = VOAMRWB_RFC3267; + + if(argc < 3){ + usage(); + return 0; + }else{ + for (arg = 1; arg < argc; arg++) { + if (argv [arg] [0] == '+') { + if(argv[arg][1] == 'M') + { + switch(argv[arg][2]) + { + case '0': mode = VOAMRWB_MD66; + break; + case '1': mode = VOAMRWB_MD885; + break; + case '2': mode = VOAMRWB_MD1265; + break; + case '3': mode = VOAMRWB_MD1425; + break; + case '4': mode = VOAMRWB_MD1585; + break; + case '5': mode = VOAMRWB_MD1825; + break; + case '6': mode = VOAMRWB_MD1985; + break; + case '7': mode = VOAMRWB_MD2305; + break; + case '8': mode = VOAMRWB_MD2385; + break; + default: + usage(); + printf ("Invalid parameter '%s'.\n", argv [arg]); + break; + } + }else if(argv[arg][1] == 'F') + { + switch(argv[arg][2]) + { + case '0': frameType = VOAMRWB_DEFAULT; + break; + case '1': frameType = VOAMRWB_ITU; + break; + case '2': frameType = VOAMRWB_RFC3267 ; + break; + default: + usage(); + printf ("Invalid parameter '%s'.\n", argv [arg]); + break; + + + } + }else if(strcmp (argv[arg], "+DTX") == 0) + { + allow_dtx = 1; + } + + } else { + switch (filename) { + case 0: + inFileName = argv[arg]; + break; + case 1: + outFileName = argv[arg]; + break; + default: + usage (); + fprintf (stderr, "Invalid parameter '%s'.\n", argv [arg]); + return 0; + } + filename++; + } + } + } + + r = encode(mode, allow_dtx, frameType, inFileName, outFileName); + if(r) + { + fprintf(stderr, "error: %d\n", r); + } + return r; +} + diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..7edb16628aafcc1ebb0aacac4e727c33205cce17 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk @@ -0,0 +1,27 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := AMRWB_E_SAMPLE.c + +LOCAL_SRC_FILES += \ + ../../../Common/cmnMemory.c + +LOCAL_MODULE := TestvoAMRWBEnc + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := + +LOCAL_SHARED_LIBRARIES := libvoAMRWBEnc + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/ \ + $(LOCAL_PATH)/../../../Common \ + $(LOCAL_PATH)/../../../Include \ + +LOCAL_CFLAGS := $(VO_CFLAGS) + +include $(BUILD_EXECUTABLE) + + + diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile b/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..55b876aee6bd75d9da034db5eb5a2a7683e37cab --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile @@ -0,0 +1,56 @@ +#/* +# ** Copyright 2003-2010, VisualOn, Inc. +# ** +# ** 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. +# */ + +# target6 +# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon) +VOTT:= v6 + + +# module type +# please specify the type of your module: lib or exe +VOMT:= exe + + +# module macros +# please append the additional macro definitions here for your module if necessary. +# e.g. -DVISUALON, macro VISUALON defined for your module +VOMM:= #ARMV5E + + + +# please specify the name of your module +VOTARGET:= voAMRWBEnc_Test + + +# please modify here to be sure to see the g1.mk +include ../../../../Tools/eclair.mk + +# dependent libraries. +VODEPLIBS:=-ldl + + +# module source +# please modify here to be sure to see the ms.mk which specifies all source info of your module +include ../ms.mk + + +# please specify where is the voRelease on your PC, relative path is suggested +VORELDIR:=../ + + +# please modify here to be sure to see the doit.mk +include ../../../../Tools/doit.mk + diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk b/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk new file mode 100644 index 0000000000000000000000000000000000000000..74e8913036e4c19605112f9fd52e7a3b826bf1f9 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk @@ -0,0 +1,24 @@ +#/* +# ** Copyright 2003-2010, VisualOn, Inc. +# ** +# ** 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. +# */ +# please list all objects needed by your target here +OBJS:=AMRWB_E_SAMPLE.o cmnMemory.o + +# please list all directories that all source files relative with your module(.h .c .cpp) locate +VOSRCDIR:=../ \ + ../../../../Common \ + ../../../../Include + + diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..58fda29bb3a0bce1c2129202b128737c94c87c0b --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile @@ -0,0 +1,53 @@ +#/* +# ** Copyright 2003-2010, VisualOn, Inc. +# ** +# ** 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. +# */ + +# target type +# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon) +VOTT:= v5 + + +# module type +# please specify the type of your module: lib or exe +VOMT:= lib + + +# module macros +# please append the additional macro definitions here for your module if necessary. +ifeq ($(VOTT), v5) +VOMM:=-DARM -DASM_OPT +endif + +# please specify the name of your module +VOTARGET:= libvoAMRWBEncv5 + + +# please modify here to be sure to see the g1.mk +include ../../../../../Tools/eclair.mk + +# dependent libraries. +VODEPLIBS:=-ldl -lstdc++ -lcutils + +# module source +# please modify here to be sure to see the ms.mk which specifies all source info of your module +include ../ms.mk + + +# please specify where is the voRelease on your PC, relative path is suggested +VORELDIR:=../../../../../../Release + +# please modify here to be sure to see the doit.mk +include ../../../../../Tools/doit.mk + diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5686411f54e90ee21adb306039661b9e5b9e8447 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile @@ -0,0 +1,53 @@ +#/* +# ** Copyright 2003-2010, VisualOn, Inc. +# ** +# ** 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. +# */ + +# target type +# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon) +VOTT:= v7 + + +# module type +# please specify the type of your module: lib or exe +VOMT:= lib + + +# module macros +# please append the additional macro definitions here for your module if necessary. +ifeq ($(VOTT), v7) +VOMM:=-DARM -DARMV7 -DASM_OPT +endif + +# please specify the name of your module +VOTARGET:= libvoAMRWBEncv7 + + +# please modify here to be sure to see the g1.mk +include ../../../../../Tools/eclair.mk + +# dependent libraries. +VODEPLIBS:=-ldl -lstdc++ -lcutils + +# module source +# please modify here to be sure to see the ms.mk which specifies all source info of your module +include ../ms.mk + + +# please specify where is the voRelease on your PC, relative path is suggested +VORELDIR:=../../../../../../Release + +# please modify here to be sure to see the doit.mk +include ../../../../../Tools/doit.mk + diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/makefile new file mode 100644 index 0000000000000000000000000000000000000000..3473a1af0a769211d75e9fcc88cd1188d0ec57f6 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/build/eclair/makefile @@ -0,0 +1,39 @@ +#/* +# ** Copyright 2003-2010, VisualOn, Inc. +# ** +# ** 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. +# */ +# Just acting as Father Makefile of Modules +# please keep the name 'makefile' unchanged + +# Module Subdirs +VOMSD:=$(dir $(shell find . -name 'Makefile')) + +all: + for dir in $(VOMSD); \ + do \ + $(MAKE) -C $$dir; \ + done + +.PHONY:clean devel +clean: + for dir in $(VOMSD); \ + do \ + $(MAKE) -C $$dir clean; \ + done + +devel: + for dir in $(VOMSD); \ + do \ + $(MAKE) -C $$dir devel; \ + done diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk b/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk new file mode 100644 index 0000000000000000000000000000000000000000..bd6620cfb290d3c89668f00d7e9e912ea574bd52 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk @@ -0,0 +1,43 @@ +#/* +# ** Copyright 2003-2010, VisualOn, Inc. +# ** +# ** 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. +# */ +# please list all directories that all source files relative with your module(.h .c .cpp) locate +VOSRCDIR:=../../../inc \ + ../../../src \ + ../../../../../Include + +# please list all objects needed by your target here +OBJS:= autocorr.o az_isp.o bits.o c2t64fx.o c4t64fx.o convolve.o cor_h_x.o decim54.o \ + deemph.o dtx.o g_pitch.o gpclip.o homing.o hp400.o hp50.o hp6k.o hp_wsp.o \ + int_lpc.o isp_az.o isp_isf.o lag_wind.o levinson.o log2.o lp_dec2.o math_op.o mem_align.o \ + oper_32b.o p_med_ol.o pit_shrp.o pitch_f4.o pred_lt4.o preemph.o q_gain2.o q_pulse.o \ + qisf_ns.o qpisf_2s.o random.o residu.o scale.o stream.o syn_filt.o updt_tar.o util.o \ + voAMRWBEnc.o voicefac.o wb_vad.o weight_a.o + + +ifeq ($(VOTT), v5) +OBJS += cor_h_vec_opt.o Deemph_32_opt.o Dot_p_opt.o Filt_6k_7k_opt.o residu_asm_opt.o \ + scale_sig_opt.o Syn_filt_32_opt.o syn_filt_opt.o pred_lt4_1_opt.o convolve_opt.o \ + Norm_Corr_opt.o +VOSRCDIR+= ../../../src/asm/ARMV5E +endif + +ifeq ($(VOTT), v7) +OBJS+= cor_h_vec_neon.o Deemph_32_neon.o Dot_p_neon.o Filt_6k_7k_neon.o residu_asm_neon.o \ + scale_sig_neon.o Syn_filt_32_neon.o syn_filt_neon.o pred_lt4_1_neon.o convolve_neon.o \ + Norm_Corr_neon.o +VOSRCDIR+= ../../../src/asm/ARMV7 +endif + diff --git a/media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf b/media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5bade44f92bb77a49e526bc047c8bcd56f61f5ee Binary files /dev/null and b/media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf differ diff --git a/media/libstagefright/codecs/amrwbenc/inc/acelp.h b/media/libstagefright/codecs/amrwbenc/inc/acelp.h new file mode 100644 index 0000000000000000000000000000000000000000..4cb38a1660c972ae48227040c64da11843dbd0af --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/acelp.h @@ -0,0 +1,521 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*--------------------------------------------------------------------------* + * ACELP.H * + *--------------------------------------------------------------------------* + * Function * + *--------------------------------------------------------------------------*/ +#ifndef __ACELP_H__ +#define __ACELP_H__ + +#include "typedef.h" +#include "cod_main.h" + +/*-----------------------------------------------------------------* + * LPC prototypes * + *-----------------------------------------------------------------*/ + +Word16 median5(Word16 x[]); + +void Autocorr( + Word16 x[], /* (i) : Input signal */ + Word16 m, /* (i) : LPC order */ + Word16 r_h[], /* (o) : Autocorrelations (msb) */ + Word16 r_l[] /* (o) : Autocorrelations (lsb) */ + ); + +void Lag_window( + Word16 r_h[], /* (i/o) : Autocorrelations (msb) */ + Word16 r_l[] /* (i/o) : Autocorrelations (lsb) */ + ); + +void Init_Levinson( + Word16 * mem /* output :static memory (18 words) */ + ); + +void Levinson( + Word16 Rh[], /* (i) : Rh[M+1] Vector of autocorrelations (msb) */ + Word16 Rl[], /* (i) : Rl[M+1] Vector of autocorrelations (lsb) */ + Word16 A[], /* (o) Q12 : A[M] LPC coefficients (m = 16) */ + Word16 rc[], /* (o) Q15 : rc[M] Reflection coefficients. */ + Word16 * mem /* (i/o) :static memory (18 words) */ + ); + +void Az_isp( + Word16 a[], /* (i) Q12 : predictor coefficients */ + Word16 isp[], /* (o) Q15 : Immittance spectral pairs */ + Word16 old_isp[] /* (i) : old isp[] (in case not found M roots) */ + ); + +void Isp_Az( + Word16 isp[], /* (i) Q15 : Immittance spectral pairs */ + Word16 a[], /* (o) Q12 : predictor coefficients (order = M) */ + Word16 m, + Word16 adaptive_scaling /* (i) 0 : adaptive scaling disabled */ + /* 1 : adaptive scaling enabled */ + ); + +void Isp_isf( + Word16 isp[], /* (i) Q15 : isp[m] (range: -1<=val<1) */ + Word16 isf[], /* (o) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */ + Word16 m /* (i) : LPC order */ + ); + +void Isf_isp( + Word16 isf[], /* (i) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */ + Word16 isp[], /* (o) Q15 : isp[m] (range: -1<=val<1) */ + Word16 m /* (i) : LPC order */ + ); + +void Int_isp( + Word16 isp_old[], /* input : isps from past frame */ + Word16 isp_new[], /* input : isps from present frame */ + Word16 frac[], /* input : fraction for 3 first subfr (Q15) */ + Word16 Az[] /* output: LP coefficients in 4 subframes */ + ); + +void Weight_a( + Word16 a[], /* (i) Q12 : a[m+1] LPC coefficients */ + Word16 ap[], /* (o) Q12 : Spectral expanded LPC coefficients */ + Word16 gamma, /* (i) Q15 : Spectral expansion factor. */ + Word16 m /* (i) : LPC order. */ + ); + + +/*-----------------------------------------------------------------* + * isf quantizers * + *-----------------------------------------------------------------*/ + +void Qpisf_2s_46b( + Word16 * isf1, /* (i) Q15 : ISF in the frequency domain (0..0.5) */ + Word16 * isf_q, /* (o) Q15 : quantized ISF (0..0.5) */ + Word16 * past_isfq, /* (io)Q15 : past ISF quantizer */ + Word16 * indice, /* (o) : quantization indices */ + Word16 nb_surv /* (i) : number of survivor (1, 2, 3 or 4) */ + ); + +void Qpisf_2s_36b( + Word16 * isf1, /* (i) Q15 : ISF in the frequency domain (0..0.5) */ + Word16 * isf_q, /* (o) Q15 : quantized ISF (0..0.5) */ + Word16 * past_isfq, /* (io)Q15 : past ISF quantizer */ + Word16 * indice, /* (o) : quantization indices */ + Word16 nb_surv /* (i) : number of survivor (1, 2, 3 or 4) */ + ); + +void Dpisf_2s_46b( + Word16 * indice, /* input: quantization indices */ + Word16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */ + Word16 * past_isfq, /* i/0 : past ISF quantizer */ + Word16 * isfold, /* input : past quantized ISF */ + Word16 * isf_buf, /* input : isf buffer */ + Word16 bfi, /* input : Bad frame indicator */ + Word16 enc_dec + ); + +void Dpisf_2s_36b( + Word16 * indice, /* input: quantization indices */ + Word16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */ + Word16 * past_isfq, /* i/0 : past ISF quantizer */ + Word16 * isfold, /* input : past quantized ISF */ + Word16 * isf_buf, /* input : isf buffer */ + Word16 bfi, /* input : Bad frame indicator */ + Word16 enc_dec + ); + +void Qisf_ns( + Word16 * isf1, /* input : ISF in the frequency domain (0..0.5) */ + Word16 * isf_q, /* output: quantized ISF */ + Word16 * indice /* output: quantization indices */ + ); + +void Disf_ns( + Word16 * indice, /* input: quantization indices */ + Word16 * isf_q /* input : ISF in the frequency domain (0..0.5) */ + ); + +Word16 Sub_VQ( /* output: return quantization index */ + Word16 * x, /* input : ISF residual vector */ + Word16 * dico, /* input : quantization codebook */ + Word16 dim, /* input : dimention of vector */ + Word16 dico_size, /* input : size of quantization codebook */ + Word32 * distance /* output: error of quantization */ + ); + +void Reorder_isf( + Word16 * isf, /* (i/o) Q15: ISF in the frequency domain (0..0.5) */ + Word16 min_dist, /* (i) Q15 : minimum distance to keep */ + Word16 n /* (i) : number of ISF */ + ); + +/*-----------------------------------------------------------------* + * filter prototypes * + *-----------------------------------------------------------------*/ + +void Init_Decim_12k8( + Word16 mem[] /* output: memory (2*NB_COEF_DOWN) set to zeros */ + ); +void Decim_12k8( + Word16 sig16k[], /* input: signal to downsampling */ + Word16 lg, /* input: length of input */ + Word16 sig12k8[], /* output: decimated signal */ + Word16 mem[] /* in/out: memory (2*NB_COEF_DOWN) */ + ); + +void Init_HP50_12k8(Word16 mem[]); +void HP50_12k8( + Word16 signal[], /* input/output signal */ + Word16 lg, /* lenght of signal */ + Word16 mem[] /* filter memory [6] */ + ); +void Init_HP400_12k8(Word16 mem[]); +void HP400_12k8( + Word16 signal[], /* input/output signal */ + Word16 lg, /* lenght of signal */ + Word16 mem[] /* filter memory [6] */ + ); + +void Init_Filt_6k_7k(Word16 mem[]); +void Filt_6k_7k( + Word16 signal[], /* input: signal */ + Word16 lg, /* input: length of input */ + Word16 mem[] /* in/out: memory (size=30) */ + ); +void Filt_6k_7k_asm( + Word16 signal[], /* input: signal */ + Word16 lg, /* input: length of input */ + Word16 mem[] /* in/out: memory (size=30) */ + ); + +void LP_Decim2( + Word16 x[], /* in/out: signal to process */ + Word16 l, /* input : size of filtering */ + Word16 mem[] /* in/out: memory (size=3) */ + ); + +void Preemph( + Word16 x[], /* (i/o) : input signal overwritten by the output */ + Word16 mu, /* (i) Q15 : preemphasis coefficient */ + Word16 lg, /* (i) : lenght of filtering */ + Word16 * mem /* (i/o) : memory (x[-1]) */ + ); +void Preemph2( + Word16 x[], /* (i/o) : input signal overwritten by the output */ + Word16 mu, /* (i) Q15 : preemphasis coefficient */ + Word16 lg, /* (i) : lenght of filtering */ + Word16 * mem /* (i/o) : memory (x[-1]) */ + ); +void Deemph( + Word16 x[], /* (i/o) : input signal overwritten by the output */ + Word16 mu, /* (i) Q15 : deemphasis factor */ + Word16 L, /* (i) : vector size */ + Word16 * mem /* (i/o) : memory (y[-1]) */ + ); +void Deemph2( + Word16 x[], /* (i/o) : input signal overwritten by the output */ + Word16 mu, /* (i) Q15 : deemphasis factor */ + Word16 L, /* (i) : vector size */ + Word16 * mem /* (i/o) : memory (y[-1]) */ + ); +void Deemph_32( + Word16 x_hi[], /* (i) : input signal (bit31..16) */ + Word16 x_lo[], /* (i) : input signal (bit15..4) */ + Word16 y[], /* (o) : output signal (x16) */ + Word16 mu, /* (i) Q15 : deemphasis factor */ + Word16 L, /* (i) : vector size */ + Word16 * mem /* (i/o) : memory (y[-1]) */ + ); + +void Deemph_32_asm( + Word16 x_hi[], /* (i) : input signal (bit31..16) */ + Word16 x_lo[], /* (i) : input signal (bit15..4) */ + Word16 y[], /* (o) : output signal (x16) */ + Word16 * mem /* (i/o) : memory (y[-1]) */ + ); + +void Convolve( + Word16 x[], /* (i) : input vector */ + Word16 h[], /* (i) Q15 : impulse response */ + Word16 y[], /* (o) 12 bits: output vector */ + Word16 L /* (i) : vector size */ + ); + +void Convolve_asm( + Word16 x[], /* (i) : input vector */ + Word16 h[], /* (i) Q15 : impulse response */ + Word16 y[], /* (o) 12 bits: output vector */ + Word16 L /* (i) : vector size */ + ); + +void Residu( + Word16 a[], /* (i) Q12 : prediction coefficients */ + Word16 x[], /* (i) : speech (values x[-m..-1] are needed */ + Word16 y[], /* (o) : residual signal */ + Word16 lg /* (i) : size of filtering */ + ); + +void Residu_opt( + Word16 a[], /* (i) Q12 : prediction coefficients */ + Word16 x[], /* (i) : speech (values x[-m..-1] are needed */ + Word16 y[], /* (o) : residual signal */ + Word16 lg /* (i) : size of filtering */ + ); + +void Syn_filt( + Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */ + Word16 x[], /* (i) : input signal */ + Word16 y[], /* (o) : output signal */ + Word16 lg, /* (i) : size of filtering */ + Word16 mem[], /* (i/o) : memory associated with this filtering. */ + Word16 update /* (i) : 0=no update, 1=update of memory. */ + ); + +void Syn_filt_asm( + Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */ + Word16 x[], /* (i) : input signal */ + Word16 y[], /* (o) : output signal */ + Word16 mem[] /* (i/o) : memory associated with this filtering. */ + ); + +void Syn_filt_32( + Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */ + Word16 m, /* (i) : order of LP filter */ + Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */ + Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */ + Word16 sig_hi[], /* (o) /16 : synthesis high */ + Word16 sig_lo[], /* (o) /16 : synthesis low */ + Word16 lg /* (i) : size of filtering */ + ); + +void Syn_filt_32_asm( + Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */ + Word16 m, /* (i) : order of LP filter */ + Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */ + Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */ + Word16 sig_hi[], /* (o) /16 : synthesis high */ + Word16 sig_lo[], /* (o) /16 : synthesis low */ + Word16 lg /* (i) : size of filtering */ + ); +/*-----------------------------------------------------------------* + * pitch prototypes * + *-----------------------------------------------------------------*/ + +Word16 Pitch_ol( /* output: open loop pitch lag */ + Word16 signal[], /* input : signal used to compute the open loop pitch */ +/* signal[-pit_max] to signal[-1] should be known */ + Word16 pit_min, /* input : minimum pitch lag */ + Word16 pit_max, /* input : maximum pitch lag */ + Word16 L_frame /* input : length of frame to compute pitch */ +); + +Word16 Pitch_med_ol( /* output: open loop pitch lag */ + Word16 wsp[], /* input : signal used to compute the open loop pitch */ + /* wsp[-pit_max] to wsp[-1] should be known */ + Coder_State *st, /* i/o : global codec structure */ + Word16 L_frame /* input : length of frame to compute pitch */ +); + +Word16 Med_olag( /* output : median of 5 previous open-loop lags */ + Word16 prev_ol_lag, /* input : previous open-loop lag */ + Word16 old_ol_lag[5] +); + +void Init_Hp_wsp(Word16 mem[]); +void scale_mem_Hp_wsp(Word16 mem[], Word16 exp); +void Hp_wsp( + Word16 wsp[], /* i : wsp[] signal */ + Word16 hp_wsp[], /* o : hypass wsp[] */ + Word16 lg, /* i : lenght of signal */ + Word16 mem[] /* i/o : filter memory [9] */ +); + +Word16 Pitch_fr4( /* (o) : pitch period. */ + Word16 exc[], /* (i) : excitation buffer */ + Word16 xn[], /* (i) : target vector */ + Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */ + Word16 t0_min, /* (i) : minimum value in the searched range. */ + Word16 t0_max, /* (i) : maximum value in the searched range. */ + Word16 * pit_frac, /* (o) : chosen fraction (0, 1, 2 or 3). */ + Word16 i_subfr, /* (i) : indicator for first subframe. */ + Word16 t0_fr2, /* (i) : minimum value for resolution 1/2 */ + Word16 t0_fr1, /* (i) : minimum value for resolution 1 */ + Word16 L_subfr /* (i) : Length of subframe */ +); +void Pred_lt4( + Word16 exc[], /* in/out: excitation buffer */ + Word16 T0, /* input : integer pitch lag */ + Word16 frac, /* input : fraction of lag */ + Word16 L_subfr /* input : subframe size */ +); + +void pred_lt4_asm( + Word16 exc[], /* in/out: excitation buffer */ + Word16 T0, /* input : integer pitch lag */ + Word16 frac, /* input : fraction of lag */ + Word16 L_subfr /* input : subframe size */ +); + +/*-----------------------------------------------------------------* + * gain prototypes * + *-----------------------------------------------------------------*/ + +Word16 G_pitch( /* (o) Q14 : Gain of pitch lag saturated to 1.2 */ + Word16 xn[], /* (i) : Pitch target. */ + Word16 y1[], /* (i) : filtered adaptive codebook. */ + Word16 g_coeff[], /* : Correlations need for gain quantization. */ + Word16 L_subfr /* : Length of subframe. */ +); +void Init_Q_gain2( + Word16 * mem /* output :static memory (2 words) */ +); +Word16 Q_gain2( /* Return index of quantization. */ + Word16 xn[], /* (i) Q_xn:Target vector. */ + Word16 y1[], /* (i) Q_xn:Adaptive codebook. */ + Word16 Q_xn, /* (i) :xn and y1 format */ + Word16 y2[], /* (i) Q9 :Filtered innovative vector. */ + Word16 code[], /* (i) Q9 :Innovative vector. */ + Word16 g_coeff[], /* (i) :Correlations */ +/* Compute in G_pitch(). */ + Word16 L_subfr, /* (i) :Subframe lenght. */ + Word16 nbits, /* (i) : number of bits (6 or 7) */ + Word16 * gain_pit, /* (i/o)Q14:Pitch gain. */ + Word32 * gain_cod, /* (o) Q16 :Code gain. */ + Word16 gp_clip, /* (i) : Gp Clipping flag */ + Word16 * mem /* (i/o) :static memory (2 words) */ +); + +void Init_D_gain2( + Word16 * mem /* output :static memory (4 words) */ +); +void D_gain2( + Word16 index, /* (i) :index of quantization. */ + Word16 nbits, /* (i) : number of bits (6 or 7) */ + Word16 code[], /* (i) Q9 :Innovative vector. */ + Word16 L_subfr, /* (i) :Subframe lenght. */ + Word16 * gain_pit, /* (o) Q14 :Pitch gain. */ + Word32 * gain_cod, /* (o) Q16 :Code gain. */ + Word16 bfi, /* (i) :bad frame indicator */ + Word16 prev_bfi, /* (i) : Previous BF indicator */ + Word16 state, /* (i) : State of BFH */ + Word16 unusable_frame, /* (i) : UF indicator */ + Word16 vad_hist, /* (i) :number of non-speech frames */ + Word16 * mem /* (i/o) :static memory (4 words) */ +); + +/*-----------------------------------------------------------------* + * acelp prototypes * + *-----------------------------------------------------------------*/ + +void cor_h_x( + Word16 h[], /* (i) Q12 : impulse response of weighted synthesis filter */ + Word16 x[], /* (i) Q0 : target vector */ + Word16 dn[] /* (o) <12bit : correlation between target and h[] */ +); +void ACELP_2t64_fx( + Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */ + Word16 cn[], /* (i) <12b : residual after long term prediction */ + Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */ + Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */ + Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */ + Word16 * index /* (o) : index (12): 5+1+5+1 = 11 bits. */ +); + +void ACELP_4t64_fx( + Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */ + Word16 cn[], /* (i) <12b : residual after long term prediction */ + Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */ + Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */ + Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */ + Word16 nbbits, /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits */ + Word16 ser_size, /* (i) : bit rate */ + Word16 _index[] /* (o) : index (20): 5+5+5+5 = 20 bits. */ + /* (o) : index (36): 9+9+9+9 = 36 bits. */ + /* (o) : index (44): 13+9+13+9 = 44 bits. */ + /* (o) : index (52): 13+13+13+13 = 52 bits. */ + /* (o) : index (64): 2+2+2+2+14+14+14+14 = 64 bits. */ + /* (o) : index (72): 10+2+10+2+10+14+10+14 = 72 bits. */ + /* (o) : index (88): 11+11+11+11+11+11+11+11 = 88 bits. */ +); + +void Pit_shrp( + Word16 * x, /* in/out: impulse response (or algebraic code) */ + Word16 pit_lag, /* input : pitch lag */ + Word16 sharp, /* input : pitch sharpening factor (Q15) */ + Word16 L_subfr /* input : subframe size */ +); + + +/*-----------------------------------------------------------------* + * others prototypes * + *-----------------------------------------------------------------*/ + +void Copy( + Word16 x[], /* (i) : input vector */ + Word16 y[], /* (o) : output vector */ + Word16 L /* (i) : vector length */ +); +void Set_zero( + Word16 x[], /* (o) : vector to clear */ + Word16 L /* (i) : length of vector */ +); +void Updt_tar( + Word16 * x, /* (i) Q0 : old target (for pitch search) */ + Word16 * x2, /* (o) Q0 : new target (for codebook search) */ + Word16 * y, /* (i) Q0 : filtered adaptive codebook vector */ + Word16 gain, /* (i) Q14 : adaptive codebook gain */ + Word16 L /* (i) : subframe size */ +); +Word16 voice_factor( /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */ + Word16 exc[], /* (i) Q_exc: pitch excitation */ + Word16 Q_exc, /* (i) : exc format */ + Word16 gain_pit, /* (i) Q14 : gain of pitch */ + Word16 code[], /* (i) Q9 : Fixed codebook excitation */ + Word16 gain_code, /* (i) Q0 : gain of code */ + Word16 L_subfr /* (i) : subframe length */ +); +void Scale_sig( + Word16 x[], /* (i/o) : signal to scale */ + Word16 lg, /* (i) : size of x[] */ + Word16 exp /* (i) : exponent: x = round(x << exp) */ +); + +void Scale_sig_opt( + Word16 x[], /* (i/o) : signal to scale */ + Word16 lg, /* (i) : size of x[] */ + Word16 exp /* (i) : exponent: x = round(x << exp) */ +); + +Word16 Random(Word16 * seed); + +void Init_gp_clip( + Word16 mem[] /* (o) : memory of gain of pitch clipping algorithm */ +); +Word16 Gp_clip( + Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */ +); +void Gp_clip_test_isf( + Word16 isf[], /* (i) : isf values (in frequency domain) */ + Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */ +); +void Gp_clip_test_gain_pit( + Word16 gain_pit, /* (i) : gain of quantized pitch */ + Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */ +); + + +#endif //__ACELP_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h new file mode 100644 index 0000000000000000000000000000000000000000..6a2f86059d07e1ce42ccce34f2a25abe9dd5af69 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h @@ -0,0 +1,1094 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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 __BASIC_OP_H__ +#define __BASIC_OP_H__ + +#include +#include +#include "typedef.h" + +#define MAX_32 (Word32)0x7fffffffL +#define MIN_32 (Word32)0x80000000L + +#define MAX_16 (Word16)+32767 /* 0x7fff */ +#define MIN_16 (Word16)-32768 /* 0x8000 */ + + +#ifdef LINUX +#define static_vo static __inline__ +#else +#define static_vo static __inline +#endif + +#define saturate(L_var1) (((L_var1) > 0X00007fffL) ? (MAX_16): (((L_var1) < (Word32) 0xffff8000L) ? (MIN_16): ((L_var1) & 0xffff))) + +#define abs_s(x) ((Word16)(((x) != MIN_16) ? (((x) >= 0) ? (x) : (-(x))) : MAX_16)) /* Short abs, 1 */ +#define L_deposit_h(x) (((Word32)(x)) << 16) /* 16 bit var1 -> MSB, 2 */ +#define L_deposit_l(x) ((Word32)(x)) /* 16 bit var1 -> LSB, 2 */ +#define L_abs(x) (((x) != MIN_32) ? (((x) >= 0) ? (x) : (-(x))) : MAX_32) /* Long abs, 3*/ +#define negate(var1) ((Word16)(((var1) == MIN_16) ? MAX_16 : (-(var1)))) /* Short negate, 1*/ +#define L_negate(L_var1) (((L_var1) == (MIN_32)) ? (MAX_32) : (-(L_var1))) /* Long negate, 2*/ + + +#define extract_h(a) ((Word16)(a >> 16)) +#define extract_l(x) (Word16)((x)) +#define add1(a,b) (a + b) +#define vo_L_msu(a,b,c) ( a - (( b * c ) << 1) ) +#define vo_mult32(a, b) ((a) * (b)) +#define vo_mult(a,b) (( a * b ) >> 15 ) +#define vo_L_mult(a,b) (((a) * (b)) << 1) +#define vo_shr_r(var1, var2) ((var1+((Word16)(1L<<(var2-1))))>>var2) +#define vo_sub(a,b) (a - b) +#define vo_L_deposit_h(a) ((Word32)((a) << 16)) +#define vo_round(a) ((a + 0x00008000) >> 16) +#define vo_extract_l(a) ((Word16)(a)) +#define vo_L_add(a,b) (a + b) +#define vo_L_sub(a,b) (a - b) +#define vo_mult_r(a,b) ((( a * b ) + 0x4000 ) >> 15 ) +#define vo_negate(a) (-a) +#define vo_L_shr_r(L_var1, var2) ((L_var1+((Word32)(1L<<(var2-1))))>>var2) + + +/*___________________________________________________________________________ +| | +| Prototypes for basic arithmetic operators | +|___________________________________________________________________________| +*/ +static_vo Word16 add (Word16 var1, Word16 var2); /* Short add,1 */ +static_vo Word16 sub (Word16 var1, Word16 var2); /* Short sub,1 */ +static_vo Word16 shl (Word16 var1, Word16 var2); /* Short shift left, 1 */ +static_vo Word16 shr (Word16 var1, Word16 var2); /* Short shift right, 1 */ +static_vo Word16 mult (Word16 var1, Word16 var2); /* Short mult, 1 */ +static_vo Word32 L_mult (Word16 var1, Word16 var2); /* Long mult, 1 */ +static_vo Word16 voround (Word32 L_var1); /* Round, 1 */ +static_vo Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2); /* Mac, 1 */ +static_vo Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2); /* Msu, 1 */ +static_vo Word32 L_add (Word32 L_var1, Word32 L_var2); /* Long add, 2 */ +static_vo Word32 L_sub (Word32 L_var1, Word32 L_var2); /* Long sub, 2 */ +static_vo Word16 mult_r (Word16 var1, Word16 var2); /* Mult with round, 2 */ +static_vo Word32 L_shl2(Word32 L_var1, Word16 var2); /* var2 > 0*/ +static_vo Word32 L_shl (Word32 L_var1, Word16 var2); /* Long shift left, 2 */ +static_vo Word32 L_shr (Word32 L_var1, Word16 var2); /* Long shift right, 2*/ +static_vo Word32 L_shr_r (Word32 L_var1, Word16 var2); /* Long shift right with round, 3 */ +static_vo Word16 norm_s (Word16 var1); /* Short norm, 15 */ +static_vo Word16 div_s (Word16 var1, Word16 var2); /* Short division, 18 */ +static_vo Word16 norm_l (Word32 L_var1); /* Long norm, 30 */ + +/*___________________________________________________________________________ +| | +| Functions | +|___________________________________________________________________________| +*/ +/*___________________________________________________________________________ +| | +| Function Name : add | +| | +| Purpose : | +| | +| Performs the addition (var1+var2) with overflow control and saturation;| +| the 16 bit result is set at +32767 when overflow occurs or at -32768 | +| when underflow occurs. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var_out <= 0x0000 7fff. | +|___________________________________________________________________________| +*/ +static_vo Word16 add (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_sum; + L_sum = (Word32) var1 + var2; + var_out = saturate (L_sum); + return (var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : sub | +| | +| Purpose : | +| | +| Performs the subtraction (var1+var2) with overflow control and satu- | +| ration; the 16 bit result is set at +32767 when overflow occurs or at | +| -32768 when underflow occurs. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var_out <= 0x0000 7fff. | +|___________________________________________________________________________| +*/ + +static_vo Word16 sub (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_diff; + L_diff = (Word32) var1 - var2; + var_out = saturate (L_diff); + return (var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : shl | +| | +| Purpose : | +| | +| Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill| +| the var2 LSB of the result. If var2 is negative, arithmetically shift | +| var1 right by -var2 with sign extension. Saturate the result in case of | +| underflows or overflows. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var_out <= 0x0000 7fff. | +|___________________________________________________________________________| +*/ + +static_vo Word16 shl (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 result; + if (var2 < 0) + { + if (var2 < -16) + var2 = -16; + var_out = var1 >> ((Word16)-var2); + } + else + { + result = (Word32) var1 *((Word32) 1 << var2); + if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result))) + { + var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16); + } + else + { + var_out = extract_l (result); + } + } + return (var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : shr | +| | +| Purpose : | +| | +| Arithmetically shift the 16 bit input var1 right var2 positions with | +| sign extension. If var2 is negative, arithmetically shift var1 left by | +| -var2 with sign extension. Saturate the result in case of underflows or | +| overflows. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var_out <= 0x0000 7fff. | +|___________________________________________________________________________| +*/ + +static_vo Word16 shr (Word16 var1, Word16 var2) +{ + Word16 var_out; + if (var2 < 0) + { + if (var2 < -16) + var2 = -16; + var_out = shl(var1, (Word16)-var2); + } + else + { + if (var2 >= 15) + { + var_out = (Word16)((var1 < 0) ? -1 : 0); + } + else + { + if (var1 < 0) + { + var_out = (Word16)(~((~var1) >> var2)); + } + else + { + var_out = (Word16)(var1 >> var2); + } + } + } + return (var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : mult | +| | +| Purpose : | +| | +| Performs the multiplication of var1 by var2 and gives a 16 bit result | +| which is scaled i.e.: | +| mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and | +| mult(-32768,-32768) = 32767. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var_out <= 0x0000 7fff. | +|___________________________________________________________________________| +*/ + +static_vo Word16 mult (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_product; + L_product = (Word32) var1 *(Word32) var2; + L_product = (L_product & (Word32) 0xffff8000L) >> 15; + if (L_product & (Word32) 0x00010000L) + L_product = L_product | (Word32) 0xffff0000L; + var_out = saturate (L_product); + return (var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : L_mult | +| | +| Purpose : | +| | +| L_mult is the 32 bit result of the multiplication of var1 times var2 | +| with one shift left i.e.: | +| L_mult(var1,var2) = L_shl((var1 times var2),1) and | +| L_mult(-32768,-32768) = 2147483647. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | +|___________________________________________________________________________| +*/ + +static_vo Word32 L_mult (Word16 var1, Word16 var2) +{ + Word32 L_var_out; + L_var_out = (Word32) var1 *(Word32) var2; + if (L_var_out != (Word32) 0x40000000L) + { + L_var_out *= 2; + } + else + { + L_var_out = MAX_32; + } + return (L_var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : round | +| | +| Purpose : | +| | +| Round the lower 16 bits of the 32 bit input number into the MS 16 bits | +| with saturation. Shift the resulting bits right by 16 and return the 16 | +| bit number: | +| round(L_var1) = extract_h(L_add(L_var1,32768)) | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L_var1 | +| 32 bit long signed integer (Word32 ) whose value falls in the | +| range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var_out <= 0x0000 7fff. | +|___________________________________________________________________________| +*/ + +static_vo Word16 voround (Word32 L_var1) +{ + Word16 var_out; + Word32 L_rounded; + L_rounded = L_add (L_var1, (Word32) 0x00008000L); + var_out = extract_h (L_rounded); + return (var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : L_mac | +| | +| Purpose : | +| | +| Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | +| result to L_var3 with saturation, return a 32 bit result: | +| L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)). | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L_var3 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | +|___________________________________________________________________________| +*/ + +static_vo Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word32 L_var_out; + Word32 L_product; + L_product = ((var1 * var2) << 1); + L_var_out = L_add (L_var3, L_product); + return (L_var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : L_msu | +| | +| Purpose : | +| | +| Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | +| bit result to L_var3 with saturation, return a 32 bit result: | +| L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)). | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L_var3 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | +|___________________________________________________________________________| +*/ + +static_vo Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word32 L_var_out; + Word32 L_product; + L_product = (var1 * var2)<<1; + L_var_out = L_sub (L_var3, L_product); + return (L_var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : L_add | +| | +| Purpose : | +| | +| 32 bits addition of the two 32 bits variables (L_var1+L_var2) with | +| overflow control and saturation; the result is set at +2147483647 when | +| overflow occurs or at -2147483648 when underflow occurs. | +| | +| Complexity weight : 2 | +| | +| Inputs : | +| | +| L_var1 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | +| | +| L_var2 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | +|___________________________________________________________________________| +*/ + +static_vo Word32 L_add (Word32 L_var1, Word32 L_var2) +{ + Word32 L_var_out; + L_var_out = L_var1 + L_var2; + if (((L_var1 ^ L_var2) & MIN_32) == 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32; + } + } + return (L_var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : L_sub | +| | +| Purpose : | +| | +| 32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with | +| overflow control and saturation; the result is set at +2147483647 when | +| overflow occurs or at -2147483648 when underflow occurs. | +| | +| Complexity weight : 2 | +| | +| Inputs : | +| | +| L_var1 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | +| | +| L_var2 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | +|___________________________________________________________________________| +*/ + +static_vo Word32 L_sub (Word32 L_var1, Word32 L_var2) +{ + Word32 L_var_out; + L_var_out = L_var1 - L_var2; + if (((L_var1 ^ L_var2) & MIN_32) != 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32; + } + } + return (L_var_out); +} + + +/*___________________________________________________________________________ +| | +| Function Name : mult_r | +| | +| Purpose : | +| | +| Same as mult with rounding, i.e.: | +| mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and | +| mult_r(-32768,-32768) = 32767. | +| | +| Complexity weight : 2 | +| | +| Inputs : | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var_out <= 0x0000 7fff. | +|___________________________________________________________________________| +*/ + +static_vo Word16 mult_r (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_product_arr; + L_product_arr = (Word32) var1 *(Word32) var2; /* product */ + L_product_arr += (Word32) 0x00004000L; /* round */ + L_product_arr &= (Word32) 0xffff8000L; + L_product_arr >>= 15; /* shift */ + if (L_product_arr & (Word32) 0x00010000L) /* sign extend when necessary */ + { + L_product_arr |= (Word32) 0xffff0000L; + } + var_out = saturate (L_product_arr); + return (var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : L_shl | +| | +| Purpose : | +| | +| Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero | +| fill the var2 LSB of the result. If var2 is negative, arithmetically | +| shift L_var1 right by -var2 with sign extension. Saturate the result in | +| case of underflows or overflows. | +| | +| Complexity weight : 2 | +| | +| Inputs : | +| | +| L_var1 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | +|___________________________________________________________________________| +*/ + +static_vo Word32 L_shl (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out = 0L; + if (var2 <= 0) + { + if (var2 < -32) + var2 = -32; + L_var_out = (L_var1 >> (Word16)-var2); + } + else + { + for (; var2 > 0; var2--) + { + if (L_var1 > (Word32) 0X3fffffffL) + { + L_var_out = MAX_32; + break; + } + else + { + if (L_var1 < (Word32) 0xc0000000L) + { + //Overflow = 1; + L_var_out = MIN_32; + break; + } + } + L_var1 *= 2; + L_var_out = L_var1; + } + } + return (L_var_out); +} + +static_vo Word32 L_shl2(Word32 L_var1, Word16 var2) +{ + Word32 L_var_out = 0L; + + for (; var2 > 0; var2--) + { + if (L_var1 > (Word32) 0X3fffffffL) + { + L_var_out = MAX_32; + break; + } + else + { + if (L_var1 < (Word32) 0xc0000000L) + { + L_var_out = MIN_32; + break; + } + } + L_var1 <<=1 ; + L_var_out = L_var1; + } + return (L_var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : L_shr | +| | +| Purpose : | +| | +| Arithmetically shift the 32 bit input L_var1 right var2 positions with | +| sign extension. If var2 is negative, arithmetically shift L_var1 left | +| by -var2 and zero fill the -var2 LSB of the result. Saturate the result | +| in case of underflows or overflows. | +| | +| Complexity weight : 2 | +| | +| Inputs : | +| | +| L_var1 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | +|___________________________________________________________________________| +*/ + +static_vo Word32 L_shr (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out; + if (var2 < 0) + { + if (var2 < -32) + var2 = -32; + L_var_out = L_shl2(L_var1, (Word16)-var2); + } + else + { + if (var2 >= 31) + { + L_var_out = (L_var1 < 0L) ? -1 : 0; + } + else + { + if (L_var1 < 0) + { + L_var_out = ~((~L_var1) >> var2); + } + else + { + L_var_out = L_var1 >> var2; + } + } + } + return (L_var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : L_shr_r | +| | +| Purpose : | +| | +| Same as L_shr(L_var1,var2) but with rounding. Saturate the result in | +| case of underflows or overflows : | +| - If var2 is greater than zero : | +| if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))| +| is equal to zero | +| then | +| L_shr_r(L_var1,var2) = L_shr(L_var1,var2) | +| else | +| L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1) | +| - If var2 is less than or equal to zero : | +| L_shr_r(L_var1,var2) = L_shr(L_var1,var2). | +| | +| Complexity weight : 3 | +| | +| Inputs : | +| | +| L_var1 | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= var1 <= 0x7fff ffff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= var_out <= 0x7fff ffff. | +|___________________________________________________________________________| +*/ + +static_vo Word32 L_shr_r (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out; + if (var2 > 31) + { + L_var_out = 0; + } + else + { + L_var_out = L_shr (L_var1, var2); + if (var2 > 0) + { + if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0) + { + L_var_out++; + } + } + } + return (L_var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : norm_s | +| | +| Purpose : | +| | +| Produces the number of left shift needed to normalize the 16 bit varia- | +| ble var1 for positive values on the interval with minimum of 16384 and | +| maximum of 32767, and for negative values on the interval with minimum | +| of -32768 and maximum of -16384; in order to normalize the result, the | +| following operation must be done : | +| norm_var1 = shl(var1,norm_s(var1)). | +| | +| Complexity weight : 15 | +| | +| Inputs : | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0x0000 0000 <= var_out <= 0x0000 000f. | +|___________________________________________________________________________| +*/ + +static_vo Word16 norm_s (Word16 var1) +{ + Word16 var_out = 0; + if (var1 == 0) + { + var_out = 0; + } + else + { + if (var1 == -1) + { + var_out = 15; + } + else + { + if (var1 < 0) + { + var1 = (Word16)~var1; + } + for (var_out = 0; var1 < 0x4000; var_out++) + { + var1 <<= 1; + } + } + } + return (var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : div_s | +| | +| Purpose : | +| | +| Produces a result which is the fractional integer division of var1 by | +| var2; var1 and var2 must be positive and var2 must be greater or equal | +| to var1; the result is positive (leading bit equal to 0) and truncated | +| to 16 bits. | +| If var1 = var2 then div(var1,var2) = 32767. | +| | +| Complexity weight : 18 | +| | +| Inputs : | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0x0000 0000 <= var1 <= var2 and var2 != 0. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : var1 <= var2 <= 0x0000 7fff and var2 != 0. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0x0000 0000 <= var_out <= 0x0000 7fff. | +| It's a Q15 value (point between b15 and b14). | +|___________________________________________________________________________| +*/ + +static_vo Word16 div_s (Word16 var1, Word16 var2) +{ + Word16 var_out = 0; + Word16 iteration; + Word32 L_num; + Word32 L_denom; + if ((var1 < 0) || (var2 < 0)) + { + var_out = MAX_16; + return var_out; + } + if (var2 == 0) + { + var_out = MAX_16; + return var_out; + } + if (var1 == 0) + { + var_out = 0; + } + else + { + if (var1 == var2) + { + var_out = MAX_16; + } + else + { + L_num = L_deposit_l (var1); + L_denom = L_deposit_l(var2); + for (iteration = 0; iteration < 15; iteration++) + { + var_out <<= 1; + L_num <<= 1; + if (L_num >= L_denom) + { + L_num -= L_denom; + var_out += 1; + } + } + } + } + return (var_out); +} + +/*___________________________________________________________________________ +| | +| Function Name : norm_l | +| | +| Purpose : | +| | +| Produces the number of left shifts needed to normalize the 32 bit varia-| +| ble L_var1 for positive values on the interval with minimum of | +| 1073741824 and maximum of 2147483647, and for negative values on the in-| +| terval with minimum of -2147483648 and maximum of -1073741824; in order | +| to normalize the result, the following operation must be done : | +| norm_L_var1 = L_shl(L_var1,norm_l(L_var1)). | +| | +| Complexity weight : 30 | +| | +| Inputs : | +| | +| L_var1 | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= var1 <= 0x7fff ffff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0x0000 0000 <= var_out <= 0x0000 001f. | +|___________________________________________________________________________| +*/ + +static_vo Word16 norm_l (Word32 L_var1) +{ + Word16 var_out = 0; + if (L_var1 != 0) + { + var_out = 31; + if (L_var1 != (Word32) 0xffffffffL) + { + L_var1 ^= (L_var1 >>31); + for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++) + { + L_var1 <<= 1; + } + } + } + return (var_out); +} + +#endif //__BASIC_OP_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/bits.h b/media/libstagefright/codecs/amrwbenc/inc/bits.h new file mode 100644 index 0000000000000000000000000000000000000000..77146de3fd481f96ae570dec8d1aea1095075b01 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/bits.h @@ -0,0 +1,92 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*--------------------------------------------------------------------------* +* BITS.H * +*--------------------------------------------------------------------------* +* Number of bits for different modes * +*--------------------------------------------------------------------------*/ + +#ifndef __BITS_H__ +#define __BITS_H__ + +#include +#include "typedef.h" +#include "cnst.h" +#include "cod_main.h" + +#define NBBITS_7k 132 /* 6.60k */ +#define NBBITS_9k 177 /* 8.85k */ +#define NBBITS_12k 253 /* 12.65k */ +#define NBBITS_14k 285 /* 14.25k */ +#define NBBITS_16k 317 /* 15.85k */ +#define NBBITS_18k 365 /* 18.25k */ +#define NBBITS_20k 397 /* 19.85k */ +#define NBBITS_23k 461 /* 23.05k */ +#define NBBITS_24k 477 /* 23.85k */ + +#define NBBITS_SID 35 +#define NB_BITS_MAX NBBITS_24k + +#define BIT_0 (Word16)-127 +#define BIT_1 (Word16)127 +#define BIT_0_ITU (Word16)0x007F +#define BIT_1_ITU (Word16)0x0081 + +#define SIZE_MAX1 (3+NB_BITS_MAX) /* serial size max */ +#define TX_FRAME_TYPE (Word16)0x6b21 +#define RX_FRAME_TYPE (Word16)0x6b20 + +static const Word16 nb_of_bits[NUM_OF_MODES] = { + NBBITS_7k, + NBBITS_9k, + NBBITS_12k, + NBBITS_14k, + NBBITS_16k, + NBBITS_18k, + NBBITS_20k, + NBBITS_23k, + NBBITS_24k, + NBBITS_SID +}; + +/*typedef struct +{ +Word16 sid_update_counter; +Word16 sid_handover_debt; +Word16 prev_ft; +} TX_State; +*/ + +//typedef struct +//{ +// Word16 prev_ft; +// Word16 prev_mode; +//} RX_State; + +int PackBits(Word16 prms[], Word16 coding_mode, Word16 mode, Coder_State *st); + + +void Parm_serial( + Word16 value, /* input : parameter value */ + Word16 no_of_bits, /* input : number of bits */ + Word16 ** prms + ); + + +#endif //__BITS_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/cnst.h b/media/libstagefright/codecs/amrwbenc/inc/cnst.h new file mode 100644 index 0000000000000000000000000000000000000000..ffdbd8815ecf8153c4dfe4ddd9233bf918a27f00 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/cnst.h @@ -0,0 +1,81 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*--------------------------------------------------------------------------* + * CNST.H * + *--------------------------------------------------------------------------* + * Codec constant parameters (coder and decoder) * + *--------------------------------------------------------------------------*/ + +#ifndef __CNST_H__ +#define __CNST_H__ + +#define L_FRAME16k 320 /* Frame size at 16kHz */ +#define L_FRAME 256 /* Frame size */ +#define L_SUBFR16k 80 /* Subframe size at 16kHz */ + +#define L_SUBFR 64 /* Subframe size */ +#define NB_SUBFR 4 /* Number of subframe per frame */ + +#define L_NEXT 64 /* Overhead in LP analysis */ +#define L_WINDOW 384 /* window size in LP analysis */ +#define L_TOTAL 384 /* Total size of speech buffer. */ +#define M 16 /* Order of LP filter */ +#define M16k 20 + +#define L_FILT16k 15 /* Delay of down-sampling filter */ +#define L_FILT 12 /* Delay of up-sampling filter */ + +#define GP_CLIP 15565 /* Pitch gain clipping = 0.95 Q14 */ +#define PIT_SHARP 27853 /* pitch sharpening factor = 0.85 Q15 */ + +#define PIT_MIN 34 /* Minimum pitch lag with resolution 1/4 */ +#define PIT_FR2 128 /* Minimum pitch lag with resolution 1/2 */ +#define PIT_FR1_9b 160 /* Minimum pitch lag with resolution 1 */ +#define PIT_FR1_8b 92 /* Minimum pitch lag with resolution 1 */ +#define PIT_MAX 231 /* Maximum pitch lag */ +#define L_INTERPOL (16+1) /* Length of filter for interpolation */ + +#define OPL_DECIM 2 /* Decimation in open-loop pitch analysis */ + +#define PREEMPH_FAC 22282 /* preemphasis factor (0.68 in Q15) */ +#define GAMMA1 30147 /* Weighting factor (numerator) (0.92 in Q15) */ +#define TILT_FAC 22282 /* tilt factor (denominator) (0.68 in Q15) */ + +#define Q_MAX 8 /* scaling max for signal (see syn_filt_32) */ + +#define RANDOM_INITSEED 21845 /* own random init value */ + +#define L_MEANBUF 3 +#define ONE_PER_MEANBUF 10923 + +#define MODE_7k 0 +#define MODE_9k 1 +#define MODE_12k 2 +#define MODE_14k 3 +#define MODE_16k 4 +#define MODE_18k 5 +#define MODE_20k 6 +#define MODE_23k 7 +#define MODE_24k 8 +#define MRDTX 9 +#define NUM_OF_MODES 10 /* see bits.h for bits definition */ + +#define EHF_MASK (Word16)0x0008 /* homing frame pattern */ + +#endif //__CNST_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/cod_main.h b/media/libstagefright/codecs/amrwbenc/inc/cod_main.h new file mode 100644 index 0000000000000000000000000000000000000000..1fd5787d0fdc44d0846e623dc58f3636336f53e6 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/cod_main.h @@ -0,0 +1,103 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*--------------------------------------------------------------------------* + * COD_MAIN.H * + *--------------------------------------------------------------------------* + * Static memory in the encoder * + *--------------------------------------------------------------------------*/ +#ifndef __COD_MAIN_H__ +#define __COD_MAIN_H__ + +#include "cnst.h" /* coder constant parameters */ + +#include "wb_vad.h" +#include "dtx.h" +#include "stream.h" +#include "voAMRWB.h" + +typedef struct +{ + Word16 mem_decim[2 * L_FILT16k]; /* speech decimated filter memory */ + Word16 mem_sig_in[6]; /* hp50 filter memory */ + Word16 mem_preemph; /* speech preemph filter memory */ + Word16 old_speech[L_TOTAL - L_FRAME]; /* old speech vector at 12.8kHz */ + Word16 old_wsp[PIT_MAX / OPL_DECIM]; /* old decimated weighted speech vector */ + Word16 old_exc[PIT_MAX + L_INTERPOL]; /* old excitation vector */ + Word16 mem_levinson[M + 2]; /* levinson routine memory */ + Word16 ispold[M]; /* old isp (immittance spectral pairs) */ + Word16 ispold_q[M]; /* quantized old isp */ + Word16 past_isfq[M]; /* past isf quantizer */ + Word16 mem_wsp; /* wsp vector memory */ + Word16 mem_decim2[3]; /* wsp decimation filter memory */ + Word16 mem_w0; /* target vector memory */ + Word16 mem_syn[M]; /* synthesis memory */ + Word16 tilt_code; /* tilt of code */ + Word16 old_wsp_max; /* old wsp maximum value */ + Word16 old_wsp_shift; /* old wsp shift */ + Word16 Q_old; /* old scaling factor */ + Word16 Q_max[2]; /* old maximum scaling factor */ + Word16 gp_clip[2]; /* gain of pitch clipping memory */ + Word16 qua_gain[4]; /* gain quantizer memory */ + + Word16 old_T0_med; + Word16 ol_gain; + Word16 ada_w; + Word16 ol_wght_flg; + Word16 old_ol_lag[5]; + Word16 hp_wsp_mem[9]; + Word16 old_hp_wsp[L_FRAME / OPL_DECIM + (PIT_MAX / OPL_DECIM)]; + VadVars *vadSt; + dtx_encState *dtx_encSt; + Word16 first_frame; + Word16 isfold[M]; /* old isf (frequency domain) */ + Word32 L_gc_thres; /* threshold for noise enhancer */ + Word16 mem_syn_hi[M]; /* modified synthesis memory (MSB) */ + Word16 mem_syn_lo[M]; /* modified synthesis memory (LSB) */ + Word16 mem_deemph; /* speech deemph filter memory */ + Word16 mem_sig_out[6]; /* hp50 filter memory for synthesis */ + Word16 mem_hp400[6]; /* hp400 filter memory for synthesis */ + Word16 mem_oversamp[2 * L_FILT]; /* synthesis oversampled filter memory */ + Word16 mem_syn_hf[M]; /* HF synthesis memory */ + Word16 mem_hf[2 * L_FILT16k]; /* HF band-pass filter memory */ + Word16 mem_hf2[2 * L_FILT16k]; /* HF band-pass filter memory */ + Word16 seed2; /* random memory for HF generation */ + Word16 vad_hist; + Word16 gain_alpha; + /* TX_State structure */ + Word16 sid_update_counter; + Word16 sid_handover_debt; + Word16 prev_ft; + Word16 allow_dtx; + /*some input/output buffer parameters */ + unsigned char *inputStream; + int inputSize; + VOAMRWBMODE mode; + VOAMRWBFRAMETYPE frameType; + unsigned short *outputStream; + int outputSize; + FrameStream *stream; + VO_MEM_OPERATOR *pvoMemop; + VO_MEM_OPERATOR voMemoprator; + VO_PTR hCheck; +} Coder_State; + +typedef void* HAMRENC; + +#endif //__COD_MAIN_H__ + + diff --git a/media/libstagefright/codecs/amrwbenc/inc/dtx.h b/media/libstagefright/codecs/amrwbenc/inc/dtx.h new file mode 100644 index 0000000000000000000000000000000000000000..e52c2d046f9f5b1c7b446b0d02caa5171c596d85 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/dtx.h @@ -0,0 +1,115 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*--------------------------------------------------------------------------* + * DTX.H * + *--------------------------------------------------------------------------* + * Static memory, constants and frametypes for the DTX * + *--------------------------------------------------------------------------*/ + +#ifndef __DTX_H__ +#define __DTX_H__ + +#define DTX_MAX_EMPTY_THRESH 50 +#define DTX_HIST_SIZE 8 +#define DTX_HIST_SIZE_MIN_ONE 7 +#define DTX_ELAPSED_FRAMES_THRESH (24 + 7 -1) +#define DTX_HANG_CONST 7 /* yields eight frames of SP HANGOVER */ +#define INV_MED_THRESH 14564 +#define ISF_GAP 128 /* 50 */ +#define ONE_MINUS_ISF_GAP 16384 - ISF_GAP +#define ISF_GAP 128 +#define ISF_DITH_GAP 448 +#define ISF_FACTOR_LOW 256 +#define ISF_FACTOR_STEP 2 +#define GAIN_THR 180 +#define GAIN_FACTOR 75 + +typedef struct +{ + Word16 isf_hist[M * DTX_HIST_SIZE]; + Word16 log_en_hist[DTX_HIST_SIZE]; + Word16 hist_ptr; + Word16 log_en_index; + Word16 cng_seed; + /* DTX handler stuff */ + Word16 dtxHangoverCount; + Word16 decAnaElapsedCount; + Word32 D[28]; + Word32 sumD[DTX_HIST_SIZE]; +} dtx_encState; + +#define SPEECH 0 +#define DTX 1 +#define DTX_MUTE 2 + +#define TX_SPEECH 0 +#define TX_SID_FIRST 1 +#define TX_SID_UPDATE 2 +#define TX_NO_DATA 3 + +#define RX_SPEECH_GOOD 0 +#define RX_SPEECH_PROBABLY_DEGRADED 1 +#define RX_SPEECH_LOST 2 +#define RX_SPEECH_BAD 3 +#define RX_SID_FIRST 4 +#define RX_SID_UPDATE 5 +#define RX_SID_BAD 6 +#define RX_NO_DATA 7 + +/***************************************************************************** + * + * DEFINITION OF DATA TYPES + *****************************************************************************/ + +Word16 dtx_enc_init(dtx_encState ** st, Word16 isf_init[], VO_MEM_OPERATOR *pMemOP); +Word16 dtx_enc_reset(dtx_encState * st, Word16 isf_init[]); +void dtx_enc_exit(dtx_encState ** st, VO_MEM_OPERATOR *pMemOP); + +Word16 dtx_enc( + dtx_encState * st, /* i/o : State struct */ + Word16 isf[M], /* o : CN ISF vector */ + Word16 * exc2, /* o : CN excitation */ + Word16 ** prms +); + +Word16 dtx_buffer( + dtx_encState * st, /* i/o : State struct */ + Word16 isf_new[], /* i : isf vector */ + Word32 enr, /* i : residual energy (in L_FRAME) */ + Word16 codec_mode +); + +void tx_dtx_handler(dtx_encState * st, /* i/o : State struct */ + Word16 vad_flag, /* i : vad decision */ + Word16 * usedMode /* i/o : mode changed or not */ +); + +void Qisf_ns( + Word16 * isf1, /* input : ISF in the frequency domain (0..0.5) */ + Word16 * isf_q, /* output: quantized ISF */ + Word16 * indice /* output: quantization indices */ +); + + +void Disf_ns( + Word16 * indice, /* input: quantization indices */ + Word16 * isf_q /* input : ISF in the frequency domain (0..0.5) */ +); + +#endif //__DTX_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/grid100.tab b/media/libstagefright/codecs/amrwbenc/inc/grid100.tab new file mode 100644 index 0000000000000000000000000000000000000000..efee18d38b50a2b21a6aa5fb2363ea32b907a9be --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/grid100.tab @@ -0,0 +1,53 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + + +/*-------------------------------------------------------------* + * Table for az_isp() * + * * + * Vector grid[] is in Q15 * + * * + * grid[0] = 1.0; * + * grid[grid_points+1] = -1.0; * + * for (i = 1; i < grid_points; i++) * + * grid[i] = cos((6.283185307*i)/(2.0*grid_points)); * + * * + *-------------------------------------------------------------*/ + +/* Version 101 points */ + +#define GRID_POINTS 100 + +const Word16 vogrid[GRID_POINTS+1] ={ + 32767, 32751, 32703, 32622, 32509, 32364, + 32187, 31978, 31738, 31466, 31164, 30830, + 30466, 30072, 29649, 29196, 28714, 28204, + 27666, 27101, 26509, 25891, 25248, 24579, + 23886, 23170, 22431, 21669, 20887, 20083, + 19260, 18418, 17557, 16680, 15786, 14876, + 13951, 13013, 12062, 11099, 10125, 9141, + 8149, 7148, 6140, 5126, 4106, 3083, + 2057, 1029, 0, -1029, -2057, -3083, + -4106, -5126, -6140, -7148, -8149, -9141, + -10125, -11099, -12062, -13013, -13951, -14876, + -15786, -16680, -17557, -18418, -19260, -20083, + -20887, -21669, -22431, -23170, -23886, -24579, + -25248, -25891, -26509, -27101, -27666, -28204, + -28714, -29196, -29649, -30072, -30466, -30830, + -31164, -31466, -31738, -31978, -32187, -32364, + -32509, -32622, -32703, -32751, -32760}; + diff --git a/media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab b/media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab new file mode 100644 index 0000000000000000000000000000000000000000..91f86900f7719992d5e116702bd0d7606d9459f4 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab @@ -0,0 +1,73 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/* Hamming_cos window for LPC analysis. */ +/* Create with function hamm_cos(window,384-128,128) */ + +#define L_WINDOW 384 + +const Word16 vo_window[L_WINDOW] = { + 2621, 2622, 2626, 2632, 2640, 2650, 2662, 2677, + 2694, 2714, 2735, 2759, 2785, 2814, 2844, 2877, + 2912, 2949, 2989, 3031, 3075, 3121, 3169, 3220, + 3273, 3328, 3385, 3444, 3506, 3569, 3635, 3703, + 3773, 3845, 3919, 3996, 4074, 4155, 4237, 4321, + 4408, 4496, 4587, 4680, 4774, 4870, 4969, 5069, + 5171, 5275, 5381, 5489, 5599, 5710, 5824, 5939, + 6056, 6174, 6295, 6417, 6541, 6666, 6793, 6922, + 7052, 7185, 7318, 7453, 7590, 7728, 7868, 8009, + 8152, 8296, 8442, 8589, 8737, 8887, 9038, 9191, + 9344, 9499, 9655, 9813, 9971, 10131, 10292, 10454, + 10617, 10781, 10946, 11113, 11280, 11448, 11617, 11787, + 11958, 12130, 12303, 12476, 12650, 12825, 13001, 13178, + 13355, 13533, 13711, 13890, 14070, 14250, 14431, 14612, + 14793, 14975, 15158, 15341, 15524, 15708, 15891, 16076, + 16260, 16445, 16629, 16814, 16999, 17185, 17370, 17555, + 17740, 17926, 18111, 18296, 18481, 18666, 18851, 19036, + 19221, 19405, 19589, 19773, 19956, 20139, 20322, 20504, + 20686, 20867, 21048, 21229, 21408, 21588, 21767, 21945, + 22122, 22299, 22475, 22651, 22825, 22999, 23172, 23344, + 23516, 23686, 23856, 24025, 24192, 24359, 24525, 24689, + 24853, 25016, 25177, 25337, 25496, 25654, 25811, 25967, + 26121, 26274, 26426, 26576, 26725, 26873, 27019, 27164, + 27308, 27450, 27590, 27729, 27867, 28003, 28137, 28270, + 28401, 28531, 28659, 28785, 28910, 29033, 29154, 29274, + 29391, 29507, 29622, 29734, 29845, 29953, 30060, 30165, + 30268, 30370, 30469, 30566, 30662, 30755, 30847, 30936, + 31024, 31109, 31193, 31274, 31354, 31431, 31506, 31579, + 31651, 31719, 31786, 31851, 31914, 31974, 32032, 32088, + 32142, 32194, 32243, 32291, 32336, 32379, 32419, 32458, + 32494, 32528, 32560, 32589, 32617, 32642, 32664, 32685, + 32703, 32719, 32733, 32744, 32753, 32760, 32764, 32767, + 32767, 32765, 32757, 32745, 32727, 32705, 32678, 32646, + 32609, 32567, 32520, 32468, 32411, 32349, 32283, 32211, + 32135, 32054, 31968, 31877, 31781, 31681, 31575, 31465, + 31351, 31231, 31107, 30978, 30844, 30706, 30563, 30415, + 30263, 30106, 29945, 29779, 29609, 29434, 29255, 29071, + 28883, 28691, 28494, 28293, 28087, 27878, 27664, 27446, + 27224, 26997, 26767, 26533, 26294, 26052, 25806, 25555, + 25301, 25043, 24782, 24516, 24247, 23974, 23698, 23418, + 23134, 22847, 22557, 22263, 21965, 21665, 21361, 21054, + 20743, 20430, 20113, 19794, 19471, 19146, 18817, 18486, + 18152, 17815, 17476, 17134, 16789, 16442, 16092, 15740, + 15385, 15028, 14669, 14308, 13944, 13579, 13211, 12841, + 12470, 12096, 11721, 11344, 10965, 10584, 10202, 9819, + 9433, 9047, 8659, 8270, 7879, 7488, 7095, 6701, + 6306, 5910, 5514, 5116, 4718, 4319, 3919, 3519, + 3118, 2716, 2315, 1913, 1510, 1108, 705, 302}; + + diff --git a/media/libstagefright/codecs/amrwbenc/inc/homing.tab b/media/libstagefright/codecs/amrwbenc/inc/homing.tab new file mode 100644 index 0000000000000000000000000000000000000000..2963da7ac251078b986950418aec7007e21bab45 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/homing.tab @@ -0,0 +1,123 @@ + +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + + +#define DHF_PARMS_MAX 32 /* homing frame pattern */ +#define NUM_OF_SPMODES 9 + +#define PRML 15 +#define PRMN_7k NBBITS_7k/PRML + 1 +#define PRMN_9k NBBITS_9k/PRML + 1 +#define PRMN_12k NBBITS_12k/PRML + 1 +#define PRMN_14k NBBITS_14k/PRML + 1 +#define PRMN_16k NBBITS_16k/PRML + 1 +#define PRMN_18k NBBITS_18k/PRML + 1 +#define PRMN_20k NBBITS_20k/PRML + 1 +#define PRMN_23k NBBITS_23k/PRML + 1 +#define PRMN_24k NBBITS_24k/PRML + 1 + +static const Word16 dfh_M7k[PRMN_7k] = +{ + 3168, 29954, 29213, 16121, + 64, 13440, 30624, 16430, + 19008 +}; + +static const Word16 dfh_M9k[PRMN_9k] = +{ + 3168, 31665, 9943, 9123, + 15599, 4358, 20248, 2048, + 17040, 27787, 16816, 13888 +}; + +static const Word16 dfh_M12k[PRMN_12k] = +{ + 3168, 31665, 9943, 9128, + 3647, 8129, 30930, 27926, + 18880, 12319, 496, 1042, + 4061, 20446, 25629, 28069, + 13948 +}; + +static const Word16 dfh_M14k[PRMN_14k] = +{ + 3168, 31665, 9943, 9131, + 24815, 655, 26616, 26764, + 7238, 19136, 6144, 88, + 4158, 25733, 30567, 30494, + 221, 20321, 17823 +}; + +static const Word16 dfh_M16k[PRMN_16k] = +{ + 3168, 31665, 9943, 9131, + 24815, 700, 3824, 7271, + 26400, 9528, 6594, 26112, + 108, 2068, 12867, 16317, + 23035, 24632, 7528, 1752, + 6759, 24576 +}; + +static const Word16 dfh_M18k[PRMN_18k] = +{ + 3168, 31665, 9943, 9135, + 14787, 14423, 30477, 24927, + 25345, 30154, 916, 5728, + 18978, 2048, 528, 16449, + 2436, 3581, 23527, 29479, + 8237, 16810, 27091, 19052, + 0 +}; + +static const Word16 dfh_M20k[PRMN_20k] = +{ + 3168, 31665, 9943, 9129, + 8637, 31807, 24646, 736, + 28643, 2977, 2566, 25564, + 12930, 13960, 2048, 834, + 3270, 4100, 26920, 16237, + 31227, 17667, 15059, 20589, + 30249, 29123, 0 +}; + +static const Word16 dfh_M23k[PRMN_23k] = +{ + 3168, 31665, 9943, 9132, + 16748, 3202, 28179, 16317, + 30590, 15857, 19960, 8818, + 21711, 21538, 4260, 16690, + 20224, 3666, 4194, 9497, + 16320, 15388, 5755, 31551, + 14080, 3574, 15932, 50, + 23392, 26053, 31216 +}; + +static const Word16 dfh_M24k[PRMN_24k] = +{ + 3168, 31665, 9943, 9134, + 24776, 5857, 18475, 28535, + 29662, 14321, 16725, 4396, + 29353, 10003, 17068, 20504, + 720, 0, 8465, 12581, + 28863, 24774, 9709, 26043, + 7941, 27649, 13965, 15236, + 18026, 22047, 16681, 3968 +}; + + + diff --git a/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab b/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab new file mode 100644 index 0000000000000000000000000000000000000000..ff20e38e25facea036a93253314777d124798297 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab @@ -0,0 +1,62 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*-----------------------------------------------------* + | Tables for function Isf_isp() and Isp_isf() | + *-----------------------------------------------------*/ + +/* table of cos(x) in Q15 */ + +const static Word16 table[129] = { + 32767, + 32758, 32729, 32679, 32610, 32522, 32413, 32286, 32138, + 31972, 31786, 31581, 31357, 31114, 30853, 30572, 30274, + 29957, 29622, 29269, 28899, 28511, 28106, 27684, 27246, + 26791, 26320, 25833, 25330, 24812, 24279, 23732, 23170, + 22595, 22006, 21403, 20788, 20160, 19520, 18868, 18205, + 17531, 16846, 16151, 15447, 14733, 14010, 13279, 12540, + 11793, 11039, 10279, 9512, 8740, 7962, 7180, 6393, + 5602, 4808, 4011, 3212, 2411, 1608, 804, 0, + -804, -1608, -2411, -3212, -4011, -4808, -5602, -6393, + -7180, -7962, -8740, -9512, -10279, -11039, -11793, -12540, + -13279, -14010, -14733, -15447, -16151, -16846, -17531, -18205, + -18868, -19520, -20160, -20788, -21403, -22006, -22595, -23170, + -23732, -24279, -24812, -25330, -25833, -26320, -26791, -27246, + -27684, -28106, -28511, -28899, -29269, -29622, -29957, -30274, + -30572, -30853, -31114, -31357, -31581, -31786, -31972, -32138, + -32286, -32413, -32522, -32610, -32679, -32729, -32758, -32768}; + +/* slope in Q11 used to compute y = acos(x) */ + +const static Word16 slope[128] = { + -26214, -9039, -5243, -3799, -2979, -2405, -2064, -1771, + -1579, -1409, -1279, -1170, -1079, -1004, -933, -880, + -827, -783, -743, -708, -676, -647, -621, -599, + -576, -557, -538, -521, -506, -492, -479, -466, + -456, -445, -435, -426, -417, -410, -402, -395, + -389, -383, -377, -372, -367, -363, -359, -355, + -351, -348, -345, -342, -340, -337, -335, -333, + -331, -330, -329, -328, -327, -326, -326, -326, + -326, -326, -326, -327, -328, -329, -330, -331, + -333, -335, -337, -340, -342, -345, -348, -351, + -355, -359, -363, -367, -372, -377, -383, -389, + -395, -402, -410, -417, -426, -435, -445, -456, + -466, -479, -492, -506, -521, -538, -557, -576, + -599, -621, -647, -676, -708, -743, -783, -827, + -880, -933, -1004, -1079, -1170, -1279, -1409, -1579, + -1771, -2064, -2405, -2979, -3799, -5243, -9039, -26214}; + diff --git a/media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab b/media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab new file mode 100644 index 0000000000000000000000000000000000000000..4175d666b9265fa6e054804f6bdd09c2d01e52a3 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab @@ -0,0 +1,81 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*-----------------------------------------------------* + | Table of lag_window for autocorrelation. | + | noise floor = 1.0001 = (0.9999 on r[1] ..r[16]) | + | Bandwidth expansion = 60 Hz | + | Sampling frequency = 12800 Hz | + | | + | Special double precision format. See "math_op.c" | + | | + | lag_wind[0] = 1.00000000 (not stored) | + | lag_wind[1] = 0.99946642 | + | lag_wind[2] = 0.99816680 | + | lag_wind[3] = 0.99600452 | + | lag_wind[4] = 0.99298513 | + | lag_wind[5] = 0.98911655 | + | lag_wind[6] = 0.98440880 | + | lag_wind[7] = 0.97887397 | + | lag_wind[8] = 0.97252619 | + | lag_wind[9] = 0.96538186 | + | lag_wind[10]= 0.95745903 | + | lag_wind[11]= 0.94877797 | + | lag_wind[12]= 0.93936038 | + | lag_wind[13]= 0.92922986 | + | lag_wind[14]= 0.91841155 | + | lag_wind[15]= 0.90693212 | + | lag_wind[16]= 0.89481968 | + ------------------------------------------------------*/ + +#define M 16 + +static Word16 volag_h[M] = { + 32750, + 32707, + 32637, + 32538, + 32411, + 32257, + 32075, + 31867, + 31633, + 31374, + 31089, + 30780, + 30449, + 30094, + 29718, + 29321}; + +static Word16 volag_l[M] = { + 16896, + 30464, + 2496, + 4480, + 12160, + 3520, + 24320, + 24192, + 20736, + 576, + 18240, + 31488, + 128, + 16704, + 11520, + 14784}; diff --git a/media/libstagefright/codecs/amrwbenc/inc/log2.h b/media/libstagefright/codecs/amrwbenc/inc/log2.h new file mode 100644 index 0000000000000000000000000000000000000000..91bdbec38fa4d661099a06d707c831cb6203005b --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/log2.h @@ -0,0 +1,62 @@ + +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/******************************************************************************** +* +* File : log2.h +* Purpose : Computes log2(L_x) +* +******************************************************************************** +*/ +#ifndef __LOG2_H__ +#define __LOG2_H__ + +/* +******************************************************************************** +* INCLUDE FILES +******************************************************************************** +*/ +#include "typedef.h" + +/* +******************************************************************************** +* DEFINITION OF DATA TYPES +******************************************************************************** +*/ + +/* +******************************************************************************** +* DECLARATION OF PROTOTYPES +******************************************************************************** +*/ +void Log2 ( + Word32 L_x, /* (i) : input value */ + Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */ + Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1)*/ + ); + +void Log2_norm ( + Word32 L_x, /* (i) : input value (normalized) */ + Word16 exp, /* (i) : norm_l (L_x) */ + Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */ + Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */ + ); + +#endif //__LOG2_H__ + + diff --git a/media/libstagefright/codecs/amrwbenc/inc/log2_tab.h b/media/libstagefright/codecs/amrwbenc/inc/log2_tab.h new file mode 100644 index 0000000000000000000000000000000000000000..7761ae6f993c4b29b32ebdcbba066639decf14c9 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/log2_tab.h @@ -0,0 +1,35 @@ + +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + + +/******************************************************************************* +* +* File : log2.tab +* Purpose : Table for routine Log2(). +* $Id $ +* +******************************************************************************** +*/ +static const Word16 table[33] = +{ + 0, 1455, 2866, 4236, 5568, 6863, 8124, 9352, 10549, 11716, + 12855, 13967, 15054, 16117, 17156, 18172, 19167, 20142, 21097, 22033, + 22951, 23852, 24735, 25603, 26455, 27291, 28113, 28922, 29716, 30497, + 31266, 32023, 32767 +}; + diff --git a/media/libstagefright/codecs/amrwbenc/inc/main.h b/media/libstagefright/codecs/amrwbenc/inc/main.h new file mode 100644 index 0000000000000000000000000000000000000000..d7e7c672ea051b5e14849c379cfc23c0171341c3 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/main.h @@ -0,0 +1,45 @@ + +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*--------------------------------------------------------------------------* + * MAIN.H * + *--------------------------------------------------------------------------* + * Main functions * + *--------------------------------------------------------------------------*/ + +#ifndef __MAIN_H__ +#define __MAIN_H__ + +void coder( + Word16 * mode, /* input : used mode */ + Word16 speech16k[], /* input : 320 new speech samples (at 16 kHz) */ + Word16 prms[], /* output: output parameters */ + Word16 * ser_size, /* output: bit rate of the used mode */ + void *spe_state, /* i/o : State structure */ + Word16 allow_dtx /* input : DTX ON/OFF */ +); + + + +void Reset_encoder(void *st, Word16 reset_all); + + +Word16 encoder_homing_frame_test(Word16 input_frame[]); + +#endif //__MAIN_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/math_op.h b/media/libstagefright/codecs/amrwbenc/inc/math_op.h new file mode 100644 index 0000000000000000000000000000000000000000..25e29f73eb46a12ff3f2376550c124b5785a7d07 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/math_op.h @@ -0,0 +1,55 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*--------------------------------------------------------------------------* + * MATH_OP.H * + *--------------------------------------------------------------------------* + * Mathematical operations * + *--------------------------------------------------------------------------*/ + +#ifndef __MATH_OP_H__ +#define __MATH_OP_H__ + +Word32 Isqrt( /* (o) Q31 : output value (range: 0<=val<1) */ + Word32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */ + ); + +void Isqrt_n( + Word32 * frac, /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */ + Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */ + ); + +Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */ + Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */ + Word16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */ + ); + +Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */ + Word16 x[], /* (i) 12bits: x vector */ + Word16 y[], /* (i) 12bits: y vector */ + Word16 lg, /* (i) : vector length */ + Word16 * exp /* (o) : exponent of result (0..+30) */ + ); + +Word32 Dot_product12_asm( /* (o) Q31: normalized result (1 < val <= -1) */ + Word16 x[], /* (i) 12bits: x vector */ + Word16 y[], /* (i) 12bits: y vector */ + Word16 lg, /* (i) : vector length */ + Word16 * exp /* (o) : exponent of result (0..+30) */ + ); +#endif //__MATH_OP_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/mem_align.h b/media/libstagefright/codecs/amrwbenc/inc/mem_align.h new file mode 100644 index 0000000000000000000000000000000000000000..d6ddec3552c68a872babcebf8b08656ccab25f07 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/mem_align.h @@ -0,0 +1,35 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: mem_align.h + + Content: Memory alloc alignments functions + +*******************************************************************************/ + +#ifndef __VO_MEM_ALIGN_H__ +#define __VO_MEM_ALIGN_H__ + +#include "voMem.h" +#include "typedef.h" + +extern void *mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID); +extern void mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID); + +#endif /* __VO_MEM_ALIGN_H__ */ + + + diff --git a/media/libstagefright/codecs/amrwbenc/inc/mime_io.tab b/media/libstagefright/codecs/amrwbenc/inc/mime_io.tab new file mode 100644 index 0000000000000000000000000000000000000000..ffc86a14c34d9378f979ee944251dcadeccfe31b --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/mime_io.tab @@ -0,0 +1,368 @@ + +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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 "typedef.h" + +static UWord8 toc_byte[16] = {0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x34, 0x3C, + 0x44, 0x4C, 0x54, 0x5C, 0x64, 0x6C, 0x74, 0x7C}; + +/* number of speech bits for all modes */ +static Word16 unpacked_size[16] = {132, 177, 253, 285, 317, 365, 397, 461, + 477, 35, 0, 0, 0, 0, 0, 0}; + +/* size of packed frame for each mode, excluding TOC byte */ +static Word16 packed_size[16] = {17, 23, 32, 36, 40, 46, 50, 58, + 60, 5, 0, 0, 0, 0, 0, 0}; + +/* number of unused speech bits in packed format for each mode */ +static Word16 unused_size[16] = {4, 7, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0}; + +/* sorting tables for all modes */ + +static Word16 sort_660[132] = { + 0, 5, 6, 7, 61, 84, 107, 130, 62, 85, + 8, 4, 37, 38, 39, 40, 58, 81, 104, 127, + 60, 83, 106, 129, 108, 131, 128, 41, 42, 80, + 126, 1, 3, 57, 103, 82, 105, 59, 2, 63, + 109, 110, 86, 19, 22, 23, 64, 87, 18, 20, + 21, 17, 13, 88, 43, 89, 65, 111, 14, 24, + 25, 26, 27, 28, 15, 16, 44, 90, 66, 112, + 9, 11, 10, 12, 67, 113, 29, 30, 31, 32, + 34, 33, 35, 36, 45, 51, 68, 74, 91, 97, + 114, 120, 46, 69, 92, 115, 52, 75, 98, 121, + 47, 70, 93, 116, 53, 76, 99, 122, 48, 71, + 94, 117, 54, 77, 100, 123, 49, 72, 95, 118, + 55, 78, 101, 124, 50, 73, 96, 119, 56, 79, + 102, 125 +}; + +static Word16 sort_885[177] = { + 0, 4, 6, 7, 5, 3, 47, 48, 49, 112, + 113, 114, 75, 106, 140, 171, 80, 111, 145, 176, + 77, 108, 142, 173, 78, 109, 143, 174, 79, 110, + 144, 175, 76, 107, 141, 172, 50, 115, 51, 2, + 1, 81, 116, 146, 19, 21, 12, 17, 18, 20, + 16, 25, 13, 10, 14, 24, 23, 22, 26, 8, + 15, 52, 117, 31, 82, 147, 9, 33, 11, 83, + 148, 53, 118, 28, 27, 84, 149, 34, 35, 29, + 46, 32, 30, 54, 119, 37, 36, 39, 38, 40, + 85, 150, 41, 42, 43, 44, 45, 55, 60, 65, + 70, 86, 91, 96, 101, 120, 125, 130, 135, 151, + 156, 161, 166, 56, 87, 121, 152, 61, 92, 126, + 157, 66, 97, 131, 162, 71, 102, 136, 167, 57, + 88, 122, 153, 62, 93, 127, 158, 67, 98, 132, + 163, 72, 103, 137, 168, 58, 89, 123, 154, 63, + 94, 128, 159, 68, 99, 133, 164, 73, 104, 138, + 169, 59, 90, 124, 155, 64, 95, 129, 160, 69, + 100, 134, 165, 74, 105, 139, 170 +}; + +static Word16 sort_1265[253] = { + 0, 4, 6, 93, 143, 196, 246, 7, 5, 3, + 47, 48, 49, 50, 51, 150, 151, 152, 153, 154, + 94, 144, 197, 247, 99, 149, 202, 252, 96, 146, + 199, 249, 97, 147, 200, 250, 100, 203, 98, 148, + 201, 251, 95, 145, 198, 248, 52, 2, 1, 101, + 204, 155, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 156, 31, 102, 205, 9, 33, 11, 103, 206, 54, + 157, 28, 27, 104, 207, 34, 35, 29, 46, 32, + 30, 55, 158, 37, 36, 39, 38, 40, 105, 208, + 41, 42, 43, 44, 45, 56, 106, 159, 209, 57, + 66, 75, 84, 107, 116, 125, 134, 160, 169, 178, + 187, 210, 219, 228, 237, 58, 108, 161, 211, 62, + 112, 165, 215, 67, 117, 170, 220, 71, 121, 174, + 224, 76, 126, 179, 229, 80, 130, 183, 233, 85, + 135, 188, 238, 89, 139, 192, 242, 59, 109, 162, + 212, 63, 113, 166, 216, 68, 118, 171, 221, 72, + 122, 175, 225, 77, 127, 180, 230, 81, 131, 184, + 234, 86, 136, 189, 239, 90, 140, 193, 243, 60, + 110, 163, 213, 64, 114, 167, 217, 69, 119, 172, + 222, 73, 123, 176, 226, 78, 128, 181, 231, 82, + 132, 185, 235, 87, 137, 190, 240, 91, 141, 194, + 244, 61, 111, 164, 214, 65, 115, 168, 218, 70, + 120, 173, 223, 74, 124, 177, 227, 79, 129, 182, + 232, 83, 133, 186, 236, 88, 138, 191, 241, 92, + 142, 195, 245 +}; + +static Word16 sort_1425[285] = { + 0, 4, 6, 101, 159, 220, 278, 7, 5, 3, + 47, 48, 49, 50, 51, 166, 167, 168, 169, 170, + 102, 160, 221, 279, 107, 165, 226, 284, 104, 162, + 223, 281, 105, 163, 224, 282, 108, 227, 106, 164, + 225, 283, 103, 161, 222, 280, 52, 2, 1, 109, + 228, 171, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 172, 31, 110, 229, 9, 33, 11, 111, 230, 54, + 173, 28, 27, 112, 231, 34, 35, 29, 46, 32, + 30, 55, 174, 37, 36, 39, 38, 40, 113, 232, + 41, 42, 43, 44, 45, 56, 114, 175, 233, 62, + 120, 181, 239, 75, 133, 194, 252, 57, 115, 176, + 234, 63, 121, 182, 240, 70, 128, 189, 247, 76, + 134, 195, 253, 83, 141, 202, 260, 92, 150, 211, + 269, 84, 142, 203, 261, 93, 151, 212, 270, 85, + 143, 204, 262, 94, 152, 213, 271, 86, 144, 205, + 263, 95, 153, 214, 272, 64, 122, 183, 241, 77, + 135, 196, 254, 65, 123, 184, 242, 78, 136, 197, + 255, 87, 145, 206, 264, 96, 154, 215, 273, 58, + 116, 177, 235, 66, 124, 185, 243, 71, 129, 190, + 248, 79, 137, 198, 256, 88, 146, 207, 265, 97, + 155, 216, 274, 59, 117, 178, 236, 67, 125, 186, + 244, 72, 130, 191, 249, 80, 138, 199, 257, 89, + 147, 208, 266, 98, 156, 217, 275, 60, 118, 179, + 237, 68, 126, 187, 245, 73, 131, 192, 250, 81, + 139, 200, 258, 90, 148, 209, 267, 99, 157, 218, + 276, 61, 119, 180, 238, 69, 127, 188, 246, 74, + 132, 193, 251, 82, 140, 201, 259, 91, 149, 210, + 268, 100, 158, 219, 277 +}; + +static Word16 sort_1585[317] = { + 0, 4, 6, 109, 175, 244, 310, 7, 5, 3, + 47, 48, 49, 50, 51, 182, 183, 184, 185, 186, + 110, 176, 245, 311, 115, 181, 250, 316, 112, 178, + 247, 313, 113, 179, 248, 314, 116, 251, 114, 180, + 249, 315, 111, 177, 246, 312, 52, 2, 1, 117, + 252, 187, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 188, 31, 118, 253, 9, 33, 11, 119, 254, 54, + 189, 28, 27, 120, 255, 34, 35, 29, 46, 32, + 30, 55, 190, 37, 36, 39, 38, 40, 121, 256, + 41, 42, 43, 44, 45, 56, 122, 191, 257, 63, + 129, 198, 264, 76, 142, 211, 277, 89, 155, 224, + 290, 102, 168, 237, 303, 57, 123, 192, 258, 70, + 136, 205, 271, 83, 149, 218, 284, 96, 162, 231, + 297, 62, 128, 197, 263, 75, 141, 210, 276, 88, + 154, 223, 289, 101, 167, 236, 302, 58, 124, 193, + 259, 71, 137, 206, 272, 84, 150, 219, 285, 97, + 163, 232, 298, 59, 125, 194, 260, 64, 130, 199, + 265, 67, 133, 202, 268, 72, 138, 207, 273, 77, + 143, 212, 278, 80, 146, 215, 281, 85, 151, 220, + 286, 90, 156, 225, 291, 93, 159, 228, 294, 98, + 164, 233, 299, 103, 169, 238, 304, 106, 172, 241, + 307, 60, 126, 195, 261, 65, 131, 200, 266, 68, + 134, 203, 269, 73, 139, 208, 274, 78, 144, 213, + 279, 81, 147, 216, 282, 86, 152, 221, 287, 91, + 157, 226, 292, 94, 160, 229, 295, 99, 165, 234, + 300, 104, 170, 239, 305, 107, 173, 242, 308, 61, + 127, 196, 262, 66, 132, 201, 267, 69, 135, 204, + 270, 74, 140, 209, 275, 79, 145, 214, 280, 82, + 148, 217, 283, 87, 153, 222, 288, 92, 158, 227, + 293, 95, 161, 230, 296, 100, 166, 235, 301, 105, + 171, 240, 306, 108, 174, 243, 309 +}; + +static Word16 sort_1825[365] = { + 0, 4, 6, 121, 199, 280, 358, 7, 5, 3, + 47, 48, 49, 50, 51, 206, 207, 208, 209, 210, + 122, 200, 281, 359, 127, 205, 286, 364, 124, 202, + 283, 361, 125, 203, 284, 362, 128, 287, 126, 204, + 285, 363, 123, 201, 282, 360, 52, 2, 1, 129, + 288, 211, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 212, 31, 130, 289, 9, 33, 11, 131, 290, 54, + 213, 28, 27, 132, 291, 34, 35, 29, 46, 32, + 30, 55, 214, 37, 36, 39, 38, 40, 133, 292, + 41, 42, 43, 44, 45, 56, 134, 215, 293, 198, + 299, 136, 120, 138, 60, 279, 58, 62, 357, 139, + 140, 295, 156, 57, 219, 297, 63, 217, 137, 170, + 300, 222, 64, 106, 61, 78, 294, 92, 142, 141, + 135, 221, 296, 301, 343, 59, 298, 184, 329, 315, + 220, 216, 265, 251, 218, 237, 352, 223, 157, 86, + 171, 87, 164, 351, 111, 302, 65, 178, 115, 323, + 72, 192, 101, 179, 93, 73, 193, 151, 337, 309, + 143, 274, 69, 324, 165, 150, 97, 338, 110, 310, + 330, 273, 68, 107, 175, 245, 114, 79, 113, 189, + 246, 259, 174, 71, 185, 96, 344, 100, 322, 83, + 334, 316, 333, 252, 161, 348, 147, 82, 269, 232, + 260, 308, 353, 347, 163, 231, 306, 320, 188, 270, + 146, 177, 266, 350, 256, 85, 149, 116, 191, 160, + 238, 258, 336, 305, 255, 88, 224, 99, 339, 230, + 228, 227, 272, 242, 241, 319, 233, 311, 102, 74, + 180, 275, 66, 194, 152, 325, 172, 247, 244, 261, + 117, 158, 166, 354, 75, 144, 108, 312, 94, 186, + 303, 80, 234, 89, 195, 112, 340, 181, 345, 317, + 326, 276, 239, 167, 118, 313, 70, 355, 327, 253, + 190, 176, 271, 104, 98, 153, 103, 90, 76, 267, + 277, 248, 225, 262, 182, 84, 154, 235, 335, 168, + 331, 196, 341, 249, 162, 307, 148, 349, 263, 321, + 257, 243, 229, 356, 159, 119, 67, 187, 173, 145, + 240, 77, 304, 332, 314, 342, 109, 254, 81, 278, + 105, 91, 346, 318, 183, 250, 197, 328, 95, 155, + 169, 268, 226, 236, 264 +}; + +static Word16 sort_1985[397] = { + 0, 4, 6, 129, 215, 304, 390, 7, 5, 3, + 47, 48, 49, 50, 51, 222, 223, 224, 225, 226, + 130, 216, 305, 391, 135, 221, 310, 396, 132, 218, + 307, 393, 133, 219, 308, 394, 136, 311, 134, 220, + 309, 395, 131, 217, 306, 392, 52, 2, 1, 137, + 312, 227, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 228, 31, 138, 313, 9, 33, 11, 139, 314, 54, + 229, 28, 27, 140, 315, 34, 35, 29, 46, 32, + 30, 55, 230, 37, 36, 39, 38, 40, 141, 316, + 41, 42, 43, 44, 45, 56, 142, 231, 317, 63, + 73, 92, 340, 82, 324, 149, 353, 159, 334, 165, + 338, 178, 163, 254, 77, 168, 257, 153, 343, 57, + 248, 238, 79, 252, 166, 67, 80, 201, 101, 267, + 143, 164, 341, 255, 339, 187, 376, 318, 78, 328, + 362, 115, 232, 242, 253, 290, 276, 62, 58, 158, + 68, 93, 179, 319, 148, 169, 154, 72, 385, 329, + 333, 344, 102, 83, 144, 233, 323, 124, 243, 192, + 354, 237, 64, 247, 202, 209, 150, 116, 335, 268, + 239, 299, 188, 196, 298, 94, 195, 258, 123, 363, + 384, 109, 325, 371, 170, 370, 84, 110, 295, 180, + 74, 210, 191, 106, 291, 205, 367, 381, 377, 206, + 355, 122, 119, 120, 383, 160, 105, 108, 277, 380, + 294, 284, 285, 345, 208, 269, 249, 366, 386, 300, + 297, 259, 125, 369, 197, 97, 194, 286, 211, 281, + 280, 183, 372, 87, 155, 283, 59, 348, 327, 184, + 76, 111, 330, 203, 349, 69, 98, 152, 145, 189, + 66, 320, 337, 173, 358, 251, 198, 174, 263, 262, + 126, 241, 193, 88, 388, 117, 95, 387, 112, 359, + 287, 244, 103, 272, 301, 171, 162, 234, 273, 127, + 373, 181, 292, 85, 378, 302, 121, 107, 364, 346, + 356, 212, 278, 213, 65, 382, 288, 207, 113, 175, + 99, 296, 374, 368, 199, 260, 185, 336, 331, 161, + 270, 264, 250, 240, 75, 350, 151, 60, 89, 321, + 156, 274, 360, 326, 70, 282, 167, 146, 352, 81, + 91, 389, 266, 245, 177, 235, 190, 256, 204, 342, + 128, 118, 303, 104, 379, 182, 114, 375, 200, 96, + 293, 172, 214, 365, 279, 86, 289, 351, 347, 357, + 261, 186, 176, 271, 90, 100, 147, 322, 275, 361, + 71, 332, 61, 265, 157, 246, 236 +}; + +static Word16 sort_2305[461] = { + 0, 4, 6, 145, 247, 352, 454, 7, 5, 3, + 47, 48, 49, 50, 51, 254, 255, 256, 257, 258, + 146, 248, 353, 455, 151, 253, 358, 460, 148, 250, + 355, 457, 149, 251, 356, 458, 152, 359, 150, 252, + 357, 459, 147, 249, 354, 456, 52, 2, 1, 153, + 360, 259, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 260, 31, 154, 361, 9, 33, 11, 155, 362, 54, + 261, 28, 27, 156, 363, 34, 35, 29, 46, 32, + 30, 55, 262, 37, 36, 39, 38, 40, 157, 364, + 41, 42, 43, 44, 45, 56, 158, 263, 365, 181, + 192, 170, 79, 57, 399, 90, 159, 297, 377, 366, + 275, 68, 183, 388, 286, 194, 299, 92 , 70, 182, + 401, 172, 59, 91, 58, 400, 368, 161, 81, 160, + 264, 171, 80, 389, 390, 378, 379, 193, 298, 69, + 266, 265, 367, 277, 288, 276, 287, 184, 60, 195, + 82, 93, 71, 369, 402, 173, 162, 444, 300, 391, + 98, 76, 278, 61, 267, 374, 135, 411, 167, 102, + 380, 200, 87, 178, 65, 94, 204, 124, 72, 342, + 189, 305, 381, 396, 433, 301, 226, 407, 289, 237, + 113, 215, 185, 128, 309, 403, 116, 320, 196, 331, + 370, 422, 174, 64, 392, 83, 425, 219, 134, 188, + 432, 112, 427, 139, 279, 163, 436, 208, 447, 218, + 236, 229, 97, 294, 385, 230, 166, 268, 177, 443, + 225, 426, 101, 272, 138, 127, 290, 117, 347, 199, + 414, 95, 140, 240, 410, 395, 209, 129, 283, 346, + 105, 241, 437, 86, 308, 448, 203, 345, 186, 107, + 220, 415, 334, 319, 106, 313, 118, 123, 73, 207, + 421, 214, 384, 373, 438, 62, 371, 341, 75, 449, + 168, 323, 164, 242, 416, 324, 304, 197, 335, 404, + 271, 63, 191, 325, 96, 169, 231, 280, 312, 187, + 406, 84, 201, 100, 67, 382, 175, 336, 202, 330, + 269, 393, 376, 383, 293, 307, 409, 179, 285, 314, + 302, 372, 398, 190, 180, 89, 99, 103, 232, 78, + 88, 77, 136, 387, 165, 198, 394, 125, 176, 428, + 74, 375, 238, 227, 66, 273, 282, 141, 306, 412, + 114, 85, 130, 348, 119, 291, 296, 386, 233, 397, + 303, 405, 284, 445, 423, 221, 210, 205, 450, 108, + 274, 434, 216, 343, 337, 142, 243, 321, 408, 451, + 310, 292, 120, 109, 281, 439, 270, 429, 332, 295, + 418, 211, 315, 222, 326, 131, 430, 244, 327, 349, + 417, 316, 143, 338, 440, 234, 110, 212, 452, 245, + 121, 419, 350, 223, 132, 441, 328, 413, 317, 339, + 126, 104, 137, 446, 344, 239, 435, 115, 333, 206, + 322, 217, 228, 424, 453, 311, 351, 111, 442, 224, + 213, 122, 431, 340, 235, 246, 133, 144, 420, 329, + 318 +}; + +static Word16 sort_2385[477] = { + 0, 4, 6, 145, 251, 360, 466, 7, 5, 3, + 47, 48, 49, 50, 51, 262, 263, 264, 265, 266, + 146, 252, 361, 467, 151, 257, 366, 472, 148, 254, + 363, 469, 149, 255, 364, 470, 156, 371, 150, 256, + 365, 471, 147, 253, 362, 468, 52, 2, 1, 157, + 372, 267, 19, 21, 12, 17, 18, 20, 16, 25, + 13, 10, 14, 24, 23, 22, 26, 8, 15, 53, + 268, 31, 152, 153, 154, 155, 258, 259, 260, 261, + 367, 368, 369, 370, 473, 474, 475, 476, 158, 373, + 9, 33, 11, 159, 374, 54, 269, 28, 27, 160, + 375, 34, 35, 29, 46, 32, 30, 55, 270, 37, + 36, 39, 38, 40, 161, 376, 41, 42, 43, 44, + 45, 56, 162, 271, 377, 185, 196, 174, 79, 57, + 411, 90, 163, 305, 389, 378, 283, 68, 187, 400, + 294, 198, 307, 92, 70, 186, 413, 176, 59, 91, + 58, 412, 380, 165, 81, 164, 272, 175, 80, 401, + 402, 390, 391, 197, 306, 69, 274, 273, 379, 285, + 296, 284, 295, 188, 60, 199, 82, 93, 71, 381, + 414, 177, 166, 456, 308, 403, 98, 76, 286, 61, + 275, 386, 135, 423, 171, 102, 392, 204, 87, 182, + 65, 94, 208, 124, 72, 350, 193, 313, 393, 408, + 445, 309, 230, 419, 297, 241, 113, 219, 189, 128, + 317, 415, 116, 328, 200, 339, 382, 434, 178, 64, + 404, 83, 437, 223, 134, 192, 444, 112, 439, 139, + 287, 167, 448, 212, 459, 222, 240, 233, 97, 302, + 397, 234, 170, 276, 181, 455, 229, 438, 101, 280, + 138, 127, 298, 117, 355, 203, 426, 95, 140, 244, + 422, 407, 213, 129, 291, 354, 105, 245, 449, 86, + 316, 460, 207, 353, 190, 107, 224, 427, 342, 327, + 106, 321, 118, 123, 73, 211, 433, 218, 396, 385, + 450, 62, 383, 349, 75, 461, 172, 331, 168, 246, + 428, 332, 312, 201, 343, 416, 279, 63, 195, 333, + 96, 173, 235, 288, 320, 191, 418, 84, 205, 100, + 67, 394, 179, 344, 206, 338, 277, 405, 388, 395, + 301, 315, 421, 183, 293, 322, 310, 384, 410, 194, + 184, 89, 99, 103, 236, 78, 88, 77, 136, 399, + 169, 202, 406, 125, 180, 440, 74, 387, 242, 231, + 66, 281, 290, 141, 314, 424, 114, 85, 130, 356, + 119, 299, 304, 398, 237, 409, 311, 417, 292, 457, + 435, 225, 214, 209, 462, 108, 282, 446, 220, 351, + 345, 142, 247, 329, 420, 463, 318, 300, 120, 109, + 289, 451, 278, 441, 340, 303, 430, 215, 323, 226, + 334, 131, 442, 248, 335, 357, 429, 324, 143, 346, + 452, 238, 110, 216, 464, 249, 121, 431, 358, 227, + 132, 453, 336, 425, 325, 347, 126, 104, 137, 458, + 352, 243, 447, 115, 341, 210, 330, 221, 232, 436, + 465, 319, 359, 111, 454, 228, 217, 122, 443, 348, + 239, 250, 133, 144, 432, 337, 326 +}; + +static Word16 sort_SID[35] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34 +}; + +/* pointer table for bit sorting tables */ +static Word16 *sort_ptr[16] = { sort_660, sort_885, sort_1265, sort_1425, sort_1585, sort_1825, sort_1985, sort_2305, + sort_2385, sort_SID, NULL, NULL, NULL, NULL, NULL, NULL}; + + + + diff --git a/media/libstagefright/codecs/amrwbenc/inc/oper_32b.h b/media/libstagefright/codecs/amrwbenc/inc/oper_32b.h new file mode 100644 index 0000000000000000000000000000000000000000..4159d84aade321fbe33e65ac0a61dbd181ac2b25 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/oper_32b.h @@ -0,0 +1,31 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/* Double precision operations */ +/* $Id$ */ + +#ifndef __OPER_32B_H__ +#define __OPER_32B_H__ + +void VO_L_Extract (Word32 L_32, Word16 *hi, Word16 *lo); +Word32 L_Comp (Word16 hi, Word16 lo); +Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2); +Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n); +Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo); + +#endif //__OPER_32B_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/p_med_o.h b/media/libstagefright/codecs/amrwbenc/inc/p_med_o.h new file mode 100644 index 0000000000000000000000000000000000000000..27c4c7e90894cc68d18a430d0dcfb5fc60eb30a0 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/p_med_o.h @@ -0,0 +1,52 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*--------------------------------------------------------------------------* + * P_MED_O.H * + *--------------------------------------------------------------------------* + * Median open-loop lag search * + *--------------------------------------------------------------------------*/ + +#ifndef __P_MED_O_H__ +#define __P_MED_O_H__ + +Word16 Pitch_med_ol( /* output: open loop pitch lag */ + Word16 wsp[], /* input : signal used to compute the open loop pitch */ + /* wsp[-pit_max] to wsp[-1] should be known */ + Word16 L_min, /* input : minimum pitch lag */ + Word16 L_max, /* input : maximum pitch lag */ + Word16 L_frame, /* input : length of frame to compute pitch */ + Word16 L_0, /* input : old_ open-loop pitch */ + Word16 * gain, /* output: normalize correlation of hp_wsp for the Lag */ + Word16 * hp_wsp_mem, /* i:o : memory of the hypass filter for hp_wsp[] (lg=9) */ + Word16 * old_hp_wsp, /* i:o : hypass wsp[] */ + Word16 wght_flg /* input : is weighting function used */ + ); + +Word16 Med_olag( /* output : median of 5 previous open-loop lags */ + Word16 prev_ol_lag, /* input : previous open-loop lag */ + Word16 old_ol_lag[5] + ); + +void Hp_wsp( + Word16 wsp[], /* i : wsp[] signal */ + Word16 hp_wsp[], /* o : hypass wsp[] */ + Word16 lg, /* i : lenght of signal */ + Word16 mem[] /* i/o : filter memory [9] */ + ); + +#endif //__P_MED_O_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab b/media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab new file mode 100644 index 0000000000000000000000000000000000000000..14bd1d5db535a22ec27a311f28008fc0ad4292e5 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab @@ -0,0 +1,47 @@ + +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*-----------------------------------------------------* + | Table for function Pitch_med_ol() | + *-----------------------------------------------------*/ + + static Word16 corrweight[199]= { + + 10772, 10794, 10816, 10839, 10862, 10885, 10908, 10932, 10955, 10980, + 11004, 11029, 11054, 11079, 11105, 11131, 11157, 11183, 11210, 11238, + 11265, 11293, 11322, 11350, 11379, 11409, 11439, 11469, 11500, 11531, + 11563, 11595, 11628, 11661, 11694, 11728, 11763, 11798, 11834, 11870, + 11907, 11945, 11983, 12022, 12061, 12101, 12142, 12184, 12226, 12270, + 12314, 12358, 12404, 12451, 12498, 12547, 12596, 12647, 12699, 12751, + 12805, 12861, 12917, 12975, 13034, 13095, 13157, 13221, 13286, 13353, + 13422, 13493, 13566, 13641, 13719, 13798, 13880, 13965, 14053, 14143, + 14237, 14334, 14435, 14539, 14648, 14761, 14879, 15002, 15130, 15265, + 15406, 15554, 15710, 15874, 16056, 16384, 16384, 16384, 16384, 16384, + 16384, 16384, 16056, 15874, 15710, 15554, 15406, 15265, 15130, 15002, + 14879, 14761, 14648, 14539, 14435, 14334, 14237, 14143, 14053, 13965, + 13880, 13798, 13719, 13641, 13566, 13493, 13422, 13353, 13286, 13221, + 13157, 13095, 13034, 12975, 12917, 12861, 12805, 12751, 12699, 12647, + 12596, 12547, 12498, 12451, 12404, 12358, 12314, 12270, 12226, 12184, + 12142, 12101, 12061, 12022, 11983, 11945, 11907, 11870, 11834, 11798, + 11763, 11728, 11694, 11661, 11628, 11595, 11563, 11531, 11500, 11469, + 11439, 11409, 11379, 11350, 11322, 11293, 11265, 11238, 11210, 11183, + 11157, 11131, 11105, 11079, 11054, 11029, 11004, 10980, 10955, 10932, + 10908, 10885, 10862, 10839, 10816, 10794, 10772, 10750, 10728}; + + + diff --git a/media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab b/media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab new file mode 100644 index 0000000000000000000000000000000000000000..1a0deee4b6be9cee8176551bf3a7197cbcdcc124 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab @@ -0,0 +1,228 @@ + +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*------------------------------------------------------* + * Tables for function q_gain2() * + * * + * g_pitch(Q14), g_code(Q11) * + * * + * pitch gain are ordered in table to reduce complexity * + * during quantization of gains. * + *------------------------------------------------------*/ + +#define nb_qua_gain6b 64 /* Number of quantization level */ +#define nb_qua_gain7b 128 /* Number of quantization level */ + + +static Word16 t_qua_gain6b[64*2] = { + 1566, 1332, + 1577, 3557, + 3071, 6490, + 4193, 10163, + 4496, 2534, + 5019, 4488, + 5586, 15614, + 5725, 1422, + 6453, 580, + 6724, 6831, + 7657, 3527, + 8072, 2099, + 8232, 5319, + 8827, 8775, + 9740, 2868, + 9856, 1465, + 10087, 12488, + 10241, 4453, + 10859, 6618, + 11321, 3587, + 11417, 1800, + 11643, 2428, + 11718, 988, + 12312, 5093, + 12523, 8413, + 12574, 26214, + 12601, 3396, + 13172, 1623, + 13285, 2423, + 13418, 6087, + 13459, 12810, + 13656, 3607, + 14111, 4521, + 14144, 1229, + 14425, 1871, + 14431, 7234, + 14445, 2834, + 14628, 10036, + 14860, 17496, + 15161, 3629, + 15209, 5819, + 15299, 2256, + 15518, 4722, + 15663, 1060, + 15759, 7972, + 15939, 11964, + 16020, 2996, + 16086, 1707, + 16521, 4254, + 16576, 6224, + 16894, 2380, + 16906, 681, + 17213, 8406, + 17610, 3418, + 17895, 5269, + 18168, 11748, + 18230, 1575, + 18607, 32767, + 18728, 21684, + 19137, 2543, + 19422, 6577, + 19446, 4097, + 19450, 9056, + 20371, 14885}; + +static Word16 t_qua_gain7b[128*2] = { + 204, 441, + 464, 1977, + 869, 1077, + 1072, 3062, + 1281, 4759, + 1647, 1539, + 1845, 7020, + 1853, 634, + 1995, 2336, + 2351, 15400, + 2661, 1165, + 2702, 3900, + 2710, 10133, + 3195, 1752, + 3498, 2624, + 3663, 849, + 3984, 5697, + 4214, 3399, + 4415, 1304, + 4695, 2056, + 5376, 4558, + 5386, 676, + 5518, 23554, + 5567, 7794, + 5644, 3061, + 5672, 1513, + 5957, 2338, + 6533, 1060, + 6804, 5998, + 6820, 1767, + 6937, 3837, + 7277, 414, + 7305, 2665, + 7466, 11304, + 7942, 794, + 8007, 1982, + 8007, 1366, + 8326, 3105, + 8336, 4810, + 8708, 7954, + 8989, 2279, + 9031, 1055, + 9247, 3568, + 9283, 1631, + 9654, 6311, + 9811, 2605, + 10120, 683, + 10143, 4179, + 10245, 1946, + 10335, 1218, + 10468, 9960, + 10651, 3000, + 10951, 1530, + 10969, 5290, + 11203, 2305, + 11325, 3562, + 11771, 6754, + 11839, 1849, + 11941, 4495, + 11954, 1298, + 11975, 15223, + 11977, 883, + 11986, 2842, + 12438, 2141, + 12593, 3665, + 12636, 8367, + 12658, 1594, + 12886, 2628, + 12984, 4942, + 13146, 1115, + 13224, 524, + 13341, 3163, + 13399, 1923, + 13549, 5961, + 13606, 1401, + 13655, 2399, + 13782, 3909, + 13868, 10923, + 14226, 1723, + 14232, 2939, + 14278, 7528, + 14439, 4598, + 14451, 984, + 14458, 2265, + 14792, 1403, + 14818, 3445, + 14899, 5709, + 15017, 15362, + 15048, 1946, + 15069, 2655, + 15405, 9591, + 15405, 4079, + 15570, 7183, + 15687, 2286, + 15691, 1624, + 15699, 3068, + 15772, 5149, + 15868, 1205, + 15970, 696, + 16249, 3584, + 16338, 1917, + 16424, 2560, + 16483, 4438, + 16529, 6410, + 16620, 11966, + 16839, 8780, + 17030, 3050, + 17033, 18325, + 17092, 1568, + 17123, 5197, + 17351, 2113, + 17374, 980, + 17566, 26214, + 17609, 3912, + 17639, 32767, + 18151, 7871, + 18197, 2516, + 18202, 5649, + 18679, 3283, + 18930, 1370, + 19271, 13757, + 19317, 4120, + 19460, 1973, + 19654, 10018, + 19764, 6792, + 19912, 5135, + 20040, 2841, + 21234, 19833}; + + diff --git a/media/libstagefright/codecs/amrwbenc/inc/q_pulse.h b/media/libstagefright/codecs/amrwbenc/inc/q_pulse.h new file mode 100644 index 0000000000000000000000000000000000000000..baf5525283535177366f972493321b2f420dd28c --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/q_pulse.h @@ -0,0 +1,66 @@ + +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*--------------------------------------------------------------------------* + * Q_PULSE.H * + *--------------------------------------------------------------------------* + * Coding and decoding of algebraic codebook * + *--------------------------------------------------------------------------*/ + +#ifndef __Q_PULSE_H__ +#define __Q_PULSE_H__ + +#include "typedef.h" + +Word32 quant_1p_N1( /* (o) return (N+1) bits */ + Word16 pos, /* (i) position of the pulse */ + Word16 N); /* (i) number of bits for position */ + +Word32 quant_2p_2N1( /* (o) return (2*N)+1 bits */ + Word16 pos1, /* (i) position of the pulse 1 */ + Word16 pos2, /* (i) position of the pulse 2 */ + Word16 N); /* (i) number of bits for position */ + +Word32 quant_3p_3N1( /* (o) return (3*N)+1 bits */ + Word16 pos1, /* (i) position of the pulse 1 */ + Word16 pos2, /* (i) position of the pulse 2 */ + Word16 pos3, /* (i) position of the pulse 3 */ + Word16 N); /* (i) number of bits for position */ + +Word32 quant_4p_4N1( /* (o) return (4*N)+1 bits */ + Word16 pos1, /* (i) position of the pulse 1 */ + Word16 pos2, /* (i) position of the pulse 2 */ + Word16 pos3, /* (i) position of the pulse 3 */ + Word16 pos4, /* (i) position of the pulse 4 */ + Word16 N); /* (i) number of bits for position */ + +Word32 quant_4p_4N( /* (o) return 4*N bits */ + Word16 pos[], /* (i) position of the pulse 1..4 */ + Word16 N); /* (i) number of bits for position */ + +Word32 quant_5p_5N( /* (o) return 5*N bits */ + Word16 pos[], /* (i) position of the pulse 1..5 */ + Word16 N); /* (i) number of bits for position */ + +Word32 quant_6p_6N_2( /* (o) return (6*N)-2 bits */ + Word16 pos[], /* (i) position of the pulse 1..6 */ + Word16 N); /* (i) number of bits for position */ + + +#endif //__Q_PULSE_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab b/media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab new file mode 100644 index 0000000000000000000000000000000000000000..52f0dafb642b5f6d31fbb50d52440dbff8a50063 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab @@ -0,0 +1,347 @@ + +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*-------------------------------------------------------------------* + * qisf_ns.h + *-------------------------------------------------------------------* + * Quantization tables for split by 5 VQ of ISFs for a background noise database + * Version whith no prediction + *-------------------------------------------------------------------*/ + +#define ORDER 16 /* order of linear prediction filter */ +#define ISF_GAP 128 + +#define SIZE_BK_NOISE1 64 +#define SIZE_BK_NOISE2 64 +#define SIZE_BK_NOISE3 64 +#define SIZE_BK_NOISE4 32 +#define SIZE_BK_NOISE5 32 + + +/* means of ISFs */ + static Word16 mean_isf_noise[ORDER] = { + + 478, 1100, 2213, 3267, 4219, 5222, 6198, 7240, + 8229, 9153, 10098, 11108, 12144, 13184, 14165, 3803}; + + +/* 28 bits */ +/*-------------------------------------------------------------------* + * isf codebooks: split-by-5 VQ * + * * + * codebook vector dimension number of vectors * + * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ * + * 1 2 64 * + * 2 3 64 * + * 3 3 64 * + * 4 4 32 * + * 5 4 32 * + *-------------------------------------------------------------------*/ + +/*------------------------------------------------* + * 1st split: isf0 to isf1 + *------------------------------------------------*/ + + + static Word16 dico1_isf_noise[SIZE_BK_NOISE1*2] = { + + -269, -673, + -222, -537, + -233, -430, + -138, -451, + -212, -331, + -192, -241, + -87, -231, + -191, -128, + -70, -106, + -164, -6, + 74, -179, + 27, -33, + -102, 74, + -162, 115, + -94, 172, + -6, 130, + -143, 234, + 14, 218, + -65, 270, + 88, 182, + -124, 341, + -44, 381, + 38, 335, + 117, 274, + -112, 454, + 74, 431, + -5, 488, + 175, 384, + -83, 561, + 122, 529, + 21, 601, + 229, 481, + 231, 303, + 226, 608, + 300, 372, + 210, 187, + 306, 265, + 328, 473, + 382, 331, + 371, 132, + 139, 58, + 365, 21, + 250, -82, + 443, 218, + 483, 110, + 426, 415, + 579, 222, + 518, 333, + 573, 448, + 455, 529, + 685, 329, + 332, 580, + 595, 593, + 468, 645, + 762, 517, + 326, 709, + 485, 793, + 130, 684, + 671, 737, + 354, 876, + 88, 806, + -65, 706, + -35, 1016, + 266, 1123}; + + +/*------------------------------------------------* + * 2nd split: isf2 to isf4 + *------------------------------------------------*/ + + static Word16 dico2_isf_noise[SIZE_BK_NOISE2*3] = { + + -824, -884, -949, + -805, -456, -418, + -442, -438, -541, + -217, -578, -793, + -168, -444, -582, + -287, -492, -274, + -552, -297, -300, + -163, -333, -358, + -370, -232, -232, + -175, -358, -159, + -381, -21, -357, + -184, -159, -162, + -53, -191, -280, + 18, -267, -215, + -138, 61, -283, + 71, -95, -294, + 13, -156, -546, + 0, -83, -79, + 44, 97, -316, + 178, -52, -213, + 222, -261, -422, + 237, -118, -44, + 141, 145, -132, + 363, 81, -287, + 213, 65, 34, + -107, 94, -5, + 91, -29, 126, + -355, 51, -41, + -219, -76, 145, + -63, 100, 244, + -719, 44, 27, + -572, -124, 155, + -423, 133, 315, + -917, 71, 224, + -268, 318, 131, + -93, -190, 420, + -97, 122, 491, + -79, 317, 355, + 130, 100, 325, + 86, -293, 210, + 133, 258, 161, + 176, -73, 465, + 195, 300, 384, + 348, 22, 221, + 376, 183, 409, + 377, 286, 202, + 242, 213, 659, + 257, 565, 248, + 344, 408, -76, + 405, 440, 509, + 612, 385, 379, + 536, 607, 216, + -56, 582, 192, + 100, 517, 567, + -365, 448, 445, + 728, 347, 10, + 505, 357, 759, + 636, 582, 658, + 335, 517, 852, + 378, 809, 572, + -195, 878, 829, + 529, 707, 987, + 918, 726, 392, + 1250, 997, 1063}; + +/*------------------------------------------------* + * 3rd split: isf5 to isf7 + *------------------------------------------------*/ + + static Word16 dico3_isf_noise[SIZE_BK_NOISE3*3] = { + + -805, -838, -774, + -522, -627, -828, + -477, -486, -603, + -295, -481, -634, + -366, -384, -393, + -186, -414, -396, + -237, -394, -106, + -252, -202, -275, + -61, -177, -442, + -84, -198, -199, + -179, -125, -31, + -72, -47, -163, + -298, -220, 215, + -64, -168, 251, + -133, 156, -59, + -30, -2, 127, + 54, 66, -61, + -233, 21, 251, + 209, -50, 32, + 33, 194, 136, + -117, -18, 475, + 202, 46, 309, + 256, 185, 53, + 35, 200, 390, + 200, 263, 242, + -216, 302, 294, + 128, 358, 0, + 19, 431, 287, + 224, 447, 280, + 367, 165, 213, + 397, 314, 319, + 383, 379, 75, + 277, 325, 462, + 394, 505, 334, + 251, 98, -213, + 450, 153, 448, + 565, 226, 76, + 470, 383, 502, + 635, 390, 278, + 237, 135, 620, + 342, 401, 649, + 331, 551, 518, + 130, 418, 592, + 531, 306, 737, + 729, 389, 580, + 497, 557, 699, + 296, 383, 874, + 283, 624, 759, + 126, 622, 476, + 559, 595, 472, + 382, 770, 616, + 719, 613, 745, + 540, 639, 928, + 517, 826, 801, + 684, 811, 604, + 752, 786, 857, + 933, 661, 350, + 694, 450, 1061, + 562, 911, 1051, + 824, 813, 1104, + 758, 1047, 882, + 1140, 917, 889, + 1039, 1246, 1426, + 1483, 1666, 1876}; + +/*------------------------------------------------* + * 4th split: isf8 to isf11 + *------------------------------------------------*/ + + static Word16 dico4_isf_noise[SIZE_BK_NOISE4*4] = { + + -776, -854, -891, -920, + -552, -610, -663, -741, + -321, -370, -476, -565, + 274, -160, -456, 201, + 265, 67, -160, -306, + -8, -210, 79, 272, + 163, 236, 307, 308, + 578, 317, 64, 298, + -9, 197, 342, 620, + 343, 232, 314, 622, + 173, 149, 548, 527, + 356, 370, 481, 376, + 135, 444, 488, 556, + 391, 471, 487, 653, + 228, 424, 576, 835, + 422, 372, 722, 682, + 295, 673, 693, 635, + 539, 596, 590, 449, + 475, 618, 659, 818, + 735, 517, 491, 673, + 602, 346, 257, 877, + 625, 635, 849, 720, + 727, 818, 698, 595, + 653, 481, 690, 1139, + 814, 762, 704, 908, + 507, 747, 898, 936, + 848, 855, 924, 785, + 646, 1037, 882, 795, + 772, 845, 1024, 1151, + 1133, 983, 818, 921, + 940, 1068, 1252, 1302, + 1588, 1767, 1718, 1513}; + +/*------------------------------------------------* + * 5th split: isf12 to isf15 + *------------------------------------------------*/ + + static Word16 dico5_isf_noise[SIZE_BK_NOISE5*4] = { + -810, -879, -945, -254, + 248, 184, 671, 128, + 288, 703, 918, 99, + 658, 558, 662, 219, + 552, 585, 910, 208, + 559, 804, 759, 119, + 606, 774, 921, -139, + 782, 761, 748, 208, + 756, 708, 983, 56, + 544, 864, 1010, 152, + 737, 698, 987, 299, + 771, 924, 879, 103, + 536, 785, 961, 405, + 667, 916, 801, 328, + 738, 705, 773, 439, + 823, 871, 992, 355, + 640, 1004, 1052, 369, + 724, 822, 949, 597, + 415, 655, 729, 482, + 1009, 896, 793, 363, + 908, 803, 687, -25, + 1016, 838, 1011, 189, + 947, 1112, 942, 222, + 914, 1049, 981, 527, + 956, 987, 1011, -120, + 781, 1049, 1121, 92, + 1178, 1053, 884, 47, + 1123, 1059, 1182, 118, + 933, 972, 1277, 357, + 1109, 918, 1101, 503, + 1039, 1286, 1220, 317, + 1351, 1207, 1010, 326}; + diff --git a/media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab b/media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab new file mode 100644 index 0000000000000000000000000000000000000000..4d869a473b43159a65d2bb4ef744016ddc8f8d1d --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab @@ -0,0 +1,1360 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*-------------------------------------------------------------------* + * qpisf_2s.h + *-------------------------------------------------------------------* + * Quantization tables for two-stage of ISFs (split by 2 in 1st stage) + * Version whith prediction MU = 0.25 + *-------------------------------------------------------------------*/ + +#define ORDER 16 /* order of linear prediction filter */ +#define ISF_GAP 128 /* 50 Hz */ +#define N_SURV 4 + +#define SIZE_BK1 256 +#define SIZE_BK2 256 +#define SIZE_BK21 64 +#define SIZE_BK22 128 +#define SIZE_BK23 128 +#define SIZE_BK24 32 +#define SIZE_BK25 32 + +#define SIZE_BK21_36b 128 +#define SIZE_BK22_36b 128 +#define SIZE_BK23_36b 64 + +/* means of ISFs */ +static Word16 mean_isf[ORDER] = { + + 738, 1326, 2336, 3578, 4596, 5662, 6711, 7730, + 8750, 9753, 10705, 11728, 12833, 13971, 15043, 4037}; + +/* 46 bits */ +/*-------------------------------------------------------------------* + * isf codebooks: two-stage VQ with split-by-5 in 2nd stage * + * * + * codebook vector dimension number of vectors * + * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ * + * 1_1 9 256 * + * 1_2 7 256 * + * 2_1 3 64 * + * 2_2 3 128 * + * 2_3 3 128 * + * 2_4 3 32 * + * 2_5 4 32 * + *-------------------------------------------------------------------*/ + +/*------------------------------------------------* + * 1st stage codebook; 1st split: isf0 to isf8 + *------------------------------------------------*/ + +static Word16 dico1_isf[SIZE_BK1*9] = { + + 579, 1081, 1035, 390, 3, -263, -198, -82, 38, + 18, -68, -12, 313, 761, 405, 249, 111, -76, + 740, 1263, 1292, 1006, 997, 1019, 1017, 976, 923, + -91, 827, 948, 648, 613, 535, 522, 490, 421, + 41, -44, -281, -472, 652, 534, 193, 135, -90, + 41, -121, -356, -60, 663, 307, 61, -48, -344, + 557, 946, 1049, 867, 846, 990, 1112, 1262, 1241, + -118, -204, 328, 512, 870, 793, 610, 402, 186, + 156, 293, 74, -338, -475, -897, -594, -161, -497, + 226, 131, -138, 307, 169, -271, -164, -387, -624, + 62, -32, -61, -252, -541, -828, -1027, -523, -662, + 102, -61, 141, 112, -270, -251, -541, 25, -150, + 6, -132, -356, -686, -96, -322, -522, -31, -326, + -36, -209, -521, -229, 307, -132, -5, -99, -384, + 60, -51, -237, -668, -973, -407, -708, -75, -172, + 26, -138, -266, 111, -302, 43, -278, -356, -359, + 570, 822, 496, -154, -312, -92, 137, 279, 371, + -146, 368, 409, 68, 6, 77, 167, 202, 162, + 633, 898, 996, 756, 662, 683, 783, 909, 996, + -103, 294, 607, 415, 483, 462, 480, 431, 408, + -120, -338, -612, -524, 584, 331, 92, 433, 276, + -178, -293, -154, -41, 269, 100, -9, 213, 160, + 830, 736, 278, 820, 1254, 686, 712, 1039, 473, + -218, -304, 463, 454, 397, 273, 202, 286, 273, + -232, 7, 6, -388, -472, -427, -378, -167, -100, + -294, -183, 134, -47, 101, -88, -84, -117, -3, + 57, 17, -202, -634, -989, -1119, -533, 176, -36, + 120, -28, 23, 111, -319, 318, -22, -77, 266, + -271, -464, -434, -658, -640, -385, -385, -99, -69, + -198, -259, -266, -44, -39, -139, -137, 171, 66, + 9, -145, -377, -846, -1000, -111, -325, 342, 135, + -81, -286, -380, 192, -57, 307, 76, -24, -140, + 677, 702, 247, 56, 249, 141, -105, -236, -99, + 36, -39, -69, 348, 198, -93, 322, 91, -72, + 503, 885, 1508, 1307, 1282, 1172, 1119, 1209, 1061, + 416, 719, 989, 1227, 1001, 1052, 954, 741, 1044, + -127, -376, -657, 139, 623, 223, 501, 306, 220, + -113, -384, -796, 504, 438, 85, 213, -83, -194, + 585, 1132, 1233, 1091, 1247, 1433, 1512, 1448, 1314, + -174, -422, 7, 1155, 1089, 1182, 1003, 945, 806, + 8, -126, -317, -103, -351, -695, -98, -268, -537, + 33, -103, -290, 167, -39, -407, 44, -208, -375, + 104, -23, -64, -291, -637, -851, -1084, -61, -112, + -75, -306, -434, 218, -148, -354, -680, -133, -216, + -121, -377, -718, -97, -130, -361, -156, -379, -599, + -56, -254, -586, 235, 157, -214, 11, -260, -149, + -124, -267, -397, -580, -593, -527, -805, -385, 346, + -193, -440, -708, -351, -141, -255, -499, -147, -185, + 448, 660, 494, 208, 509, 461, 338, 291, 149, + -223, 88, 335, 159, 212, 191, 286, 308, 205, + -31, 469, 803, 659, 619, 658, 843, 987, 1113, + -171, -242, 514, 362, 295, 524, 552, 694, 585, + -64, -308, -448, -21, 284, 786, 446, 289, 92, + -218, -390, -7, 169, 206, 330, 352, 408, 358, + -36, 702, 959, 859, 861, 1115, 1269, 1357, 1305, + -133, -341, -65, 678, 417, 440, 486, 518, 780, + 33, -44, -191, -344, -461, -755, -201, 217, -31, + -353, -547, -44, 123, -61, -68, -79, 29, 60, + 73, -57, -406, -766, -1243, -1203, 240, 400, 165, + -73, -282, -601, -213, -171, -375, 332, 35, -103, + -29, -207, -553, -476, -638, -908, 172, -22, -135, + -192, -239, -164, -103, -111, -47, 153, 125, 110, + -1, -203, -570, -1030, -1424, -535, 155, 1, 147, + -333, -653, -865, -197, -158, -21, -44, 95, 108, + 389, 588, 490, 33, -237, -524, -628, -136, -260, + 40, -177, -462, 453, 862, 380, 131, -130, -405, + 842, 1678, 1841, 1549, 1474, 1256, 1082, 905, 742, + 370, 1216, 1768, 1633, 1212, 636, 22, -330, 71, + -76, -281, -741, -742, 898, 619, 277, 71, -222, + -32, -265, -556, -25, 994, 682, 305, 126, -165, + 73, 738, 893, 968, 993, 1768, 2273, 1840, 1391, + -69, -349, -585, 234, 1158, 903, 626, 510, 251, + -1, -99, -272, -210, -603, -351, -540, -811, -383, + -16, -230, -504, 410, 149, -205, -343, -651, -639, + 103, -9, -227, -205, -562, -781, -1079, -1208, -156, + 143, 63, -135, -67, -317, -602, -784, -1154, -640, + -144, -391, -674, -622, -200, -254, -660, -947, -395, + -40, -250, -625, 27, 543, 94, -131, -386, -673, + -123, -371, -757, -451, -564, -614, -415, -711, -35, + -116, -309, -593, -268, 239, -33, -338, -650, -135, + 94, 251, 554, 57, -312, -423, -154, -57, 235, + -268, -71, 381, 114, -44, -87, 125, 173, 133, + 1513, 1714, 1238, 534, 276, 315, 461, 459, 508, + -131, -19, 1149, 670, 486, 356, 309, 369, 296, + -223, -501, -899, -722, -70, 6, 131, 310, 394, + -99, -303, -517, 249, 64, -53, 135, -11, 453, + -147, -399, -730, -401, 817, 738, 802, 749, 575, + -154, -435, -739, 800, 593, 366, 529, 318, 326, + -224, 45, -39, -387, -515, -518, -608, -384, -321, + -315, -377, 143, -101, -113, -377, -177, -144, -12, + 117, 40, -239, -651, -1051, -581, -737, -990, -328, + 26, -50, -157, -23, -453, -283, -531, -546, 192, + -252, -501, -743, -589, -627, -499, -328, -118, -72, + -324, -494, -244, -306, -144, -177, -262, -135, -78, + -36, -234, -519, -961, -1290, -314, -479, -371, -45, + -95, -292, -535, -8, -300, 112, -164, -277, 198, + -99, -128, 880, 836, 579, 351, 23, -95, -217, + -27, -258, 124, 1011, 597, 425, 144, 7, -73, + 421, 1293, 1640, 1623, 1742, 1617, 1499, 1284, 1006, + -95, 752, 1680, 1569, 1618, 1436, 1200, 980, 712, + -69, -300, -683, -435, 1132, 899, 504, 332, 109, + -74, -323, -637, 563, 1074, 608, 371, 105, -49, + -78, 831, 1194, 1110, 1378, 1481, 1492, 1365, 1217, + -259, -121, 1440, 1334, 1628, 1490, 1438, 1223, 933, + -82, -306, -613, -222, -378, -675, -545, -671, -845, + 53, -124, -347, 422, 52, -125, -270, -529, 9, + 79, -89, -320, -662, -999, -1199, -1243, -676, -297, + -68, -273, -611, 137, -146, -397, -627, -845, -220, + -112, -346, -797, -826, 234, -132, -188, -278, -522, + -159, -405, -734, -419, 293, 74, -167, -167, 184, + -153, -437, -833, -1080, -336, -472, -561, -340, -253, + -169, -423, -820, -904, -131, -19, -346, -604, 31, + 33, -31, 312, 62, -148, 49, -59, 564, 486, + -306, -333, 194, -44, 67, 72, 147, 205, 243, + -207, -49, 1360, 983, 969, 991, 1014, 1110, 973, + -211, -172, 883, 627, 711, 674, 705, 798, 746, + -88, -325, -763, -974, 687, 908, 514, 382, 172, + -292, -612, -805, 63, 131, 270, 259, 352, 348, + -235, -84, 955, 818, 1120, 1289, 1559, 1480, 1285, + -180, -461, -614, 657, 691, 745, 854, 783, 713, + -97, -309, -477, -614, -777, -734, -768, -526, -472, + -344, -476, -35, -169, 49, -77, -150, -240, -141, + -52, -268, -639, -919, -1278, -1113, -342, -333, -151, + -68, -242, -585, -73, -209, -478, -159, -429, 133, + -197, -499, -1005, -1268, -272, -224, -105, -67, 17, + -363, -618, -414, -116, -62, 20, 10, 116, 108, + -195, -475, -906, -1260, -891, -441, -277, -142, -28, + -226, -519, -950, -700, -275, -266, -116, -105, 82, + 404, 511, 520, 327, 17, -194, -333, -536, -586, + -114, -130, 276, 237, 204, 342, 135, -16, -111, + 670, 1208, 1168, 860, 742, 601, 528, 403, 309, + 397, 621, 966, 752, 579, 398, 400, 329, 252, + 191, 180, -137, -467, 272, 106, -95, 17, -192, + -80, -290, -626, 194, 598, 196, 21, -281, 77, + 510, 864, 1108, 807, 939, 902, 925, 717, 481, + 137, 367, 534, 764, 670, 382, 296, 153, 84, + 303, 497, 144, -85, -125, -539, -482, -464, -764, + 233, 347, 68, -147, 169, -210, -242, -226, -482, + 307, 422, 154, -175, -386, -722, -724, -904, -1015, + 309, 308, 160, -60, -470, -420, -598, -791, -219, + 68, 121, -137, -560, -146, -446, -515, -494, -729, + 130, 53, -227, 46, 474, 32, -161, -192, -490, + 213, 164, -71, -465, -876, -161, -456, -587, -48, + 218, 117, 39, 177, -194, -88, -226, -418, 50, + 210, 547, 569, 279, 121, -44, -50, 10, -84, + 58, 140, 182, -5, 267, 117, 106, 211, 198, + 539, 835, 913, 719, 617, 544, 591, 565, 642, + 153, 559, 872, 460, 222, 108, 188, 180, 183, + 158, 119, 284, -153, -271, 229, 87, 110, -57, + -183, 82, 118, 21, 13, 40, 118, 191, 185, + 162, 889, 654, 108, -34, 244, 488, 561, 532, + 163, 56, 609, 341, 50, 329, 68, 266, 218, + 100, 206, 18, -304, -107, -436, -487, -65, -306, + -86, 154, 134, -30, -45, -73, -104, -80, -96, + 245, 330, 10, -440, -849, -1082, 79, 40, -265, + 196, 372, 272, -181, -493, -389, 275, 80, -59, + 2, -12, -246, -505, -100, -436, 21, -187, -431, + -221, -48, 36, -271, -186, -147, -109, 26, 71, + 213, 140, 72, -351, -620, -84, -363, 69, 46, + 91, 167, -3, -95, -99, -105, -48, 114, 147, + 259, 249, 172, 607, 406, 52, 59, -189, -320, + 115, -85, -54, 574, 128, 226, -59, -253, 130, + -62, 1033, 1308, 1035, 1127, 1098, 1029, 961, 823, + 39, 364, 757, 940, 728, 660, 659, 583, 770, + -115, -338, -760, -471, 394, 37, 441, 178, 6, + -57, -305, -525, 796, 453, 188, -4, -114, 248, + 71, 444, 797, 731, 1096, 1157, 1222, 1029, 811, + 135, 359, 551, 425, 749, 815, 874, 704, 502, + 132, 247, 0, -206, -449, -750, -258, -514, -633, + 248, 249, 91, 121, -195, -499, -90, -282, -435, + 78, 20, -277, -623, -983, -1224, -415, -458, -639, + 347, 509, 208, -179, -464, -728, -76, -237, -486, + -103, -343, -756, -713, -265, -609, -191, -398, -636, + -121, -383, -749, 567, 252, -36, -354, -417, -50, + 204, 100, -149, -650, -1081, -47, -7, -263, 111, + -46, -180, -267, -324, -562, -394, -692, 398, 292, + 482, 670, 683, 624, 442, 165, 116, 36, -149, + 108, 247, 291, 247, 355, 122, 109, 224, 296, + -14, 945, 990, 801, 755, 815, 847, 913, 892, + 292, 349, 725, 482, 388, 329, 429, 620, 667, + -34, 197, 213, -127, 84, 494, 620, 575, 375, + 126, 207, 172, 167, 362, 202, 296, 395, 455, + -6, 250, 539, 467, 636, 801, 1149, 1287, 1118, + 27, 240, 369, 280, 440, 411, 634, 892, 953, + 159, 170, -58, -395, -797, -690, 77, -211, -334, + -5, -28, -13, -74, -335, -603, 300, 88, -205, + 82, -33, -364, -698, -1203, -1153, 110, -146, -289, + 113, 1, -243, -588, -994, -496, 414, 160, 42, + -56, -247, -440, -693, -996, -479, 11, -178, -357, + -151, -353, -327, -211, -340, 141, 65, 425, 453, + 34, -169, -455, -932, -1215, 138, 499, 256, 324, + 68, 139, -15, -547, -478, 17, 306, 502, 481, + -32, -134, 445, 129, -143, -244, -503, -507, -599, + 61, -140, -345, 496, 458, -2, 20, -227, -514, + 394, 1765, 1666, 1339, 1117, 806, 642, 479, 380, + 215, 519, 920, 1053, 1090, 791, 528, 290, 155, + -54, -233, -647, -602, 639, 294, -2, -167, -442, + -78, -315, -791, -113, 820, 403, 158, -116, -356, + 529, 1851, 2003, 1228, 622, -41, -416, 344, 819, + -105, -379, -236, 1224, 893, 749, 568, 356, 214, + -17, -199, -144, 50, -283, -247, -578, -846, -1087, + 69, -11, -381, -206, 209, -284, -387, -416, -716, + 39, -5, -145, -374, -682, -909, -1074, -1169, -1066, + 287, 226, 67, -221, -662, -171, -421, -642, -707, + -132, -348, -538, -448, -20, -4, -354, -748, -933, + 4, -75, -289, -598, 317, 52, -208, -297, -559, + -88, -264, -358, -589, -631, -248, -523, -822, -1071, + 70, -8, 54, -314, -515, 92, -146, -274, -493, + 199, 62, 391, 158, -141, 71, -219, -203, -207, + 152, 40, 329, 162, -29, 48, -149, 108, 127, + 635, 1058, 883, 492, 372, 312, 317, 274, 241, + 267, 722, 1256, 882, 625, 248, 8, -81, -60, + -58, -138, -291, -600, -12, -2, -39, 147, 117, + -107, -345, -513, 459, 76, 92, -272, 388, 262, + 362, 516, 203, -409, -716, -831, -331, 185, 209, + -117, -391, -298, 671, 292, 538, 257, 166, -38, + -102, -319, -194, -283, -573, -262, -579, -219, -444, + -235, 78, 11, -168, -101, -229, -263, -321, -123, + 70, 50, -170, -599, -996, -588, -263, -516, -455, + 394, 363, 229, -136, -538, 21, -183, -348, -201, + -124, -368, -640, -879, -847, -209, -409, -494, -515, + -127, -341, -541, -425, -510, -10, -252, -473, -291, + 84, -69, -201, -676, -868, 103, -311, -132, -320, + 5, -173, -188, -297, -628, 197, -57, 7, -11, + 49, -160, 56, 558, 111, 33, -311, -440, -463, + -1, -246, -307, 862, 453, 139, -170, -355, -232, + 279, 966, 1642, 1478, 1463, 1123, 795, 525, 339, + -197, -38, 1702, 1331, 1252, 950, 692, 504, 426, + -108, -344, -861, -1172, 444, 354, 88, -46, -220, + -53, -321, -494, 1113, 744, 364, 198, -34, -75, + 457, 955, 1177, 1214, 1427, 1457, 1345, 917, 539, + -69, 199, 897, 1140, 1343, 1183, 977, 742, 522, + 122, 44, -269, 27, -155, -562, -307, -590, -773, + 154, 42, -160, 252, -129, -305, -471, -733, -371, + 135, 185, -82, -416, -722, -913, -504, -743, -880, + 149, 214, -84, -329, -680, -835, -426, -661, -81, + -128, -380, -735, -998, -337, 17, -182, -467, -697, + -84, -290, -510, -592, 13, 440, 154, -38, -279, + 70, -61, -246, -727, -1047, -80, -381, -535, -704, + 178, -2, -146, -670, -938, 482, 138, 63, 65, + -11, 15, 772, 443, 142, -20, -209, -126, -161, + -32, -249, 95, 552, 124, 30, -343, 82, -86, + 148, 751, 1515, 1105, 867, 606, 474, 448, 399, + -163, -257, 899, 1097, 906, 751, 502, 390, 294, + -51, -258, -447, -806, -368, 763, 464, 364, 183, + -166, -374, -367, 87, 35, 399, 418, 856, 833, + -205, -310, 588, 778, 785, 1065, 1118, 1245, 1157, + -173, -312, 107, 345, 400, 790, 870, 1113, 1001, + -7, -120, -387, -410, -614, -943, -226, -384, -491, + -203, -288, -51, -331, -90, -178, -408, -573, -338, + 56, -29, -273, -627, -1041, -798, -247, -467, 148, + 66, -2, -205, -205, -575, -349, -57, -352, -58, + -45, -225, -471, -924, -497, 77, -32, 44, -135, + -277, -491, -497, -502, -424, -202, -137, 77, 96, + 26, -179, -469, -1008, -1260, 262, -35, -132, -259, + -66, -232, -447, -533, -789, -191, -100, -267, 364}; + +/*------------------------------------------------* + * 1st stage codebook; 2nd split: isf9 to isf15 + *------------------------------------------------*/ + +static Word16 dico2_isf[SIZE_BK2*7] = { + + 1357, 1313, 1136, 784, 438, 181, 145, + 636, 648, 667, 568, 442, 217, 362, + 427, 440, 674, 524, 332, 117, -417, + 121, 295, 468, 465, 230, 44, -221, + -147, -240, 149, 80, 390, 278, 106, + -418, -556, 552, 511, 235, 144, -95, + 43, 193, 274, 150, 67, 34, -273, + -43, -126, 171, 416, 282, 63, -354, + -372, -86, -344, -108, -94, -182, -89, + -600, -840, -200, 465, 258, -11, -253, + -48, 329, 97, -290, -543, -795, -354, + -570, -117, 187, 10, -133, -416, -76, + -618, -129, -247, -371, 45, -76, 277, + -1022, -1079, 126, 474, 254, 127, 52, + -281, 76, -167, -361, -283, -551, -283, + -119, -52, -1, 134, -32, -204, -415, + 1064, 827, 637, 684, 464, 209, 12, + 482, 416, 449, 371, 335, 294, 194, + 719, 576, 365, 135, 113, 91, -199, + 298, 176, 493, 366, 194, 163, 36, + -35, -236, -259, -36, -4, 99, 152, + -98, -306, -27, 228, 90, 111, -86, + 91, 13, -211, -258, -106, 86, -64, + 73, -35, -57, -31, 162, 35, -192, + -109, -335, -629, -66, -61, -128, 322, + -495, -669, -728, 193, 31, -220, 122, + 324, 95, -89, -91, -409, -710, -154, + 0, -234, 92, 33, -343, -609, -220, + -343, -408, -476, -655, -153, 82, 222, + -490, -745, -255, 49, -48, 135, -127, + 119, -67, -328, -390, -272, -545, -56, + -57, -130, -10, -7, -164, -47, -22, + 984, 1064, 961, 568, 210, -27, 16, + 811, 691, 754, 514, 224, -35, 166, + 662, 704, 618, 386, 57, -211, -257, + 510, 359, 418, 393, 91, -144, -18, + -193, -31, -27, 223, 89, -143, 24, + -112, -98, 471, 319, 185, 3, 175, + 252, 146, -47, 272, 48, -211, -234, + 146, 69, 203, 364, 68, -52, 51, + -259, -478, -697, -349, -758, -501, 63, + -501, -769, -289, 79, -311, -497, -106, + 251, 53, -235, -469, -895, -884, 145, + -416, -551, 140, -133, -523, -775, 44, + -326, -423, -713, -497, -86, -431, 99, + -757, -772, -160, -76, -46, -32, 379, + 85, -35, -200, -401, -663, -1040, -247, + -180, -330, -92, -376, 27, -183, -110, + 1279, 1086, 781, 502, 324, 164, 157, + 682, 466, 449, 277, 146, 28, 409, + 635, 472, 390, 107, -232, -538, -139, + 196, 396, 332, 213, 209, -29, -81, + 150, -95, -312, 76, -77, -320, -50, + 46, 9, 47, 175, 139, 30, 384, + 218, 206, -24, -250, -96, -276, -183, + 26, 119, 38, 14, -4, -133, -52, + -477, -614, -987, -715, -631, -813, 200, + -744, -1009, -1065, -745, -631, -171, 18, + -137, -251, -483, -613, -980, -1203, 12, + -605, -767, -562, -686, -1088, -515, 58, + -202, -428, -782, -1072, -96, -234, -179, + -480, -709, -1070, -897, -131, -92, 321, + -145, -193, -512, -729, -572, -765, -210, + -331, -585, -525, -631, -281, -208, -303, + 1165, 1104, 939, 828, 716, 426, 155, + 6, -109, 820, 778, 415, 113, -27, + 381, 339, 314, 265, 121, -9, -474, + -373, 47, 584, 442, 99, -231, -113, + -496, -38, -285, 262, 305, 170, 4, + -587, -556, 69, 66, 471, 354, 13, + -138, 70, -18, 106, 67, 167, -302, + -445, -141, 185, 191, 151, 83, -133, + -257, -521, -720, -198, 134, -46, -182, + -819, -1168, -777, 512, 359, 95, -113, + 137, -2, -74, -138, -401, -114, -371, + -242, -466, 204, 223, -31, -212, -192, + -532, -637, -466, -686, 256, 277, -139, + -1141, -1244, -381, -75, -54, 14, 88, + -311, 115, -143, -499, -343, 124, -416, + -616, -147, -135, 43, -4, 121, -369, + 835, 783, 641, 390, 355, 350, 64, + 72, 194, 443, 467, 436, 219, 372, + 464, 369, 192, 4, -156, -72, -226, + 57, 206, 303, 205, 188, 101, 265, + -40, -205, -488, -184, 276, 64, -26, + -217, -433, -297, 137, 328, 308, -289, + 378, 81, -308, -465, 57, -37, 227, + -100, 24, -36, -151, 199, 8, 143, + -426, -697, -1059, -133, 388, 161, 321, + -644, -1023, -1271, 39, 66, -123, 70, + 372, 177, -173, -556, -553, -304, -189, + -117, -369, -425, -122, -462, -152, -73, + -649, -850, -1189, -767, 497, 360, 222, + -798, -1139, -1455, -190, 430, 234, 179, + 42, -94, -405, -692, 38, -202, -246, + -169, -366, -290, -88, -64, 32, -292, + 1010, 923, 938, 710, 465, 230, 342, + 217, 300, 1054, 675, 68, -458, -179, + 78, 453, 316, 18, -237, -496, -243, + 167, 21, 424, 215, -91, -303, -170, + -290, -81, -70, -67, 40, 54, -59, + -353, -427, -90, 53, 94, 9, 54, + -28, 318, 283, 15, -240, -58, 79, + -75, -121, 229, 35, 58, 6, -133, + -351, -514, -744, -834, -705, -137, 164, + -1124, -1388, -1055, -230, -73, 40, 36, + -163, -233, -532, -785, -1170, -697, 96, + -788, -959, -246, -430, -624, -165, -8, + -856, -540, -630, -907, -337, -70, 76, + -937, -1042, -659, -733, -208, 199, -26, + -523, 78, -98, -501, -869, -890, -81, + -624, -703, -45, -348, -25, 87, -186, + 1005, 823, 546, 249, 90, -22, 207, + 298, 397, 381, 319, 200, 62, 303, + 473, 379, 133, -247, -632, -441, 75, + 284, 208, 391, 115, -25, 44, 95, + -72, 79, -95, -63, -129, -293, 203, + -164, -349, 115, 122, 69, -1, 378, + 348, 170, 99, 58, -179, -302, 188, + -190, -2, 150, 23, -51, -11, 216, + -615, -863, -1090, -1427, -802, -48, -6, + -961, -1276, -1548, -727, -58, 56, 223, + -124, -255, -561, -988, -1277, -148, -82, + -480, -660, -891, -1191, -1339, -325, 20, + -621, -917, -1296, -1350, 264, 289, 50, + -844, -1022, -1345, -1329, -293, 46, 278, + -260, -468, -829, -1176, -533, -560, -78, + -215, -484, -822, -1233, -791, 15, -138, + 1301, 1317, 1262, 1048, 716, 357, -64, + 578, 824, 925, 802, 630, 362, 102, + 470, 925, 767, 514, 327, 190, -112, + 225, 492, 495, 437, 598, 384, -45, + 43, 82, -42, 175, 519, 342, -64, + -304, -154, 159, 576, 403, 221, 327, + 214, 244, 122, -62, 312, 92, -160, + 218, 208, 310, 268, 306, 323, -199, + -285, -269, -79, -124, -143, -153, 236, + -205, -384, -426, 344, 59, -185, -184, + -272, 247, 126, -210, -518, -468, 78, + -99, -120, 502, 160, -280, -557, 304, + -423, -17, -283, -443, 215, 212, -140, + -564, -684, -228, 510, 361, 130, 323, + -428, 335, 98, -65, 36, -215, -246, + -362, 51, 364, -16, -234, 150, -165, + 914, 883, 751, 653, 676, 464, -153, + 631, 545, 535, 720, 596, 360, -81, + 783, 712, 512, 439, 341, 251, -391, + 497, 417, 249, 372, 295, 173, -193, + 128, -110, -385, 93, 39, 173, -231, + 216, -59, -253, 462, 389, 154, 69, + 455, 270, -4, -337, -49, 233, -322, + 307, 143, 53, 218, 128, 236, -156, + -37, -186, -240, -411, -110, 9, 399, + -140, -365, -628, 258, 380, 214, 277, + 131, 454, 177, -285, -520, 108, -214, + 77, -141, 201, -123, -490, -131, 60, + -14, -194, -521, -741, 273, 362, -33, + -362, -566, -287, -228, 161, 237, 317, + -269, 195, -75, -375, -204, 11, 77, + -128, -264, -156, -223, -475, 265, 27, + 1238, 1147, 916, 689, 432, 210, -280, + 800, 664, 879, 726, 411, 160, -164, + 454, 686, 536, 275, 147, 46, 111, + 303, 486, 512, 355, 241, 181, -69, + 79, 92, 29, 147, 233, 52, 17, + -171, 289, 131, 439, 271, 3, -10, + 413, 241, 144, 174, 155, -2, 14, + 58, 217, 247, 219, 149, 175, -18, + 228, -8, -240, -206, -513, -191, 202, + -96, -272, -454, 33, -300, -575, 46, + -10, -108, -246, -347, -770, -535, 9, + -326, -430, -61, -321, -704, -299, 201, + -1, -280, -603, -419, -185, 18, -36, + -516, -522, -379, -291, -181, -97, 27, + -159, -313, -525, -224, -510, -831, -197, + -292, -459, -59, -310, -562, -143, -351, + 1066, 912, 631, 389, 207, 86, -224, + 596, 512, 596, 505, 314, 122, -48, + 787, 861, 441, -93, -303, 33, -190, + 257, 469, 337, 51, 15, 298, -93, + 295, 73, -119, 25, 36, 23, 108, + -28, -3, -32, 114, 21, 185, 107, + 482, 305, 15, -279, -319, 52, 96, + 226, 46, 115, 72, -136, 133, -125, + 18, -207, -559, -590, -503, -482, 321, + -571, -789, -951, -172, -441, -538, 113, + 181, 14, -310, -641, -1001, -202, 159, + -136, -393, -433, -513, -911, -144, -22, + 72, -265, -706, -954, -159, 53, 332, + -338, -591, -852, -383, -395, 56, 44, + 43, -158, -464, -897, -631, -157, -294, + -161, -128, -328, -573, -483, -125, 11, + 1017, 906, 1051, 1005, 679, 341, -102, + 359, 334, 1567, 1314, 723, 105, 10, + -65, 726, 529, 301, 220, 43, -273, + -510, 436, 719, 566, 358, 179, 114, + -560, 298, 133, -120, 342, 225, 14, + -899, -101, 217, 617, 400, 146, -58, + -41, 352, 82, -196, 39, 121, -167, + -212, 59, 447, 284, 423, 250, -169, + -371, -484, -596, 30, -41, 249, 22, + -372, -650, -794, 477, 445, 216, -79, + -352, 275, 17, -443, -929, 92, 19, + -699, -696, 431, 264, -49, -310, 182, + -978, -217, -430, -400, 101, 261, 72, + -929, -889, -357, -13, 463, 378, 236, + -826, 56, 30, -299, -360, -128, -51, + -878, -299, -111, 75, 65, 36, 3, + 817, 368, -25, 354, 697, 591, -173, + 309, 212, 222, 751, 484, 140, -56, + 593, 379, 70, -8, 258, 180, 110, + 165, -46, 255, 297, 219, 273, 105, + 160, -70, -358, -181, 379, 330, 319, + -238, -369, -198, 740, 580, 319, -143, + 201, 109, -202, -456, 328, 276, -141, + 203, 170, 111, 42, 207, 360, 188, + -345, -399, -513, -233, 650, 422, 81, + -635, -961, -1220, 463, 539, 204, 209, + 202, -25, -194, -498, -787, 193, -143, + -449, -538, 195, -106, -331, 68, 62, + -228, -477, -840, -576, 317, 128, 283, + -671, -937, -807, -114, 391, 335, -62, + 246, 2, -314, -679, -303, 180, -88, + -107, -272, 90, -198, -28, 290, -112, + 885, 1149, 1021, 712, 496, 281, -83, + 269, 492, 787, 643, 347, 70, 124, + 336, 636, 499, 92, -229, -179, 191, + 26, 402, 564, 340, 149, -11, 135, + -440, 561, 470, 204, -72, -186, 140, + -720, 14, 355, 229, 68, -133, 465, + 110, 310, 103, 12, 106, 29, 158, + -178, 113, 161, 142, 121, 115, 27, + -651, -414, -645, -152, -164, -13, -429, + -639, -944, -681, -104, -81, 52, -189, + -663, -164, -316, -683, -954, -205, -83, + -609, -669, -172, -517, -694, 283, -80, + -646, -152, -383, -678, -246, -40, -143, + -747, -796, -745, -390, -98, 43, 275, + -599, -199, -398, -433, -436, -538, 31, + -1107, -568, -376, -265, -126, -21, 1, + 847, 573, 308, 392, 305, 101, 55, + 273, 293, 201, 267, 346, 201, 123, + 727, 480, 226, 2, -65, -138, 164, + 273, 208, 173, 292, 12, 253, 174, + 340, 207, 180, 88, 116, 46, 475, + -460, -166, -30, 13, 110, 173, 396, + 137, 88, 43, -137, -94, 34, 284, + 96, -14, 226, 40, 63, 70, 130, + -467, -735, -1012, -1174, -307, 305, -67, + -612, -920, -1146, -567, -8, 92, -25, + -182, -271, -492, -754, -857, 287, -75, + -494, -787, -689, -683, -709, 137, -326, + -288, -550, -903, -1105, 334, 321, -62, + -354, -653, -834, -445, 1, 377, -152, + -162, -306, -608, -937, -297, 247, -192, + -234, -477, -244, -488, -266, 342, -332}; + +/*---------------------------------------------------* + * 2nd stage codebook; 1st split: isf2_0 to isf2_2 + *---------------------------------------------------*/ + + +static Word16 dico21_isf[SIZE_BK21*3] = { + + 329, 409, 249, + -33, 505, 160, + -29, -14, 582, + -262, 127, 354, + 145, 237, 175, + -152, 245, 122, + 27, 42, 340, + -84, -93, 311, + 285, 222, -156, + 47, -43, -504, + 234, 121, 385, + 104, -317, 45, + 176, 195, 8, + 104, -59, -94, + 177, 53, 192, + -34, -127, 152, + 570, 277, -34, + -67, -329, -639, + -157, -272, 462, + -177, -462, 198, + 322, 179, 115, + -386, 171, 19, + 19, -12, 195, + -120, -252, 201, + 304, 36, -336, + -128, -221, -380, + 171, -185, 296, + -242, -312, 23, + 198, 39, 16, + -3, -177, -111, + 111, -93, 76, + -92, -223, 4, + 177, 406, -44, + -168, 380, -149, + -4, 273, 331, + -420, 513, 277, + 21, 247, 47, + -58, 131, -2, + -3, 134, 180, + -145, 40, 175, + 189, 74, -145, + -27, -45, -325, + 370, -114, -21, + -83, -415, -173, + 77, 95, -51, + -40, -30, -67, + 71, 88, 86, + -35, -98, 14, + 69, 197, -334, + -196, 79, -231, + -348, -137, 218, + -352, -89, -85, + 47, 201, -130, + -165, 37, -15, + -43, 3, 86, + -161, -108, 79, + 83, 21, -237, + -81, -149, -238, + 150, -186, -251, + -186, -249, -162, + -19, 66, -139, + -26, -50, -181, + 24, 11, 0, + -130, -105, -98}; + + + +/*---------------------------------------------------* + * 2nd stage codebook; 2nd split: isf2_3 to isf2_5 + *---------------------------------------------------*/ + + +static Word16 dico22_isf[SIZE_BK22*3] = { + + -127, 310, 42, + -242, 197, 5, + -151, 84, -17, + -214, 127, -149, + -247, -131, 159, + -268, -267, -95, + -217, 1, -79, + -271, -80, -185, + -45, 436, 159, + 165, 199, 391, + -33, 81, 187, + -66, -42, 355, + -298, -57, 343, + -108, -537, 226, + -144, -23, 193, + 176, -402, 87, + 53, 296, 25, + -84, 253, -104, + -58, 105, -126, + -169, 174, -314, + -48, 44, -294, + -164, -417, -242, + -139, 3, -194, + -155, -207, -211, + 119, 322, 213, + 333, 50, 380, + 237, 247, -2, + 466, -16, 201, + 238, -255, -107, + 67, -440, -149, + 122, -88, -139, + 88, -247, -73, + -41, 231, 167, + -62, 155, 16, + -65, 16, 77, + -68, -2, -63, + -151, -300, 160, + -18, -333, 54, + -56, -94, 5, + 2, -190, 14, + 92, 148, 209, + 108, 9, 272, + 108, 35, 110, + 142, -85, 145, + 47, -157, 279, + 3, -320, 246, + 43, -72, 68, + 86, -217, 135, + 36, 140, 79, + 56, 175, -49, + 26, 45, 3, + 73, 55, -101, + 109, -183, -242, + -4, -283, -242, + 48, -68, -48, + -6, -153, -122, + 161, 196, 96, + 232, 80, 190, + 165, 97, 11, + 258, -31, 71, + 267, -77, -91, + 311, -209, 87, + 152, -14, -22, + 150, -149, 9, + -324, 557, 187, + -384, 307, 46, + -251, 27, 77, + -365, 77, -52, + -482, -84, 160, + -424, -515, -64, + -294, -120, -4, + -476, -116, -109, + -97, 318, 365, + 106, 627, 445, + -190, 120, 287, + -146, 65, 619, + -427, 242, 363, + -361, -371, 432, + -347, 102, 168, + -629, 195, -14, + -65, 476, -47, + -297, 320, -168, + -55, 356, -264, + -391, 82, -286, + -51, -31, -556, + -178, -399, -586, + -205, -49, -360, + -343, -238, -337, + 220, 457, 58, + 561, 467, 259, + 340, 270, -168, + 450, 77, -280, + 60, 167, -413, + 133, -252, -492, + 216, 157, -290, + 282, 0, -495, + -226, 293, 183, + -157, 135, 122, + -158, -59, 39, + -133, -118, -97, + -332, -309, 113, + -160, -425, -6, + -149, -211, 24, + -80, -277, -90, + -11, 125, 338, + 130, -71, 465, + 5, -45, 184, + 237, -95, 253, + -139, -197, 297, + -19, -300, 511, + -63, -152, 139, + 250, -289, 336, + 124, 339, -150, + 34, 176, -208, + 171, 166, -116, + 94, 38, -229, + 75, -65, -339, + -78, -205, -385, + 0, -30, -163, + -56, -110, -242, + 321, 244, 194, + 505, 238, -1, + 317, 116, 65, + 309, 88, -74, + 452, -51, -50, + 334, -217, -290, + 211, 41, -152, + 238, -55, -260}; + + +/*---------------------------------------------------* + * 2nd stage codebook; 3rd split: isf2_6 to isf2_8 + *---------------------------------------------------*/ + + +static Word16 dico23_isf[SIZE_BK23*3] = { + + -10, 151, 359, + 136, 298, 223, + 255, -104, 290, + 423, 6, 183, + -270, -269, -98, + -52, -82, 13, + -82, -274, -97, + 90, -246, -72, + -299, -70, 421, + -88, 365, 430, + 187, -318, 381, + 380, 37, 488, + -373, -316, 79, + -308, -101, 5, + -135, -451, 8, + 72, -421, -154, + 180, 170, -121, + 62, 177, -40, + 326, 80, -105, + 248, 263, -5, + -168, -181, -221, + -2, -23, -158, + -14, -149, -121, + 119, -91, -147, + 119, 332, -153, + 49, 303, 34, + 442, -55, -69, + 217, 454, 58, + -359, -187, -375, + -42, 50, -274, + -8, -267, -249, + 85, -86, -346, + -77, -40, 345, + 89, 134, 219, + 156, -80, 160, + 108, 40, 116, + -158, -206, 29, + 5, -32, 175, + -65, -158, 146, + 55, -78, 73, + -114, -222, 353, + -47, 81, 211, + 49, -151, 268, + 105, 4, 302, + -263, -132, 183, + -151, -28, 201, + -177, -307, 166, + 101, -221, 130, + 74, 58, -98, + 32, 44, 13, + 194, 30, -142, + 170, 96, 8, + -136, -119, -91, + -65, 8, -55, + 3, -188, 12, + 45, -63, -49, + 149, -21, -19, + 24, 144, 95, + 254, -22, 60, + 161, 196, 96, + -158, -61, 48, + -70, 33, 82, + -23, -321, 58, + 155, -147, 5, + -364, 328, 77, + -21, 453, 173, + -108, 82, 630, + 367, 263, 208, + -300, -62, -176, + -205, 143, -158, + -169, -410, -264, + 257, -269, -100, + -636, 289, -2, + -292, 627, 173, + -382, -363, 387, + 248, 524, 447, + -521, -111, -107, + -395, 118, -274, + -343, -680, -125, + -172, -447, -663, + 75, 148, -367, + -79, 263, -94, + 249, 148, -286, + 380, 271, -162, + -142, -4, -186, + -57, 111, -125, + -35, -108, -254, + 100, 29, -242, + -80, 303, -264, + -78, 464, -57, + 248, -22, -494, + 661, 662, 44, + -193, -40, -330, + -178, 145, -337, + -90, -199, -400, + -40, -23, -498, + -192, 114, 315, + -41, 244, 190, + 88, -97, 485, + 241, 80, 212, + -246, 40, 87, + -156, 147, 134, + -2, -334, 239, + 308, -203, 110, + -459, 251, 422, + -218, 310, 228, + -86, -346, 654, + 184, 175, 425, + -481, -63, 169, + -349, 117, 188, + -125, -560, 310, + 158, -416, 94, + 46, 171, -192, + -63, 157, 14, + 256, -35, -271, + 322, 123, 53, + -214, 4, -76, + -156, 86, -18, + 128, -197, -232, + 265, -90, -98, + -308, 332, -145, + -131, 308, 58, + 509, 59, -339, + 562, 196, -14, + -378, 100, -47, + -234, 202, 1, + 104, -270, -493, + 319, -210, -325}; + + +/*---------------------------------------------------* + * 2nd stage codebook; 4th split: isf2_9 to isf2_11 + *---------------------------------------------------*/ + +static Word16 dico24_isf[SIZE_BK24*3] = { + + -79, -89, -4, + -171, 77, -211, + 160, -193, 98, + 120, -103, 323, + 32, -22, -129, + 72, 78, -268, + 182, -76, -66, + 309, 99, -145, + -229, -157, -84, + -383, 98, -71, + -90, -352, 12, + -284, -178, 178, + -65, -125, -166, + -87, -175, -351, + 42, -198, -48, + 154, -140, -243, + -77, 18, 108, + -39, 355, 91, + 87, 8, 155, + -4, 158, 239, + 128, 95, -54, + 7, 246, -124, + 258, 15, 89, + 206, 216, 98, + -201, 9, 18, + -312, 233, 204, + -39, -174, 155, + -144, -9, 284, + -57, 70, -69, + -157, 187, 18, + 54, -30, 23, + 24, 135, 55}; + + +/*---------------------------------------------------* + * 2nd stage codebook; 5th split: isf2_12 to isf2_15 + *---------------------------------------------------*/ + +static Word16 dico25_isf[SIZE_BK25*4] = { + + 169, 142, -119, 115, + 206, -20, 94, 226, + -106, 313, -21, 16, + -62, 161, 71, 255, + -89, 101, -185, 125, + 72, -30, -201, 344, + -258, 33, -8, 81, + -104, -154, 72, 296, + 144, -68, -268, -25, + 81, -78, -87, 106, + 22, 155, -186, -119, + -46, -28, 27, 91, + -114, -37, -175, -33, + -94, -222, -189, 122, + -132, -119, -191, -270, + -172, -173, 18, -43, + 279, 135, -42, -128, + 187, -86, 229, -138, + 159, 240, 140, 46, + 69, 25, 227, 77, + 21, 115, 13, 8, + 68, -248, 126, 81, + -150, 137, 207, -9, + -154, -133, 289, 67, + 143, -37, -86, -326, + 180, -32, 19, -23, + 26, 168, 116, -233, + -32, -26, 118, -78, + 3, -8, -45, -115, + 57, -215, -54, -83, + -209, 112, -22, -167, + -91, -151, 168, -262}; + + + + /* 36 bit */ +/*-------------------------------------------------------------------* + * isf codebooks: two-stage VQ with split-by-3 in 2nd stage * + * 1st stage is kept the same as the 46 bit quantizer * + * * + * codebook vector dimension number of vectors * + * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ * + * 1_1 9 256 * + * 1_2 7 256 * + * 2_1 5 128 * + * 2_2 4 128 * + * 2_3 7 64 * + *-------------------------------------------------------------------*/ + +static Word16 dico21_isf_36b[SIZE_BK21_36b*5] = { + + -52, -96, 212, 315, -73, + 82, -204, 363, 136, -197, + -126, -331, 183, 218, 143, + -49, -41, 557, 230, 72, + 2, -73, 163, 377, 221, + 133, 111, 278, 215, -110, + -102, -20, 284, 113, 273, + 84, 319, 290, 18, 85, + -25, -5, 125, 132, -204, + -38, -5, 286, -9, -356, + -140, -256, 92, 117, -189, + -144, 191, 313, 51, -98, + 167, -10, 44, 247, 36, + 381, 197, 238, 74, 6, + 38, -408, 29, -3, -85, + 92, 266, 157, -25, -200, + 161, -121, 70, 84, -140, + -16, -86, 112, -94, -189, + -269, -270, 351, 107, -24, + -68, -67, 492, -103, -155, + -53, -131, 62, 122, 10, + 135, 84, 283, -55, -120, + -12, -219, 331, -81, 167, + 220, -136, 147, -172, -42, + 140, -95, -109, -88, -194, + 0, -2, -4, -33, -381, + -66, -217, 152, -186, -402, + 244, 108, 156, -140, -395, + 113, -136, -196, 110, -24, + 214, 118, 11, -64, -131, + -110, -286, -6, -332, 16, + 94, 97, 79, -291, -205, + -5, -39, -20, 252, -96, + 76, 174, 101, 163, 61, + -69, -239, -55, 399, 6, + -115, 319, 164, 275, 196, + -15, 36, -47, 331, 121, + 226, 209, 271, 325, 184, + 13, -80, -218, 471, 353, + 288, 378, 16, -51, 251, + 174, 116, 52, 149, -279, + 235, 276, 39, 120, -48, + 0, -108, -108, 241, -339, + -93, 534, 45, 33, -87, + 194, 149, -71, 405, -44, + 409, 370, 81, -186, -154, + 25, -102, -448, 124, -173, + 22, 408, -110, -310, -214, + -26, 23, -83, 114, 14, + -110, 164, 52, 223, -82, + 37, -25, -263, 306, -15, + -466, 415, 292, 165, -18, + 29, -19, -171, 155, 182, + 179, 144, -27, 231, 258, + -103, -247, -396, 238, 113, + 375, -154, -109, -4, 156, + 98, 85, -292, -5, -124, + 116, 139, -116, -98, -294, + -14, -83, -278, -117, -378, + 106, 33, -106, -344, -484, + 119, 17, -412, 138, 166, + 384, 101, -204, 88, -156, + -121, -284, -300, -1, -166, + 280, 33, -152, -313, -81, + -37, 22, 229, 153, 37, + -60, -83, 236, -8, -41, + -169, -228, 126, -20, 363, + -235, 17, 364, -156, 156, + -25, -30, 72, 144, 156, + 153, -26, 256, 97, 144, + -21, -37, 48, -65, 250, + 63, 77, 273, -128, 124, + -129, -26, 40, 9, -115, + -6, 82, 38, -90, -182, + -336, -13, 28, 158, 91, + -30, 241, 137, -170, -17, + 146, 14, -11, 33, 61, + 192, 197, 54, -84, 85, + 23, -200, -78, -29, 140, + 122, 237, 106, -341, 136, + -57, -142, -85, -16, -74, + -59, -90, -8, -187, -20, + -211, -267, 216, -179, -110, + -50, -7, 220, -267, -70, + -57, -42, -17, -15, 71, + 32, 21, 63, -137, 33, + -137, -175, 104, -68, 97, + -67, -43, 133, -301, 221, + -116, -200, -81, -92, -272, + -64, -41, -54, -244, -220, + -287, -242, -50, -87, -89, + -245, 236, 102, -166, -295, + 66, 24, -162, -71, 95, + 66, 136, -90, -220, -36, + -98, -161, -222, -188, 29, + -18, 18, -19, -415, 9, + 49, 61, 100, 39, -56, + -111, 82, 135, -31, 52, + -90, -153, -93, 189, 182, + -214, 295, 119, -74, 284, + 2, 137, 37, 47, 182, + 92, 117, 184, -53, 373, + -21, -14, -35, 136, 391, + 146, 129, -164, -28, 333, + 92, 80, -84, 100, -134, + -8, 217, -32, 3, -47, + -151, 251, -215, 142, 92, + -224, 310, -172, -275, 98, + 159, 155, -177, 112, 53, + 205, 27, 8, -240, 192, + 169, 120, -319, -201, 106, + 11, 36, -86, -237, 455, + -109, -154, -163, 174, -55, + -38, 32, -101, -78, -59, + -205, -321, -97, 69, 79, + -310, 44, 18, -185, 34, + -115, -20, -148, -39, 203, + -29, 154, -30, -158, 166, + -45, -131, -317, -24, 363, + -165, -205, -112, -222, 265, + -32, -44, -150, 54, -193, + -6, -38, -255, -169, -115, + -266, 87, -189, -36, -169, + -60, -87, -266, -436, -170, + -68, -81, -278, 24, 38, + -23, -19, -155, -256, 141, + -61, -226, -565, -175, 71, + 9, -29, -237, -515, 263}; + +static Word16 dico22_isf_36b[SIZE_BK22_36b*4] = { + + -298, -6, 95, 31, + -213, -87, -122, 261, + 4, -49, 208, 14, + -129, -110, 30, 118, + -214, 258, 110, -235, + -41, -18, -126, 120, + 103, 65, 127, -37, + 126, -36, -24, 25, + -138, -67, -278, -186, + -164, -194, -201, 78, + -211, -87, -51, -221, + -174, -79, -94, -39, + 23, -6, -157, -240, + 22, -110, -153, -68, + 148, -5, -2, -149, + -1, -135, -39, -179, + 68, 360, -117, -15, + 137, 47, -278, 146, + 136, 260, 135, 65, + 61, 116, -45, 97, + 231, 379, 87, -120, + 338, 177, -272, 3, + 266, 156, 28, -69, + 260, 84, -85, 86, + -266, 154, -256, -182, + -17, -65, -304, -6, + -40, 175, -151, -180, + -27, 27, -87, -63, + 121, 114, -166, -469, + 159, -66, -323, -231, + 214, 152, -141, -212, + 137, 36, -184, -51, + -282, -237, 40, 10, + -48, -235, -37, 251, + -54, -323, 136, 29, + -88, -174, 213, 198, + -390, 99, -63, -375, + 107, -169, -164, 424, + 69, -111, 141, -167, + 74, -129, 65, 144, + -353, -207, -205, -109, + -160, -386, -355, 98, + -176, -493, -20, -143, + -252, -432, -2, 216, + -90, -174, -168, -411, + 13, -284, -229, -160, + -87, -279, 34, -251, + -75, -263, -58, -42, + 420, 53, -211, -358, + 384, -35, -374, 396, + 68, -228, 323, -2, + 167, -307, 192, 194, + 459, 329, -5, -332, + 375, 79, -7, 313, + 282, -124, 200, -92, + 271, -162, -70, 180, + -157, -298, -514, -309, + 58, -163, -546, 18, + 124, -364, 167, -238, + 83, -411, -117, 96, + 140, -112, -388, -624, + 259, -133, -317, 41, + 163, -130, -64, -334, + 226, -165, -124, -110, + -466, -61, 6, 229, + -153, 205, -145, 242, + -159, 48, 195, 148, + -58, 28, 31, 279, + -303, 185, 279, -4, + -61, 197, 59, 86, + -114, 123, 168, -52, + 35, 36, 100, 126, + -407, 102, -77, -40, + -338, -1, -342, 156, + -179, 105, -34, -97, + -185, 84, -35, 108, + -133, 107, -91, -357, + -180, 54, -229, 24, + -44, 47, 47, -182, + -66, 13, 45, 4, + -339, 251, 64, 226, + -42, 101, -350, 275, + -99, 398, 142, 121, + 111, 12, -102, 260, + 0, 505, 260, -94, + 161, 285, -96, 224, + -4, 206, 314, 33, + 167, 139, 88, 204, + -235, 316, -60, -25, + -8, -150, -312, 201, + -36, 292, 61, -104, + -40, 174, -162, 42, + -21, 402, -29, -351, + 21, 152, -360, -93, + 57, 191, 212, -196, + 76, 158, -21, -69, + -328, -185, 331, 119, + -53, 285, 56, 337, + -107, -24, 405, 29, + -18, 137, 272, 277, + -255, 22, 173, -191, + 295, 322, 325, 302, + 21, -27, 332, -178, + 119, 13, 271, 129, + -455, -180, 116, -191, + -227, 62, -148, 524, + -176, -287, 282, -157, + -243, 13, 199, 430, + -59, -49, 115, -365, + 72, -172, -137, 93, + -138, -126, 141, -84, + 5, -124, 38, -20, + -258, 311, 601, 213, + 94, 130, -61, 502, + -1, -157, 485, 313, + 146, -74, 158, 345, + 276, 135, 280, -57, + 490, 252, 99, 43, + 267, -74, 429, 105, + 278, -23, 119, 94, + -542, 488, 257, -115, + -84, -244, -438, 478, + -113, -545, 387, 101, + -95, -306, 111, 498, + 95, 166, 22, -301, + 420, -15, -58, -78, + 270, 29, 122, -282, + 160, -240, 50, -38}; + +static Word16 dico23_isf_36b[SIZE_BK23_36b*7] = { + + 81, -18, 68, -27, -122, -280, -4, + 45, -177, 209, -30, -136, -74, 131, + -44, 101, -75, -88, -48, -137, -54, + -245, -28, 63, -18, -112, -103, 58, + -79, -6, 220, -65, 114, -35, -50, + 109, -65, 143, -114, 129, 76, 125, + 166, 90, -61, -242, 186, -74, -43, + -46, -92, 49, -227, 24, -155, 39, + 67, 85, 99, -42, 53, -184, -281, + 142, -122, 0, 21, -142, -15, -17, + 223, 92, -21, -48, -82, -14, -167, + 51, -37, -243, -30, -90, 18, -56, + 54, 105, 74, 86, 69, 13, -101, + 196, 72, -89, 43, 65, 19, 39, + 121, 34, 131, -82, 25, 213, -156, + 101, -102, -136, -21, 57, 214, 22, + 36, -124, 205, 204, 58, -156, -83, + 83, -117, 137, 137, 85, 116, 44, + -92, -148, -68, 11, -102, -197, -220, + -76, -185, -58, 132, -26, -183, 85, + -7, -31, -2, 23, 205, -151, 10, + -27, -37, -5, -18, 292, 131, 1, + 117, -168, 9, -93, 80, -59, -125, + -182, -244, 98, -24, 135, -22, 94, + 221, 97, 106, 42, 43, -160, 83, + 25, -64, -21, 6, 14, -15, 154, + 126, 15, -140, 150, -10, -207, -114, + 79, -63, -211, -70, -28, -217, 165, + 46, 38, -22, 281, 132, -62, 109, + 112, 54, -112, -93, 208, 27, 296, + 115, 10, -147, 41, 216, 42, -276, + 50, -115, -254, 167, 117, -2, 61, + 17, 144, 34, -72, -186, -150, 272, + -29, -66, -89, -95, -149, 129, 251, + 122, 0, -50, -234, -91, 36, 26, + -105, -102, -88, -121, -236, -7, -11, + -204, 109, 5, -191, 105, -15, 163, + -80, 32, -24, -209, 41, 294, 70, + -106, -94, -204, -118, 120, -50, -37, + -82, -241, 46, -131, -29, 150, -55, + 33, 155, 120, -89, -8, 7, 62, + 213, 82, 61, 18, -161, 144, 152, + 30, 131, 65, -87, -255, -17, -107, + -8, 85, -64, 51, -162, 223, -53, + -134, 261, 69, -56, 218, 72, -111, + 2, 155, -113, -87, 49, 85, -28, + -163, 42, -1, -196, 7, 39, -245, + 14, -137, -79, 11, -160, 202, -293, + -94, 33, 208, 100, 56, -44, 326, + -78, -41, 232, 13, -142, 227, 80, + -16, -87, 201, 33, -133, 15, -183, + -58, -192, -47, 184, -128, 133, 99, + -205, 11, -155, 78, 52, 72, 141, + -246, 26, 99, 151, 59, 115, -64, + -79, -47, -16, -14, 6, 47, -43, + -72, -178, -27, 162, 112, 43, -174, + -175, 238, 186, 71, -54, -188, -76, + -225, 233, 39, -39, -158, 122, 44, + -26, 43, 84, 130, -93, -51, 22, + 3, 92, -150, 136, -182, -57, 97, + -131, 179, -78, 80, 91, -165, 90, + -2, 148, 15, 130, 65, 175, 117, + -138, 114, -137, 132, 3, -10, -186, + 140, -4, -37, 254, -62, 92, -109}; + + diff --git a/media/libstagefright/codecs/amrwbenc/inc/stream.h b/media/libstagefright/codecs/amrwbenc/inc/stream.h new file mode 100644 index 0000000000000000000000000000000000000000..edbc13a3838ac74e2a460d4271266b5af5e8ab6c --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/stream.h @@ -0,0 +1,47 @@ + +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*********************************************************************** +File: stream.h + +Contains: VOME API Buffer Operator Implement Header + +************************************************************************/ +#ifndef __STREAM_H__ +#define __STREAM_H__ + +#include "voMem.h" +#define Frame_Maxsize 1024 * 2 //Work Buffer 10K +#define Frame_MaxByte 640 //AMR_WB Encoder one frame 320 samples = 640 Bytes +#define MIN(a,b) ((a) < (b)? (a) : (b)) + +typedef struct{ + unsigned char *set_ptr; + unsigned char *frame_ptr; + unsigned char *frame_ptr_bk; + int set_len; + int framebuffer_len; + int frame_storelen; + int used_len; +}FrameStream; + +void voAWB_UpdateFrameBuffer(FrameStream *stream, VO_MEM_OPERATOR *pMemOP); +void voAWB_InitFrameBuffer(FrameStream *stream); +void voAWB_FlushFrameBuffer(FrameStream *stream); +#endif //__STREAM_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/typedef.h b/media/libstagefright/codecs/amrwbenc/inc/typedef.h new file mode 100644 index 0000000000000000000000000000000000000000..aa8c0988560a0131c9e9e0fa062a52bb090a7dc4 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/typedef.h @@ -0,0 +1,65 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* +* File : typedef.c +* Purpose : Basic types. +* +************************************************************************/ + +#ifndef __TYPEDEF_H__ +#define __TYPEDEF_H__ + +#undef ORIGINAL_TYPEDEF_H /* define to get "original" ETSI version + of typedef.h */ + +#ifdef ORIGINAL_TYPEDEF_H +/* + * this is the original code from the ETSI file typedef.h + */ + +#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__) +typedef signed char Word8; +typedef short Word16; +typedef long Word32; +typedef int Flag; + +#elif defined(__sun) +typedef signed char Word8; +typedef short Word16; +typedef long Word32; +typedef int Flag; + +#elif defined(__unix__) || defined(__unix) +typedef signed char Word8; +typedef short Word16; +typedef int Word32; +typedef int Flag; + +#endif +#else /* not original typedef.h */ + +/* + * use (improved) type definition file typdefs.h and add a "Flag" type + */ +#include "typedefs.h" +typedef int Flag; + +#endif + +#endif //__TYPEDEF_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/typedefs.h b/media/libstagefright/codecs/amrwbenc/inc/typedefs.h new file mode 100644 index 0000000000000000000000000000000000000000..28b657e4188748b72c3a52f02af124f4e11bd2d1 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/typedefs.h @@ -0,0 +1,211 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/* +* +* File : typedefs.h +* Description : Definition of platform independent data +* types and constants +* +* +* The following platform independent data types and corresponding +* preprocessor (#define) constants are defined: +* +* defined type meaning corresponding constants +* ---------------------------------------------------------- +* Char character (none) +* Bool boolean true, false +* Word8 8-bit signed minWord8, maxWord8 +* UWord8 8-bit unsigned minUWord8, maxUWord8 +* Word16 16-bit signed minWord16, maxWord16 +* UWord16 16-bit unsigned minUWord16, maxUWord16 +* Word32 32-bit signed minWord32, maxWord32 +* UWord32 32-bit unsigned minUWord32, maxUWord32 +* Float floating point minFloat, maxFloat +* +* +* The following compile switches are #defined: +* +* PLATFORM string indicating platform progam is compiled on +* possible values: "OSF", "PC", "SUN" +* +* OSF only defined if the current platform is an Alpha +* PC only defined if the current platform is a PC +* SUN only defined if the current platform is a Sun +* +* LSBFIRST is defined if the byte order on this platform is +* "least significant byte first" -> defined on DEC Alpha +* and PC, undefined on Sun +* +******************************************************************************** +*/ + +#ifndef __TYPEDEFS_H__ +#define __TYPEDEFS_H__ + +/* +******************************************************************************** +* INCLUDE FILES +******************************************************************************** +*/ +#include +#include + + + +/* +******************************************************************************** +* DEFINITION OF CONSTANTS +******************************************************************************** +*/ +/* + ********* define char type + */ +typedef char Char; + +/* + ********* define 8 bit signed/unsigned types & constants + */ +#if SCHAR_MAX == 127 +typedef signed char Word8; +#define minWord8 SCHAR_MIN +#define maxWord8 SCHAR_MAX + +typedef unsigned char UWord8; +#define minUWord8 0 +#define maxUWord8 UCHAR_MAX +#else +#error cannot find 8-bit type +#endif + + +/* + ********* define 16 bit signed/unsigned types & constants + */ +#if INT_MAX == 32767 +typedef int Word16; +#define minWord16 INT_MIN +#define maxWord16 INT_MAX +typedef unsigned int UWord16; +#define minUWord16 0 +#define maxUWord16 UINT_MAX +#elif SHRT_MAX == 32767 +typedef short Word16; +#define minWord16 SHRT_MIN +#define maxWord16 SHRT_MAX +typedef unsigned short UWord16; +#define minUWord16 0 +#define maxUWord16 USHRT_MAX +#else +#error cannot find 16-bit type +#endif + + +/* + ********* define 32 bit signed/unsigned types & constants + */ +#if INT_MAX == 2147483647 +typedef int Word32; +#define minWord32 INT_MIN +#define maxWord32 INT_MAX +typedef unsigned int UWord32; +#define minUWord32 0 +#define maxUWord32 UINT_MAX +#elif LONG_MAX == 2147483647 +typedef long Word32; +#define minWord32 LONG_MIN +#define maxWord32 LONG_MAX +typedef unsigned long UWord32; +#define minUWord32 0 +#define maxUWord32 ULONG_MAX +#else +#error cannot find 32-bit type +#endif + +/* + ********* define floating point type & constants + */ +/* use "#if 0" below if Float should be double; + use "#if 1" below if Float should be float + */ +#if 0 +typedef float Float; +#define maxFloat FLT_MAX +#define minFloat FLT_MIN +#else +typedef double Float; +#define maxFloat DBL_MAX +#define minFloat DBL_MIN +#endif + +/* + ********* define complex type + */ +typedef struct { + Float r; /* real part */ + Float i; /* imaginary part */ +} CPX; + +/* + ********* define boolean type + */ +typedef int Bool; +#define false 0 +#define true 1 + +/* ******Avoid function multiple definition****** */ +#define Autocorr voAWB_Autocorr +#define Convolve voAWB_Convolve +#define cor_h_x voAWB_cor_h_x +#define dtx_enc_init voAWB_dtx_enc_init +#define dtx_enc_reset voAWB_dtx_enc_reset +#define dtx_enc_exit voAWB_dtx_enc_exit +#define dtx_enc voAWB_dtx_enc +#define dtx_buffer voAWB_dtx_buffer +#define tx_dtx_handler voAWB_tx_dtx_handler +#define G_pitch voAWB_G_pitch +#define Isp_Az voAWB_Isp_Az +#define Lag_window voAWB_Lag_window +#define Log2_norm voAWB_Log2_norm +#define Log2 voAWB_Log2 +#define Pow2 voAWB_Pow2 +#define L_Comp voAWB_L_Comp +#define Mpy_32 voAWB_Mpy_32 +#define Mpy_32_16 voAWB_Mpy_32_16 +#define Div_32 voAWB_Div_32 +#define Pit_shrp voAWB_Pit_shrp +#define Qisf_ns voAWB_Qisf_ns +#define Disf_ns voAWB_Disf_ns +#define Residu voAWB_Residu +#define Syn_filt voAWB_Syn_filt +#define Set_zero voAWB_Set_zero +#define Copy voAWB_Copy +#define voice_factor voAWB_voice_factor +#define Syn_filt_32 voAWB_Syn_filt_32 +#define Isf_isp voAWB_Isf_isp +#define Levinson voAWB_Levinson +#define median5 voAWB_median5 +#define Pred_lt4 voAWB_Pred_lt4 +#define Reorder_isf voAWB_Reorder_isf +#define Dpisf_2s_36b voAWB_Dpisf_2s_36b +#define Dpisf_2s_46b voAWB_Dpisf_2s_46b +#define Dot_product12 voAWB_Dot_product12 +#define mem_malloc voAWB_mem_malloc +#define mem_free voAWB_mem_free +/******************************************************/ + +#endif //#define __TYPEDEFS_H__ + diff --git a/media/libstagefright/codecs/amrwbenc/inc/wb_vad.h b/media/libstagefright/codecs/amrwbenc/inc/wb_vad.h new file mode 100644 index 0000000000000000000000000000000000000000..b733afee25b26ed64f055c1258a531fa4fece8ca --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/wb_vad.h @@ -0,0 +1,78 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*-------------------------------------------------------------------* + * WB_VAD.H * + *-------------------------------------------------------------------* + * Functions and static memory for Voice Activity Detection. * + *-------------------------------------------------------------------*/ + +#ifndef __WB_VAD_H__ +#define __WB_VAD_H__ + +/****************************************************************************** + * INCLUDE FILES + ******************************************************************************/ +#include "typedef.h" +#include "wb_vad_c.h" +#include "voMem.h" + +/****************************************************************************** + * DEFINITION OF DATA TYPES + ******************************************************************************/ + +typedef struct +{ + Word16 bckr_est[COMPLEN]; /* background noise estimate */ + Word16 ave_level[COMPLEN]; /* averaged input components for stationary */ + /* estimation */ + Word16 old_level[COMPLEN]; /* input levels of the previous frame */ + Word16 sub_level[COMPLEN]; /* input levels calculated at the end of a frame (lookahead) */ + Word16 a_data5[F_5TH_CNT][2]; /* memory for the filter bank */ + Word16 a_data3[F_3TH_CNT]; /* memory for the filter bank */ + + Word16 burst_count; /* counts length of a speech burst */ + Word16 hang_count; /* hangover counter */ + Word16 stat_count; /* stationary counter */ + + /* Note that each of the following two variables holds 15 flags. Each flag reserves 1 bit of the + * variable. The newest flag is in the bit 15 (assuming that LSB is bit 1 and MSB is bit 16). */ + Word16 vadreg; /* flags for intermediate VAD decisions */ + Word16 tone_flag; /* tone detection flags */ + + Word16 sp_est_cnt; /* counter for speech level estimation */ + Word16 sp_max; /* maximum level */ + Word16 sp_max_cnt; /* counts frames that contains speech */ + Word16 speech_level; /* estimated speech level */ + Word32 prev_pow_sum; /* power of previous frame */ + +} VadVars; + +/******************************************************************************** + * + * DECLARATION OF PROTOTYPES + ********************************************************************************/ + +Word16 wb_vad_init(VadVars ** st, VO_MEM_OPERATOR *pMemOP); +Word16 wb_vad_reset(VadVars * st); +void wb_vad_exit(VadVars ** st, VO_MEM_OPERATOR *pMemOP); +void wb_vad_tone_detection(VadVars * st, Word16 p_gain); +Word16 wb_vad(VadVars * st, Word16 in_buf[]); + +#endif //__WB_VAD_H__ + + diff --git a/media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h b/media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h new file mode 100644 index 0000000000000000000000000000000000000000..39ef5062b9dd28b215a20a3812844eedef415d49 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h @@ -0,0 +1,109 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*-------------------------------------------------------------------* + * WB_VAD_C.H * + *-------------------------------------------------------------------* + * Constants for Voice Activity Detection. * + *-------------------------------------------------------------------*/ + +#ifndef __WB_VAD_C_H__ +#define __WB_VAD_C_H__ + +#define FRAME_LEN 256 /* Length (samples) of the input frame */ +#define COMPLEN 12 /* Number of sub-bands used by VAD */ + +#define UNIRSHFT 7 /* = log2(MAX_16/UNITY), UNITY = 256 */ +#define SCALE 128 /* (UNITY*UNITY)/512 */ + +#define TONE_THR (Word16)(0.65*MAX_16) /* Threshold for tone detection */ + +/* constants for speech level estimation */ +#define SP_EST_COUNT 80 +#define SP_ACTIVITY_COUNT 25 +#define ALPHA_SP_UP (Word16)((1.0 - 0.85)*MAX_16) +#define ALPHA_SP_DOWN (Word16)((1.0 - 0.85)*MAX_16) + +#define NOM_LEVEL 2050 /* about -26 dBov Q15 */ +#define SPEECH_LEVEL_INIT NOM_LEVEL /* initial speech level */ +#define MIN_SPEECH_LEVEL1 (Word16)(NOM_LEVEL * 0.063) /* NOM_LEVEL -24 dB */ +#define MIN_SPEECH_LEVEL2 (Word16)(NOM_LEVEL * 0.2) /* NOM_LEVEL -14 dB */ +#define MIN_SPEECH_SNR 4096 /* 0 dB, lowest SNR estimation, Q12 */ + +/* Time constants for background spectrum update */ +#define ALPHA_UP1 (Word16)((1.0 - 0.95)*MAX_16) /* Normal update, upwards: */ +#define ALPHA_DOWN1 (Word16)((1.0 - 0.936)*MAX_16) /* Normal update, downwards */ +#define ALPHA_UP2 (Word16)((1.0 - 0.985)*MAX_16) /* Forced update, upwards */ +#define ALPHA_DOWN2 (Word16)((1.0 - 0.943)*MAX_16) /* Forced update, downwards */ +#define ALPHA3 (Word16)((1.0 - 0.95)*MAX_16) /* Update downwards */ +#define ALPHA4 (Word16)((1.0 - 0.9)*MAX_16) /* For stationary estimation */ +#define ALPHA5 (Word16)((1.0 - 0.5)*MAX_16) /* For stationary estimation */ + +/* Constants for VAD threshold */ +#define THR_MIN (Word16)(1.6*SCALE) /* Minimum threshold */ +#define THR_HIGH (Word16)(6*SCALE) /* Highest threshold */ +#define THR_LOW (Word16)(1.7*SCALE) /* Lowest threshold */ +#define NO_P1 31744 /* ilog2(1), Noise level for highest threshold */ +#define NO_P2 19786 /* ilog2(0.1*MAX_16), Noise level for lowest threshold */ +#define NO_SLOPE (Word16)(MAX_16*(float)(THR_LOW-THR_HIGH)/(float)(NO_P2-NO_P1)) + +#define SP_CH_MIN (Word16)(-0.75*SCALE) +#define SP_CH_MAX (Word16)(0.75*SCALE) +#define SP_P1 22527 /* ilog2(NOM_LEVEL/4) */ +#define SP_P2 17832 /* ilog2(NOM_LEVEL*4) */ +#define SP_SLOPE (Word16)(MAX_16*(float)(SP_CH_MAX-SP_CH_MIN)/(float)(SP_P2-SP_P1)) + +/* Constants for hangover length */ +#define HANG_HIGH 12 /* longest hangover */ +#define HANG_LOW 2 /* shortest hangover */ +#define HANG_P1 THR_LOW /* threshold for longest hangover */ +#define HANG_P2 (Word16)(4*SCALE) /* threshold for shortest hangover */ +#define HANG_SLOPE (Word16)(MAX_16*(float)(HANG_LOW-HANG_HIGH)/(float)(HANG_P2-HANG_P1)) + +/* Constants for burst length */ +#define BURST_HIGH 8 /* longest burst length */ +#define BURST_LOW 3 /* shortest burst length */ +#define BURST_P1 THR_HIGH /* threshold for longest burst */ +#define BURST_P2 THR_LOW /* threshold for shortest burst */ +#define BURST_SLOPE (Word16)(MAX_16*(float)(BURST_LOW-BURST_HIGH)/(float)(BURST_P2-BURST_P1)) + +/* Parameters for background spectrum recovery function */ +#define STAT_COUNT 20 /* threshold of stationary detection counter */ + +#define STAT_THR_LEVEL 184 /* Threshold level for stationarity detection */ +#define STAT_THR 1000 /* Threshold for stationarity detection */ + +/* Limits for background noise estimate */ +#define NOISE_MIN 40 /* minimum */ +#define NOISE_MAX 20000 /* maximum */ +#define NOISE_INIT 150 /* initial */ + +/* Thresholds for signal power (now calculated on 2 frames) */ +#define VAD_POW_LOW (Word32)30000L /* If input power is lower than this, VAD is set to 0 */ +#define POW_TONE_THR (Word32)686080L /* If input power is lower,tone detection flag is ignored */ + +/* Constants for the filter bank */ +#define COEFF3 13363 /* coefficient for the 3rd order filter */ +#define COEFF5_1 21955 /* 1st coefficient the for 5th order filter */ +#define COEFF5_2 6390 /* 2nd coefficient the for 5th order filter */ +#define F_5TH_CNT 5 /* number of 5th order filters */ +#define F_3TH_CNT 6 /* number of 3th order filters */ + +#endif //__WB_VAD_C_H__ + + + diff --git a/media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt b/media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt new file mode 100644 index 0000000000000000000000000000000000000000..b4bf11d4ab14011ba28ce5ff6090529d2b7b587f --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt @@ -0,0 +1,9 @@ + +THIS IS NOT A GRANT OF PATENT RIGHTS. + +Google makes no representation or warranty that the codecs for which +source code is made available hereunder are unencumbered by +third-party patents. Those intending to use this source code in +hardware or software products are advised that implementations of +these codecs, including in open source software or shareware, may +require patent licenses from the relevant patent holders. diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s new file mode 100644 index 0000000000000000000000000000000000000000..0eb5e9f57ad76170af34e8d2e9671ec1fe4bd2fe --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s @@ -0,0 +1,104 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@void Deemph_32( +@ Word16 x_hi[], /* (i) : input signal (bit31..16) */ +@ Word16 x_lo[], /* (i) : input signal (bit15..4) */ +@ Word16 y[], /* (o) : output signal (x16) */ +@ Word16 mu, /* (i) Q15 : deemphasis factor */ +@ Word16 L, /* (i) : vector size */ +@ Word16 * mem /* (i/o) : memory (y[-1]) */ +@ ) + +@x_hi RN R0 +@x_lo RN R1 +@y[] RN R2 +@*mem RN R3 + + .section .text + .global Deemph_32_asm + +Deemph_32_asm: + + STMFD r13!, {r4 - r12, r14} + MOV r4, #2 @i=0 + LDRSH r6, [r0], #2 @load x_hi[0] + LDRSH r7, [r1], #2 @load x_lo[0] + LDR r5, =22282 @r5---mu + MOV r11, #0x8000 + + @y[0] + MOV r10, r6, LSL #16 @L_tmp = x_hi[0]<<16 + MOV r8, r5, ASR #1 @fac = mu >> 1 + LDR r5, [r3] + ADD r12, r10, r7, LSL #4 @L_tmp += x_lo[0] << 4 + MOV r10, r12, LSL #3 @L_tmp <<= 3 + MUL r9, r5, r8 + LDRSH r6, [r0], #2 @load x_hi[1] + QDADD r10, r10, r9 + LDRSH r7, [r1], #2 @load x_lo[1] + MOV r12, r10, LSL #1 @L_tmp = L_mac(L_tmp, *mem, fac) + QADD r10, r12, r11 + MOV r14, r10, ASR #16 @y[0] = round(L_tmp) + + + MOV r10, r6, LSL #16 + ADD r12, r10, r7, LSL #4 + STRH r14, [r2], #2 @update y[0] + MOV r10, r12, LSL #3 + MUL r9, r14, r8 + QDADD r10, r10, r9 + MOV r12, r10, LSL #1 + QADD r10, r12, r11 + MOV r14, r10, ASR #16 @y[1] = round(L_tmp) + +LOOP: + LDRSH r6, [r0], #2 @load x_hi[] + LDRSH r7, [r1], #2 + STRH r14, [r2], #2 + MOV r10, r6, LSL #16 + ADD r12, r10, r7, LSL #4 + MUL r9, r14, r8 + MOV r10, r12, LSL #3 + QDADD r10, r10, r9 + LDRSH r6, [r0], #2 @load x_hi[] + MOV r12, r10, LSL #1 + QADD r10, r12, r11 + LDRSH r7, [r1], #2 + MOV r14, r10, ASR #16 + + MOV r10, r6, LSL #16 + ADD r12, r10, r7, LSL #4 + STRH r14, [r2], #2 + MUL r9, r14, r8 + MOV r10, r12, LSL #3 + QDADD r10, r10, r9 + ADD r4, r4, #2 + MOV r12, r10, LSL #1 + QADD r10, r12, r11 + CMP r4, #64 + MOV r14, r10, ASR #16 + + BLT LOOP + STR r14, [r3] + STRH r14, [r2] + + LDMFD r13!, {r4 - r12, r15} + + @ENDP + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s new file mode 100644 index 0000000000000000000000000000000000000000..03832696eca7d96f2be1e3a67892a63b11e705cd --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s @@ -0,0 +1,80 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */ +@ Word16 x[], /* (i) 12bits: x vector */ +@ Word16 y[], /* (i) 12bits: y vector */ +@ Word16 lg, /* (i) : vector length */ +@ Word16 * exp /* (o) : exponent of result (0..+30) */ +@) +@**************************************************************** +@ x[] --- r0 +@ y[] --- r1 +@ lg --- r2 +@ *exp --- r3 + + .section .text + .global Dot_product12_asm + +Dot_product12_asm: + + STMFD r13!, {r4 - r12, r14} + MOV r4, #0 @ L_sum = 0 + MOV r5, #0 @ i = 0 + +LOOP: + LDR r6, [r0], #4 + LDR r7, [r1], #4 + LDR r8, [r0], #4 + SMLABB r4, r6, r7, r4 + LDR r9, [r1], #4 + SMLATT r4, r6, r7, r4 + + LDR r6, [r0], #4 + SMLABB r4, r8, r9, r4 + + LDR r7, [r1], #4 + SMLATT r4, r8, r9, r4 + LDR r8, [r0], #4 + + SMLABB r4, r6, r7, r4 + LDR r9, [r1], #4 + SMLATT r4, r6, r7, r4 + ADD r5, r5, #8 + SMLABB r4, r8, r9, r4 + CMP r5, r2 + SMLATT r4, r8, r9, r4 + BLT LOOP + + MOV r12, r4, LSL #1 + ADD r12, r12, #1 @ L_sum = (L_sum << 1) + 1 + MOV r4, r12 + + CMP r12, #0 + RSBLT r4, r12, #0 + CLZ r10, r4 + SUB r10, r10, #1 @ sft = norm_l(L_sum) + MOV r0, r12, LSL r10 @ L_sum = L_sum << sft + RSB r11, r10, #30 @ *exp = 30 - sft + STRH r11, [r3] + +Dot_product12_end: + + LDMFD r13!, {r4 - r12, r15} + @ENDFUNC + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s new file mode 100644 index 0000000000000000000000000000000000000000..e6ebd73dc39bda3a6d45d5f5d7277f3476732b1b --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s @@ -0,0 +1,185 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@**********************************************************************/ +@void Filt_6k_7k( +@ Word16 signal[], /* input: signal */ +@ Word16 lg, /* input: length of input */ +@ Word16 mem[] /* in/out: memory (size=30) */ +@) +@****************************************************************** +@ r0 --- signal[] +@ r1 --- lg +@ r2 --- mem[] + + .section .text + .global Filt_6k_7k_asm + .extern voAWB_Copy + .extern fir_6k_7k + +Filt_6k_7k_asm: + + STMFD r13!, {r4 - r12, r14} + SUB r13, r13, #240 @ x[L_SUBFR16k + (L_FIR - 1)] + MOV r8, r0 @ copy signal[] address + MOV r4, r1 @ copy lg address + MOV r5, r2 @ copy mem[] address + + MOV r1, r13 + MOV r0, r2 + MOV r2, #30 @ L_FIR - 1 + BL voAWB_Copy @ memcpy(x, mem, (L_FIR - 1)<<1) + + LDR r10, Lable1 @ get fir_7k address + + MOV r14, #0 + MOV r3, r8 @ change myMemCopy to Copy, due to Copy will change r3 content + ADD r6, r13, #60 @ get x[L_FIR - 1] address + MOV r7, r3 @ get signal[i] +LOOP1: + LDRSH r8, [r7], #2 + LDRSH r9, [r7], #2 + MOV r8, r8, ASR #2 + MOV r9, r9, ASR #2 + LDRSH r11, [r7], #2 + LDRSH r12, [r7], #2 + MOV r11, r11, ASR #2 + MOV r12, r12, ASR #2 + STRH r8, [r6], #2 + STRH r9, [r6], #2 + STRH r11, [r6], #2 + STRH r12, [r6], #2 + LDRSH r8, [r7], #2 + LDRSH r9, [r7], #2 + MOV r8, r8, ASR #2 + MOV r9, r9, ASR #2 + LDRSH r11, [r7], #2 + LDRSH r12, [r7], #2 + MOV r11, r11, ASR #2 + MOV r12, r12, ASR #2 + STRH r8, [r6], #2 + STRH r9, [r6], #2 + STRH r11, [r6], #2 + STRH r12, [r6], #2 + ADD r14, r14, #8 + CMP r14, #80 + BLT LOOP1 + + + STR r5, [sp, #-4] @ PUSH r5 to stack + + @ not use registers: r4, r10, r12, r14, r5 + MOV r4, r13 + MOV r5, #0 @ i = 0 +LOOP2: + LDR r0, [r10] + + LDRSH r1, [r4] @ load x[i] + LDRSH r2, [r4, #60] @ load x[i + 30] + LDRSH r6, [r4, #2] @ load x[i + 1] + LDRSH r7, [r4, #58] @ load x[i + 29] + ADD r1, r1, r2 @ x[i] + x[i + 30] + ADD r6, r6, r7 @ x[i + 1] + x[i + 29] + LDRSH r8, [r4, #4] @ load x[i + 2] + LDRSH r9, [r4, #56] @ load x[i + 28] + + SMULBB r14, r1, r0 @ (x[i] + x[i + 30]) * fir_7k[0] + ADD r8, r8, r9 @ x[i + 2] + x[i + 28] + SMLABT r14, r6, r0, r14 @ (x[i + 1] + x[i + 29]) * fir_7k[1] + + LDR r0, [r10, #4] + LDRSH r1, [r4, #6] @ load x[i+3] + LDRSH r2, [r4, #54] @ load x[i+27] + LDRSH r6, [r4, #8] @ load x[i+4] + LDRSH r7, [r4, #52] @ load x[i+26] + ADD r1, r1, r2 @ x[i+3] + x[i+27] + ADD r6, r6, r7 @ x[i+4] + x[i+26] + SMLABB r14, r8, r0, r14 @ (x[i + 2] + x[i + 28]) * fir_7k[2] + LDRSH r8, [r4, #10] @ load x[i+5] + LDRSH r9, [r4, #50] @ load x[i+25] + SMLABT r14, r1, r0, r14 @ (x[i+3] + x[i+27]) * fir_7k[3] + ADD r8, r8, r9 @ x[i+5] + x[i+25] + + LDR r0, [r10, #8] + LDRSH r1, [r4, #12] @ x[i+6] + LDRSH r2, [r4, #48] @ x[i+24] + SMLABB r14, r6, r0, r14 @ (x[i+4] + x[i+26]) * fir_7k[4] + LDRSH r6, [r4, #14] @ x[i+7] + LDRSH r7, [r4, #46] @ x[i+23] + SMLABT r14, r8, r0, r14 @ (x[i+5] + x[i+25]) * fir_7k[5] + LDR r0, [r10, #12] + ADD r1, r1, r2 @ (x[i+6] + x[i+24]) + ADD r6, r6, r7 @ (x[i+7] + x[i+23]) + SMLABB r14, r1, r0, r14 @ (x[i+6] + x[i+24]) * fir_7k[6] + LDRSH r8, [r4, #16] @ x[i+8] + LDRSH r9, [r4, #44] @ x[i+22] + SMLABT r14, r6, r0, r14 @ (x[i+7] + x[i+23]) * fir_7k[7] + LDR r0, [r10, #16] + LDRSH r1, [r4, #18] @ x[i+9] + LDRSH r2, [r4, #42] @ x[i+21] + LDRSH r6, [r4, #20] @ x[i+10] + LDRSH r7, [r4, #40] @ x[i+20] + ADD r8, r8, r9 @ (x[i+8] + x[i+22]) + ADD r1, r1, r2 @ (x[i+9] + x[i+21]) + ADD r6, r6, r7 @ (x[i+10] + x[i+20]) + SMLABB r14, r8, r0, r14 @ (x[i+8] + x[i+22]) * fir_7k[8] + LDRSH r8, [r4, #22] @ x[i+11] + LDRSH r9, [r4, #38] @ x[i+19] + SMLABT r14, r1, r0, r14 @ (x[i+9] + x[i+21]) * fir_7k[9] + LDR r0, [r10, #20] + LDRSH r1, [r4, #24] @ x[i+12] + LDRSH r2, [r4, #36] @ x[i+18] + SMLABB r14, r6, r0, r14 @ (x[i+10] + x[i+20]) * fir_7k[10] + LDRSH r6, [r4, #26] @ x[i+13] + ADD r8, r8, r9 @ (x[i+11] + x[i+19]) + LDRSH r7, [r4, #34] @ x[i+17] + SMLABT r14, r8, r0, r14 @ (x[i+11] + x[i+19]) * fir_7k[11] + LDR r0, [r10, #24] + ADD r1, r1, r2 @ x[i+12] + x[i+18] + LDRSH r8, [r4, #28] @ x[i+14] + SMLABB r14, r1, r0, r14 @ (x[i+12] + x[i+18]) * fir_7k[12] + ADD r6, r6, r7 @ (x[i+13] + x[i+17]) + LDRSH r9, [r4, #32] @ x[i+16] + SMLABT r14, r6, r0, r14 @ (x[i+13] + x[i+17]) * fir_7k[13] + LDR r0, [r10, #28] + ADD r8, r8, r9 @ (x[i+14] + x[i+16]) + LDRSH r1, [r4, #30] @ x[i+15] + SMLABB r14, r8, r0, r14 @ (x[i+14] + x[i+16]) * fir_7k[14] + SMLABT r14, r1, r0, r14 @ x[i+15] * fir_7k[15] + + ADD r5, r5, #1 + ADD r14, r14, #0x4000 + ADD r4, r4, #2 + MOV r1, r14, ASR #15 + CMP r5, #80 + STRH r1, [r3], #2 @signal[i] = (L_tmp + 0x4000) >> 15 + BLT LOOP2 + + LDR r1, [sp, #-4] @mem address + ADD r0, r13, #160 @x + lg + MOV r2, #30 + BL voAWB_Copy + +Filt_6k_7k_end: + ADD r13, r13, #240 + LDMFD r13!, {r4 - r12, r15} + +Lable1: + .word fir_6k_7k + @ENDFUNC + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s new file mode 100644 index 0000000000000000000000000000000000000000..b440a31ed0b6f216b11ae32ffe98e7a9dd4d1bb6 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s @@ -0,0 +1,231 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + +@static void Norm_Corr (Word16 exc[], /* (i) : excitation buffer */ +@ Word16 xn[], /* (i) : target vector */ +@ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */ +@ Word16 L_subfr, /* (i) : sub-frame length */ +@ Word16 t_min, /* (i) : minimum value of pitch lag. */ +@ Word16 t_max, /* (i) : maximum value of pitch lag. */ +@ Word16 corr_norm[]) /* (o) Q15 : normalized correlation */ +@ + +@ r0 --- exc[] +@ r1 --- xn[] +@ r2 --- h[] +@ r3 --- L_subfr +@ r4 --- t_min +@ r5 --- t_max +@ r6 --- corr_norm[] + + + .section .text + .global Norm_corr_asm + .extern Convolve_asm + .extern Isqrt_n +@****************************** +@ constant +@****************************** +.equ EXC , 0 +.equ XN , 4 +.equ H , 8 +.equ L_SUBFR , 12 +.equ voSTACK , 172 +.equ T_MIN , 212 +.equ T_MAX , 216 +.equ CORR_NORM , 220 + +Norm_corr_asm: + + STMFD r13!, {r4 - r12, r14} + SUB r13, r13, #voSTACK + + ADD r8, r13, #20 @get the excf[L_SUBFR] + LDR r4, [r13, #T_MIN] @get t_min + RSB r11, r4, #0 @k = -t_min + ADD r5, r0, r11, LSL #1 @get the &exc[k] + + @transfer Convolve function + STMFD sp!, {r0 - r3} + MOV r0, r5 + MOV r1, r2 + MOV r2, r8 @r2 --- excf[] + BL Convolve_asm + LDMFD sp!, {r0 - r3} + + @ r8 --- excf[] + + MOV r14, r1 @copy xn[] address + MOV r5, #64 + MOV r6, #0 @L_tmp = 0 + MOV r7, #1 + +LOOP1: + LDR r9, [r14], #4 + LDR r10, [r14], #4 + LDR r11, [r14], #4 + LDR r12, [r14], #4 + SMLABB r6, r9, r9, r6 @L_tmp += (xn[i] * xn[i]) + SMLATT r6, r9, r9, r6 @L_tmp += (xn[i+1] * xn[i+1]) + SMLABB r6, r10, r10, r6 + SMLATT r6, r10, r10, r6 + SMLABB r6, r11, r11, r6 + SMLATT r6, r11, r11, r6 + SMLABB r6, r12, r12, r6 + SMLATT r6, r12, r12, r6 + SUBS r5, r5, #8 + BNE LOOP1 + + ADD r9, r7, r6, LSL #1 @L_tmp = (L_tmp << 1) + 1 + CLZ r7, r9 + SUB r6, r7, #1 @exp = norm_l(L_tmp) + RSB r7, r6, #32 @exp = 32 - exp + MOV r6, r7, ASR #1 + RSB r7, r6, #0 @scale = -(exp >> 1) + + @loop for every possible period + @for(t = t_min@ t <= t_max@ t++) + @r7 --- scale r4 --- t_min r8 --- excf[] + +LOOPFOR: + MOV r5, #0 @L_tmp = 0 + MOV r6, #0 @L_tmp1 = 0 + MOV r9, #64 + MOV r12, r1 @copy of xn[] + ADD r14, r13, #20 @copy of excf[] + MOV r8, #0x8000 + +LOOPi: + LDR r11, [r14], #4 @load excf[i], excf[i+1] + LDR r10, [r12], #4 @load xn[i], xn[i+1] + SMLABB r6, r11, r11, r6 @L_tmp1 += excf[i] * excf[i] + SMLATT r6, r11, r11, r6 @L_tmp1 += excf[i+1] * excf[i+1] + SMLABB r5, r10, r11, r5 @L_tmp += xn[i] * excf[i] + SMLATT r5, r10, r11, r5 @L_tmp += xn[i+1] * excf[i+1] + LDR r11, [r14], #4 @load excf[i+2], excf[i+3] + LDR r10, [r12], #4 @load xn[i+2], xn[i+3] + SMLABB r6, r11, r11, r6 + SMLATT r6, r11, r11, r6 + SMLABB r5, r10, r11, r5 + SMLATT r5, r10, r11, r5 + SUBS r9, r9, #4 + BNE LOOPi + + @r5 --- L_tmp, r6 --- L_tmp1 + MOV r10, #1 + ADD r5, r10, r5, LSL #1 @L_tmp = (L_tmp << 1) + 1 + ADD r6, r10, r6, LSL #1 @L_tmp1 = (L_tmp1 << 1) + 1 + + CLZ r10, r5 + CMP r5, #0 + RSBLT r11, r5, #0 + CLZLT r10, r11 + SUB r10, r10, #1 @exp = norm_l(L_tmp) + + MOV r5, r5, LSL r10 @L_tmp = (L_tmp << exp) + RSB r10, r10, #30 @exp_corr = 30 - exp + MOV r11, r5, ASR #16 @corr = extract_h(L_tmp) + + CLZ r5, r6 + SUB r5, r5, #1 + MOV r6, r6, LSL r5 @L_tmp = (L_tmp1 << exp) + RSB r5, r5, #30 @exp_norm = 30 - exp + + @r10 --- exp_corr, r11 --- corr + @r6 --- L_tmp, r5 --- exp_norm + + @Isqrt_n(&L_tmp, &exp_norm) + + MOV r14, r0 + MOV r12, r1 + + STMFD sp!, {r0 - r4, r7 - r12, r14} + ADD r1, sp, #4 + ADD r0, sp, #0 + STR r6, [sp] + STRH r5, [sp, #4] + BL Isqrt_n + LDR r6, [sp] + LDRSH r5, [sp, #4] + LDMFD sp!, {r0 - r4, r7 - r12, r14} + MOV r0, r14 + MOV r1, r12 + + + MOV r6, r6, ASR #16 @norm = extract_h(L_tmp) + MUL r12, r6, r11 + ADD r12, r12, r12 @L_tmp = vo_L_mult(corr, norm) + + ADD r6, r10, r5 + ADD r6, r6, r7 @exp_corr + exp_norm + scale + + CMP r6, #0 + RSBLT r6, r6, #0 + MOVLT r12, r12, ASR r6 + MOVGT r12, r12, LSL r6 @L_tmp = L_shl(L_tmp, exp_corr + exp_norm + scale) + + ADD r12, r12, r8 + MOV r12, r12, ASR #16 @vo_round(L_tmp) + + LDR r5, [r13, #CORR_NORM] @ get corr_norm address + LDR r6, [r13, #T_MAX] @ get t_max + ADD r10, r5, r4, LSL #1 @ get corr_norm[t] address + STRH r12, [r10] @ corr_norm[t] = vo_round(L_tmp) + + CMP r4, r6 + BEQ Norm_corr_asm_end + + ADD r4, r4, #1 @ t_min ++ + + RSB r5, r4, #0 @ k + + MOV r6, #63 @ i = 63 + MOV r8, r0 @ exc[] + MOV r9, r2 @ h[] + ADD r10, r13, #20 @ excf[] + + ADD r8, r8, r5, LSL #1 @ exc[k] address + ADD r9, r9, r6, LSL #1 @ h[i] address + ADD r10, r10, r6, LSL #1 @ excf[i] address + LDRSH r11, [r8] @ tmp = exc[k] + +LOOPK: + LDRSH r8, [r9], #-2 @ load h[i] + LDRSH r12, [r10, #-2] @ load excf[i - 1] + MUL r14, r11, r8 + MOV r8, r14, ASR #15 + ADD r14, r8, r12 + STRH r14, [r10], #-2 + SUBS r6, r6, #1 + BGT LOOPK + + LDRSH r8, [r9] @ load h[0] + MUL r14, r11, r8 + LDR r6, [r13, #T_MAX] @ get t_max + MOV r8, r14, ASR #15 + STRH r8, [r10] + + CMP r4, r6 + BLE LOOPFOR + +Norm_corr_asm_end: + + ADD r13, r13, #voSTACK + LDMFD r13!, {r4 - r12, r15} + + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s new file mode 100644 index 0000000000000000000000000000000000000000..6416634bcce4063fe0bae3def70a4d86ac3b00e9 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s @@ -0,0 +1,226 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@void Syn_filt_32( +@ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */ +@ Word16 m, /* (i) : order of LP filter */ +@ Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */ +@ Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */ +@ Word16 sig_hi[], /* (o) /16 : synthesis high */ +@ Word16 sig_lo[], /* (o) /16 : synthesis low */ +@ Word16 lg /* (i) : size of filtering */ +@) +@*************************************************************** +@ +@ a[] --- r0 +@ m --- r1 +@ exc[] --- r2 +@ Qnew --- r3 +@ sig_hi[] --- r4 +@ sig_lo[] --- r5 +@ lg --- r6 + + .section .text + .global Syn_filt_32_asm + +Syn_filt_32_asm: + + STMFD r13!, {r4 - r12, r14} + LDR r4, [r13, #40] @ get sig_hi[] address + LDR r5, [r13, #44] @ get sig_lo[] address + + LDRSH r6, [r0] @ load Aq[0] + ADD r7, r3, #4 @ 4 + Q_new + MOV r3, r6, ASR r7 @ a0 = Aq[0] >> (4 + Q_new) + + LDR r14, =0xffff + LDRSH r6, [r0, #2] @ load Aq[1] + LDRSH r7, [r0, #4] @ load Aq[2] + LDRSH r8, [r0, #6] @ load Aq[3] + LDRSH r9, [r0, #8] @ load Aq[4] + AND r6, r6, r14 + AND r8, r8, r14 + ORR r10, r6, r7, LSL #16 @ Aq[2] -- Aq[1] + ORR r11, r8, r9, LSL #16 @ Aq[4] -- Aq[3] + STR r10, [r13, #-4] + STR r11, [r13, #-8] + + LDRSH r6, [r0, #10] @ load Aq[5] + LDRSH r7, [r0, #12] @ load Aq[6] + LDRSH r8, [r0, #14] @ load Aq[7] + LDRSH r9, [r0, #16] @ load Aq[8] + AND r6, r6, r14 + AND r8, r8, r14 + ORR r10, r6, r7, LSL #16 @ Aq[6] -- Aq[5] + ORR r11, r8, r9, LSL #16 @ Aq[8] -- Aq[7] + STR r10, [r13, #-12] + STR r11, [r13, #-16] + + LDRSH r6, [r0, #18] @ load Aq[9] + LDRSH r7, [r0, #20] @ load Aq[10] + LDRSH r8, [r0, #22] @ load Aq[11] + LDRSH r9, [r0, #24] @ load Aq[12] + AND r6, r6, r14 + AND r8, r8, r14 + ORR r10, r6, r7, LSL #16 @ Aq[10] -- Aq[9] + ORR r11, r8, r9, LSL #16 @ Aq[12] -- Aq[11] + STR r10, [r13, #-20] + STR r11, [r13, #-24] + + LDRSH r6, [r0, #26] @ load Aq[13] + LDRSH r7, [r0, #28] @ load Aq[14] + LDRSH r8, [r0, #30] @ load Aq[15] + LDRSH r9, [r0, #32] @ load Aq[16] + AND r6, r6, r14 + AND r8, r8, r14 + ORR r10, r6, r7, LSL #16 @ Aq[14] -- Aq[13] + ORR r11, r8, r9, LSL #16 @ Aq[16] -- Aq[15] + STR r10, [r13, #-28] + STR r11, [r13, #-32] + + MOV r8, #0 @ i = 0 + +LOOP: + LDRSH r6, [r5, #-2] @ load sig_lo[i-1] + LDRSH r7, [r5, #-4] @ load sig_lo[i-2] + + LDR r11, [r13, #-4] @ Aq[2] -- Aq[1] + LDRSH r9, [r5, #-6] @ load sig_lo[i-3] + LDRSH r10, [r5, #-8] @ load sig_lo[i-4] + + SMULBB r12, r6, r11 @ sig_lo[i-1] * Aq[1] + + LDRSH r6, [r5, #-10] @ load sig_lo[i-5] + SMLABT r12, r7, r11, r12 @ sig_lo[i-2] * Aq[2] + LDR r11, [r13, #-8] @ Aq[4] -- Aq[3] + LDRSH r7, [r5, #-12] @ load sig_lo[i-6] + SMLABB r12, r9, r11, r12 @ sig_lo[i-3] * Aq[3] + LDRSH r9, [r5, #-14] @ load sig_lo[i-7] + SMLABT r12, r10, r11, r12 @ sig_lo[i-4] * Aq[4] + LDR r11, [r13, #-12] @ Aq[6] -- Aq[5] + LDRSH r10, [r5, #-16] @ load sig_lo[i-8] + SMLABB r12, r6, r11, r12 @ sig_lo[i-5] * Aq[5] + LDRSH r6, [r5, #-18] @ load sig_lo[i-9] + SMLABT r12, r7, r11, r12 @ sig_lo[i-6] * Aq[6] + LDR r11, [r13, #-16] @ Aq[8] -- Aq[7] + LDRSH r7, [r5, #-20] @ load sig_lo[i-10] + SMLABB r12, r9, r11, r12 @ sig_lo[i-7] * Aq[7] + LDRSH r9, [r5, #-22] @ load sig_lo[i-11] + SMLABT r12, r10, r11, r12 @ sig_lo[i-8] * Aq[8] + LDR r11, [r13, #-20] @ Aq[10] -- Aq[9] + LDRSH r10,[r5, #-24] @ load sig_lo[i-12] + SMLABB r12, r6, r11, r12 @ sig_lo[i-9] * Aq[9] + LDRSH r6, [r5, #-26] @ load sig_lo[i-13] + SMLABT r12, r7, r11, r12 @ sig_lo[i-10] * Aq[10] + LDR r11, [r13, #-24] @ Aq[12] -- Aq[11] + LDRSH r7, [r5, #-28] @ load sig_lo[i-14] + SMLABB r12, r9, r11, r12 @ sig_lo[i-11] * Aq[11] + LDRSH r9, [r5, #-30] @ load sig_lo[i-15] + SMLABT r12, r10, r11, r12 @ sig_lo[i-12] * Aq[12] + + LDR r11, [r13, #-28] @ Aq[14] -- Aq[13] + LDRSH r10, [r5, #-32] @ load sig_lo[i-16] + SMLABB r12, r6, r11, r12 @ sig_lo[i-13] * Aq[13] + SMLABT r12, r7, r11, r12 @ sig_lo[i-14] * Aq[14] + + LDR r11, [r13, #-32] @ Aq[16] -- Aq[15] + LDRSH r6, [r2],#2 @ load exc[i] + SMLABB r12, r9, r11, r12 @ sig_lo[i-15] * Aq[15] + SMLABT r12, r10, r11, r12 @ sig_lo[i-16] * Aq[16] + MUL r7, r6, r3 @ exc[i] * a0 + RSB r14, r12, #0 @ L_tmp + MOV r14, r14, ASR #11 @ L_tmp >>= 11 + ADD r14, r14, r7, LSL #1 @ L_tmp += (exc[i] * a0) << 1 + + + LDRSH r6, [r4, #-2] @ load sig_hi[i-1] + LDRSH r7, [r4, #-4] @ load sig_hi[i-2] + + LDR r11, [r13, #-4] @ Aq[2] -- Aq[1] + LDRSH r9, [r4, #-6] @ load sig_hi[i-3] + LDRSH r10, [r4, #-8] @ load sig_hi[i-4] + SMULBB r12, r6, r11 @ sig_hi[i-1] * Aq[1] + LDRSH r6, [r4, #-10] @ load sig_hi[i-5] + SMLABT r12, r7, r11, r12 @ sig_hi[i-2] * Aq[2] + + LDR r11, [r13, #-8] @ Aq[4] -- Aq[3] + LDRSH r7, [r4, #-12] @ load sig_hi[i-6] + + SMLABB r12, r9, r11, r12 @ sig_hi[i-3] * Aq[3] + LDRSH r9, [r4, #-14] @ load sig_hi[i-7] + + SMLABT r12, r10, r11, r12 @ sig_hi[i-4] * Aq[4] + + LDR r11, [r13, #-12] @ Aq[6] -- Aq[5] + LDRSH r10, [r4, #-16] @ load sig_hi[i-8] + + SMLABB r12, r6, r11, r12 @ sig_hi[i-5] * Aq[5] + + LDRSH r6, [r4, #-18] @ load sig_hi[i-9] + SMLABT r12, r7, r11, r12 @ sig_hi[i-6] * Aq[6] + + LDR r11, [r13, #-16] @ Aq[8] -- Aq[7] + LDRSH r7, [r4, #-20] @ load sig_hi[i-10] + + SMLABB r12, r9, r11, r12 @ sig_hi[i-7] * Aq[7] + + LDRSH r9, [r4, #-22] @ load sig_hi[i-11] + + SMLABT r12, r10, r11, r12 @ sig_hi[i-8] * Aq[8] + + LDR r11, [r13, #-20] @ Aq[10] -- Aq[9] + LDRSH r10,[r4, #-24] @ load sig_hi[i-12] + + SMLABB r12, r6, r11, r12 @ sig_hi[i-9] * Aq[9] + LDRSH r6, [r4, #-26] @ load sig_hi[i-13] + SMLABT r12, r7, r11, r12 @ sig_hi[i-10] * Aq[10] + + LDR r11, [r13, #-24] @ Aq[12] -- Aq[11] + LDRSH r7, [r4, #-28] @ load sig_hi[i-14] + SMLABB r12, r9, r11, r12 @ sig_hi[i-11] * Aq[11] + LDRSH r9, [r4, #-30] @ load sig_hi[i-15] + SMLABT r12, r10, r11, r12 @ sig_hi[i-12] * Aq[12] + + LDR r11, [r13, #-28] @ Aq[14] -- Aq[13] + LDRSH r10, [r4, #-32] @ load sig_hi[i-16] + SMLABB r12, r6, r11, r12 @ sig_hi[i-13] * Aq[13] + SMLABT r12, r7, r11, r12 @ sig_hi[i-14] * Aq[14] + + LDR r11, [r13, #-32] @ Aq[16] -- Aq[15] + SMLABB r12, r9, r11, r12 @ sig_hi[i-15] * Aq[15] + SMLABT r12, r10, r11, r12 @ sig_hi[i-16] * Aq[16] + ADD r6, r12, r12 @ r12 << 1 + SUB r14, r14, r6 + MOV r14, r14, LSL #3 @ L_tmp <<=3 + + MOV r7, r14, ASR #16 @ L_tmp >> 16 + + MOV r14, r14, ASR #4 @ L_tmp >>=4 + STRH r7, [r4], #2 @ sig_hi[i] = L_tmp >> 16 + SUB r9, r14, r7, LSL #12 @ sig_lo[i] = L_tmp - (sig_hi[i] << 12) + + ADD r8, r8, #1 + STRH r9, [r5], #2 + CMP r8, #64 + BLT LOOP + +Syn_filt_32_end: + + LDMFD r13!, {r4 - r12, r15} + @ENDFUNC + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s new file mode 100644 index 0000000000000000000000000000000000000000..0228bda4a165509260f3d68bcd49d7e1ffff7416 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s @@ -0,0 +1,186 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ + + +@*void Convolve ( +@* Word16 x[], /* (i) : input vector */ +@* Word16 h[], /* (i) : impulse response */ +@* Word16 y[], /* (o) : output vector */ +@* Word16 L /* (i) : vector size */ +@*) +@ r0 --- x[] +@ r1 --- h[] +@ r2 --- y[] +@ r3 --- L + + .section .text + .global Convolve_asm + +Convolve_asm: + + STMFD r13!, {r4 - r12, r14} + MOV r3, #0 @ n + MOV r11, #0x8000 + +LOOP: + ADD r4, r1, r3, LSL #1 @ tmpH address + ADD r5, r3, #1 @ i = n + 1 + MOV r6, r0 @ tmpX = x + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4], #-2 @ *tmpH-- + SUB r5, r5, #1 + MUL r8, r9, r10 + +LOOP1: + CMP r5, #0 + BLE L1 + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4], #-2 @ *tmpH-- + LDRSH r12, [r6], #2 @ *tmpX++ + LDRSH r14, [r4], #-2 @ *tmpH-- + MLA r8, r9, r10, r8 + MLA r8, r12, r14, r8 + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4], #-2 @ *tmpH-- + LDRSH r12, [r6], #2 @ *tmpX++ + LDRSH r14, [r4], #-2 @ *tmpH-- + MLA r8, r9, r10, r8 + SUBS r5, r5, #4 + MLA r8, r12, r14, r8 + + B LOOP1 + +L1: + + ADD r5, r11, r8, LSL #1 + MOV r5, r5, LSR #16 @extract_h(s) + ADD r3, r3, #1 + STRH r5, [r2], #2 @y[n] + + + ADD r4, r1, r3, LSL #1 @tmpH address + ADD r5, r3, #1 + MOV r6, r0 + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4], #-2 + LDRSH r12, [r6], #2 + LDRSH r14, [r4], #-2 + + MUL r8, r9, r10 + SUB r5, r5, #2 + MLA r8, r12, r14, r8 + +LOOP2: + CMP r5, #0 + BLE L2 + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4], #-2 @ *tmpH-- + LDRSH r12, [r6], #2 @ *tmpX++ + LDRSH r14, [r4], #-2 @ *tmpH-- + MLA r8, r9, r10, r8 + MLA r8, r12, r14, r8 + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4], #-2 @ *tmpH-- + LDRSH r12, [r6], #2 @ *tmpX++ + LDRSH r14, [r4], #-2 @ *tmpH-- + MLA r8, r9, r10, r8 + SUBS r5, r5, #4 + MLA r8, r12, r14, r8 + B LOOP2 + +L2: + ADD r8, r11, r8, LSL #1 + MOV r8, r8, LSR #16 @extract_h(s) + ADD r3, r3, #1 + STRH r8, [r2], #2 @y[n] + + ADD r4, r1, r3, LSL #1 + ADD r5, r3, #1 + MOV r6, r0 + LDRSH r9, [r6], #2 + LDRSH r10, [r4], #-2 + LDRSH r12, [r6], #2 + LDRSH r14, [r4], #-2 + MUL r8, r9, r10 + LDRSH r9, [r6], #2 + LDRSH r10, [r4], #-2 + MLA r8, r12, r14, r8 + SUB r5, r5, #3 + MLA r8, r9, r10, r8 + +LOOP3: + CMP r5, #0 + BLE L3 + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4], #-2 @ *tmpH-- + LDRSH r12, [r6], #2 @ *tmpX++ + LDRSH r14, [r4], #-2 @ *tmpH-- + MLA r8, r9, r10, r8 + MLA r8, r12, r14, r8 + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4], #-2 @ *tmpH-- + LDRSH r12, [r6], #2 @ *tmpX++ + LDRSH r14, [r4], #-2 @ *tmpH-- + MLA r8, r9, r10, r8 + SUBS r5, r5, #4 + MLA r8, r12, r14, r8 + B LOOP3 + +L3: + ADD r8, r11, r8, LSL #1 + MOV r8, r8, LSR #16 @extract_h(s) + ADD r3, r3, #1 + STRH r8, [r2], #2 @y[n] + + ADD r5, r3, #1 @ i = n + 1 + ADD r4, r1, r3, LSL #1 @ tmpH address + MOV r6, r0 + MOV r8, #0 + +LOOP4: + CMP r5, #0 + BLE L4 + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4], #-2 @ *tmpH-- + LDRSH r12, [r6], #2 @ *tmpX++ + LDRSH r14, [r4], #-2 @ *tmpH-- + MLA r8, r9, r10, r8 + MLA r8, r12, r14, r8 + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4], #-2 @ *tmpH-- + LDRSH r12, [r6], #2 @ *tmpX++ + LDRSH r14, [r4], #-2 @ *tmpH-- + MLA r8, r9, r10, r8 + SUBS r5, r5, #4 + MLA r8, r12, r14, r8 + B LOOP4 +L4: + ADD r5, r11, r8, LSL #1 + MOV r5, r5, LSR #16 @extract_h(s) + ADD r3, r3, #1 + STRH r5, [r2], #2 @y[n] + + CMP r3, #64 + BLT LOOP + +Convolve_asm_end: + + LDMFD r13!, {r4 - r12, r15} + + @ENDFUNC + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s new file mode 100644 index 0000000000000000000000000000000000000000..441b9848028293fdee98c51f8bae37270bfe037d --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s @@ -0,0 +1,151 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@static void cor_h_vec_012( +@ Word16 h[], /* (i) scaled impulse response */ +@ Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */ +@ Word16 track, /* (i) track to use */ +@ Word16 sign[], /* (i) sign vector */ +@ Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */ +@ Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */ +@ Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */ +@) +@r0 ---- h[] +@r1 ---- vec[] +@r2 ---- track +@r3 ---- sign[] +@r4 ---- rrixix[][NB_POS] +@r5 ---- cor_1[] +@r6 ---- cor_2[] + + + .section .text + .global cor_h_vec_012_asm + +cor_h_vec_012_asm: + + STMFD r13!, {r4 - r12, r14} + LDR r4, [r13, #40] @load rrixix[][NB_POS] + ADD r7, r4, r2, LSL #5 @r7 --- p0 = rrixix[track] + MOV r4, #0 @i=0 + + @r0 --- h[], r1 --- vec[], r2 --- pos + @r3 --- sign[], r4 --- i, r7 --- p0 +LOOPi: + MOV r5, #0 @L_sum1 = 0 + MOV r6, #0 @L_sum2 = 0 + ADD r9, r1, r2, LSL #1 @p2 = &vec[pos] + MOV r10, r0 @p1 = h + RSB r11, r2, #62 @j=62-pos + +LOOPj1: + LDRSH r12, [r10], #2 + LDRSH r8, [r9], #2 + LDRSH r14, [r9] + SUBS r11, r11, #1 + MLA r5, r12, r8, r5 + MLA r6, r12, r14, r6 + BGE LOOPj1 + + LDRSH r12, [r10], #2 @*p1++ + MOV r6, r6, LSL #2 @L_sum2 = (L_sum2 << 2) + MLA r5, r12, r14, r5 + MOV r14, #0x8000 + MOV r5, r5, LSL #2 @L_sum1 = (L_sum1 << 2) + ADD r10, r6, r14 + ADD r9, r5, r14 + MOV r5, r9, ASR #16 + MOV r6, r10, ASR #16 + ADD r9, r3, r2, LSL #1 @address of sign[pos] + ADD r8, r7, #32 + LDRSH r10, [r9], #2 @sign[pos] + LDRSH r11, [r9] @sign[pos + 1] + MUL r12, r5, r10 + MUL r14, r6, r11 + MOV r5, r12, ASR #15 + MOV r6, r14, ASR #15 + LDR r9, [r13, #44] + LDR r12, [r13, #48] + LDRSH r10, [r7], #2 @*p0++ + LDRSH r11, [r8] @*p3++ + ADD r9, r9, r4, LSL #1 + ADD r12, r12, r4, LSL #1 + ADD r5, r5, r10 + ADD r6, r6, r11 + STRH r5, [r9] + STRH r6, [r12] + + ADD r2, r2, #4 + + MOV r5, #0 @L_sum1 = 0 + MOV r6, #0 @L_sum2 = 0 + ADD r9, r1, r2, LSL #1 @p2 = &vec[pos] + MOV r10, r0 @p1 = h + RSB r11, r2, #62 @j=62-pos + ADD r4, r4, #1 @i++ + +LOOPj2: + LDRSH r12, [r10], #2 + LDRSH r8, [r9], #2 + LDRSH r14, [r9] + SUBS r11, r11, #1 + MLA r5, r12, r8, r5 + MLA r6, r12, r14, r6 + BGE LOOPj2 + + LDRSH r12, [r10], #2 @*p1++ + MOV r6, r6, LSL #2 @L_sum2 = (L_sum2 << 2) + MLA r5, r12, r14, r5 + MOV r14, #0x8000 + MOV r5, r5, LSL #2 @L_sum1 = (L_sum1 << 2) + ADD r10, r6, r14 + ADD r9, r5, r14 + + MOV r5, r9, ASR #16 + MOV r6, r10, ASR #16 + ADD r9, r3, r2, LSL #1 @address of sign[pos] + ADD r8, r7, #32 + LDRSH r10, [r9], #2 @sign[pos] + LDRSH r11, [r9] @sign[pos + 1] + MUL r12, r5, r10 + MUL r14, r6, r11 + MOV r5, r12, ASR #15 + MOV r6, r14, ASR #15 + LDR r9, [r13, #44] + LDR r12, [r13, #48] + LDRSH r10, [r7], #2 @*p0++ + LDRSH r11, [r8] @*p3++ + ADD r9, r9, r4, LSL #1 + ADD r12, r12, r4, LSL #1 + ADD r5, r5, r10 + ADD r6, r6, r11 + STRH r5, [r9] + STRH r6, [r12] + ADD r4, r4, #1 @i+1 + ADD r2, r2, #4 @pos += STEP + CMP r4, #16 + + BLT LOOPi + +the_end: + LDMFD r13!, {r4 - r12, r15} + + @ENDFUNC + .END + + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s new file mode 100644 index 0000000000000000000000000000000000000000..d5dd8f0693d43b14ea52e48ce46fee9fca6941f2 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s @@ -0,0 +1,460 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@void Pred_lt4( +@ Word16 exc[], /* in/out: excitation buffer */ +@ Word16 T0, /* input : integer pitch lag */ +@ Word16 frac, /* input : fraction of lag */ +@ Word16 L_subfr /* input : subframe size */ +@ ) + +@****************************** +@ ARM Register +@****************************** +@ r0 --- exc[] +@ r1 --- T0 +@ r2 --- frac +@ r3 --- L_subfr + + .section .text + .global pred_lt4_asm + .extern inter4_2 + +pred_lt4_asm: + + STMFD r13!, {r4 - r12, r14} + RSB r4, r1, #0 @-T0 + RSB r2, r2, #0 @frac = -frac + ADD r5, r0, r4, LSL #1 @x = exc - T0 + CMP r2, #0 + ADDLT r2, r2, #4 @frac += UP_SAMP + SUBLT r5, r5, #2 @x-- + SUB r5, r5, #30 @x -= 15 + RSB r4, r2, #3 @k = 3 - frac + LDR r6, Table + MOV r8, r4, LSL #6 + @MOV r7, #0 @j = 0 + ADD r8, r6, r8 @ptr2 = &(inter4_2[k][0]) + + MOV r1, r5 + MOV r5, #0x8000 + MOV r14, #21 +@ used register + @r0 --- exc[] r1 --- x r7 --- j r8 --- ptr2 r5 --- 0x8000 +THREE_LOOP: + + @MOV r1, r5 @ptr1 = x + MOV r2, r8 @ptr = ptr2 + LDR r3, [r2], #4 @h[0], h[1] + LDRSH r4, [r1], #2 @x[0] + LDRSH r6, [r1], #2 @x[1] + LDRSH r9, [r1], #2 @x[2] + + SMULBB r10, r4, r3 @x[0] * h[0] + SMULBB r11, r6, r3 @x[1] * h[0] + SMULBB r12, r9, r3 @x[2] * h[0] + + LDRSH r4, [r1], #2 @x[3] + SMLABT r10, r6, r3, r10 @x[1] * h[1] + SMLABT r11, r9, r3, r11 @x[2] * h[1] + SMLABT r12, r4, r3, r12 @x[3] * h[1] + + LDR r3, [r2], #4 @h[2], h[3] + LDRSH r6, [r1], #2 @x[4] + SMLABB r10, r9, r3, r10 @x[2] * h[2] + SMLABB r11, r4, r3, r11 @x[3] * h[2] + SMLABB r12, r6, r3, r12 @x[4] * h[2] + + LDRSH r9, [r1], #2 @x[5] + SMLABT r10, r4, r3, r10 @x[3] * h[3] + SMLABT r11, r6, r3, r11 @x[4] * h[3] + SMLABT r12, r9, r3, r12 @x[5] * h[3] + + LDR r3, [r2], #4 @h[4], h[5] + LDRSH r4, [r1], #2 @x[6] + SMLABB r10, r6, r3, r10 @x[4] * h[4] + SMLABB r11, r9, r3, r11 @x[5] * h[4] + SMLABB r12, r4, r3, r12 @x[6] * h[4] + + LDRSH r6, [r1], #2 @x[7] + SMLABT r10, r9, r3, r10 @x[5] * h[5] + SMLABT r11, r4, r3, r11 @x[6] * h[5] + SMLABT r12, r6, r3, r12 @x[7] * h[5] + + LDR r3, [r2], #4 @h[6], h[7] + LDRSH r9, [r1], #2 @x[8] + SMLABB r10, r4, r3, r10 @x[6] * h[6] + SMLABB r11, r6, r3, r11 @x[7] * h[6] + SMLABB r12, r9, r3, r12 @x[8] * h[6] + + LDRSH r4, [r1], #2 @x[9] + SMLABT r10, r6, r3, r10 @x[7] * h[7] + SMLABT r11, r9, r3, r11 @x[8] * h[7] + SMLABT r12, r4, r3, r12 @x[9] * h[7] + + LDR r3, [r2], #4 @h[8], h[9] + LDRSH r6, [r1], #2 @x[10] + SMLABB r10, r9, r3, r10 @x[8] * h[8] + SMLABB r11, r4, r3, r11 @x[9] * h[8] + SMLABB r12, r6, r3, r12 @x[10] * h[8] + + LDRSH r9, [r1], #2 @x[11] + SMLABT r10, r4, r3, r10 @x[9] * h[9] + SMLABT r11, r6, r3, r11 @x[10] * h[9] + SMLABT r12, r9, r3, r12 @x[11] * h[9] + + LDR r3, [r2], #4 @h[10], h[11] + LDRSH r4, [r1], #2 @x[12] + SMLABB r10, r6, r3, r10 @x[10] * h[10] + SMLABB r11, r9, r3, r11 @x[11] * h[10] + SMLABB r12, r4, r3, r12 @x[12] * h[10] + + LDRSH r6, [r1], #2 @x[13] + SMLABT r10, r9, r3, r10 @x[11] * h[11] + SMLABT r11, r4, r3, r11 @x[12] * h[11] + SMLABT r12, r6, r3, r12 @x[13] * h[11] + + LDR r3, [r2], #4 @h[12], h[13] + LDRSH r9, [r1], #2 @x[14] + SMLABB r10, r4, r3, r10 @x[12] * h[12] + SMLABB r11, r6, r3, r11 @x[13] * h[12] + SMLABB r12, r9, r3, r12 @x[14] * h[12] + + LDRSH r4, [r1], #2 @x[15] + SMLABT r10, r6, r3, r10 @x[13] * h[13] + SMLABT r11, r9, r3, r11 @x[14] * h[13] + SMLABT r12, r4, r3, r12 @x[15] * h[13] + + LDR r3, [r2], #4 @h[14], h[15] + LDRSH r6, [r1], #2 @x[16] + SMLABB r10, r9, r3, r10 @x[14] * h[14] + SMLABB r11, r4, r3, r11 @x[15] * h[14] + SMLABB r12, r6, r3, r12 @x[16] * h[14] + + LDRSH r9, [r1], #2 @x[17] + SMLABT r10, r4, r3, r10 @x[15] * h[15] + SMLABT r11, r6, r3, r11 @x[16] * h[15] + SMLABT r12, r9, r3, r12 @x[17] * h[15] + + LDR r3, [r2], #4 @h[16], h[17] + LDRSH r4, [r1], #2 @x[18] + SMLABB r10, r6, r3, r10 @x[16] * h[16] + SMLABB r11, r9, r3, r11 @x[17] * h[16] + SMLABB r12, r4, r3, r12 @x[18] * h[16] + + LDRSH r6, [r1], #2 @x[19] + SMLABT r10, r9, r3, r10 @x[17] * h[17] + SMLABT r11, r4, r3, r11 @x[18] * h[17] + SMLABT r12, r6, r3, r12 @x[19] * h[17] + + LDR r3, [r2], #4 @h[18], h[19] + LDRSH r9, [r1], #2 @x[20] + SMLABB r10, r4, r3, r10 @x[18] * h[18] + SMLABB r11, r6, r3, r11 @x[19] * h[18] + SMLABB r12, r9, r3, r12 @x[20] * h[18] + + LDRSH r4, [r1], #2 @x[21] + SMLABT r10, r6, r3, r10 @x[19] * h[19] + SMLABT r11, r9, r3, r11 @x[20] * h[19] + SMLABT r12, r4, r3, r12 @x[21] * h[19] + + LDR r3, [r2], #4 @h[20], h[21] + LDRSH r6, [r1], #2 @x[22] + SMLABB r10, r9, r3, r10 @x[20] * h[20] + SMLABB r11, r4, r3, r11 @x[21] * h[20] + SMLABB r12, r6, r3, r12 @x[22] * h[20] + + LDRSH r9, [r1], #2 @x[23] + SMLABT r10, r4, r3, r10 @x[21] * h[21] + SMLABT r11, r6, r3, r11 @x[22] * h[21] + SMLABT r12, r9, r3, r12 @x[23] * h[21] + + LDR r3, [r2], #4 @h[22], h[23] + LDRSH r4, [r1], #2 @x[24] + SMLABB r10, r6, r3, r10 @x[22] * h[22] + SMLABB r11, r9, r3, r11 @x[23] * h[22] + SMLABB r12, r4, r3, r12 @x[24] * h[22] + + LDRSH r6, [r1], #2 @x[25] + SMLABT r10, r9, r3, r10 @x[23] * h[23] + SMLABT r11, r4, r3, r11 @x[24] * h[23] + SMLABT r12, r6, r3, r12 @x[25] * h[23] + + LDR r3, [r2], #4 @h[24], h[25] + LDRSH r9, [r1], #2 @x[26] + SMLABB r10, r4, r3, r10 @x[24] * h[24] + SMLABB r11, r6, r3, r11 @x[25] * h[24] + SMLABB r12, r9, r3, r12 @x[26] * h[24] + + LDRSH r4, [r1], #2 @x[27] + SMLABT r10, r6, r3, r10 @x[25] * h[25] + SMLABT r11, r9, r3, r11 @x[26] * h[25] + SMLABT r12, r4, r3, r12 @x[27] * h[25] + + LDR r3, [r2], #4 @h[26], h[27] + LDRSH r6, [r1], #2 @x[28] + SMLABB r10, r9, r3, r10 @x[26] * h[26] + SMLABB r11, r4, r3, r11 @x[27] * h[26] + SMLABB r12, r6, r3, r12 @x[28] * h[26] + + LDRSH r9, [r1], #2 @x[29] + SMLABT r10, r4, r3, r10 @x[27] * h[27] + SMLABT r11, r6, r3, r11 @x[28] * h[27] + SMLABT r12, r9, r3, r12 @x[29] * h[27] + + LDR r3, [r2], #4 @h[28], h[29] + LDRSH r4, [r1], #2 @x[30] + SMLABB r10, r6, r3, r10 @x[28] * h[28] + SMLABB r11, r9, r3, r11 @x[29] * h[28] + SMLABB r12, r4, r3, r12 @x[30] * h[28] + + LDRSH r6, [r1], #2 @x[31] + SMLABT r10, r9, r3, r10 @x[29] * h[29] + SMLABT r11, r4, r3, r11 @x[30] * h[29] + SMLABT r12, r6, r3, r12 @x[31] * h[29] + + LDR r3, [r2], #4 @h[30], h[31] + LDRSH r9, [r1], #2 @x[32] + SMLABB r10, r4, r3, r10 @x[30] * h[30] + SMLABB r11, r6, r3, r11 @x[31] * h[30] + SMLABB r12, r9, r3, r12 @x[32] * h[30] + + LDRSH r4, [r1], #-60 @x[33] + SMLABT r10, r6, r3, r10 @x[31] * h[31] + SMLABT r11, r9, r3, r11 @x[32] * h[31] + SMLABT r12, r4, r3, r12 @x[33] * h[31] + + @SSAT r10, #32, r10, LSL #2 + @SSAT r11, #32, r11, LSL #2 + @SSAT r12, #32, r12, LSL #2 + + MOV r10, r10, LSL #1 + MOV r11, r11, LSL #1 + MOV r12, r12, LSL #1 + + QADD r10, r10, r10 + QADD r11, r11, r11 + QADD r12, r12, r12 + + QADD r10, r10, r5 + QADD r11, r11, r5 + QADD r12, r12, r5 + + SUBS r14, r14, #1 + + MOV r10, r10, ASR #16 + MOV r11, r11, ASR #16 + MOV r12, r12, ASR #16 + + STRH r10, [r0], #2 + STRH r11, [r0], #2 + STRH r12, [r0], #2 + BNE THREE_LOOP + + MOV r2, r8 @ptr = ptr2 + +Last2LOOP: + + LDR r3, [r2], #4 @h[0], h[1] + LDRSH r4, [r1], #2 @x[0] + LDRSH r6, [r1], #2 @x[1] + LDRSH r9, [r1], #2 @x[2] + + SMULBB r10, r4, r3 @x[0] * h[0] + SMULBB r11, r6, r3 @x[1] * h[0] + + SMLABT r10, r6, r3, r10 @x[1] * h[1] + SMLABT r11, r9, r3, r11 @x[2] * h[1] + + LDR r3, [r2], #4 @h[2], h[3] + LDRSH r4, [r1], #2 @x[3] + LDRSH r6, [r1], #2 @x[4] + + SMLABB r10, r9, r3, r10 @x[2] * h[2] + SMLABB r11, r4, r3, r11 @x[3] * h[2] + + SMLABT r10, r4, r3, r10 @x[3] * h[3] + SMLABT r11, r6, r3, r11 @x[4] * h[3] + + LDR r3, [r2], #4 @h[4], h[5] + LDRSH r9, [r1], #2 @x[5] + LDRSH r4, [r1], #2 @x[6] + + SMLABB r10, r6, r3, r10 @x[4] * h[4] + SMLABB r11, r9, r3, r11 @x[5] * h[4] + + SMLABT r10, r9, r3, r10 @x[5] * h[5] + SMLABT r11, r4, r3, r11 @x[6] * h[5] + + LDR r3, [r2], #4 @h[6], h[7] + LDRSH r6, [r1], #2 @x[7] + LDRSH r9, [r1], #2 @x[8] + + SMLABB r10, r4, r3, r10 @x[6] * h[6] + SMLABB r11, r6, r3, r11 @x[7] * h[6] + + SMLABT r10, r6, r3, r10 @x[7] * h[7] + SMLABT r11, r9, r3, r11 @x[8] * h[7] + + LDR r3, [r2], #4 @h[8], h[9] + LDRSH r4, [r1], #2 @x[9] + LDRSH r6, [r1], #2 @x[10] + + SMLABB r10, r9, r3, r10 @x[8] * h[8] + SMLABB r11, r4, r3, r11 @x[9] * h[8] + + SMLABT r10, r4, r3, r10 @x[9] * h[9] + SMLABT r11, r6, r3, r11 @x[10] * h[9] + + LDR r3, [r2], #4 @h[10], h[11] + LDRSH r9, [r1], #2 @x[11] + LDRSH r4, [r1], #2 @x[12] + + SMLABB r10, r6, r3, r10 @x[10] * h[10] + SMLABB r11, r9, r3, r11 @x[11] * h[10] + + SMLABT r10, r9, r3, r10 @x[11] * h[11] + SMLABT r11, r4, r3, r11 @x[12] * h[11] + + LDR r3, [r2], #4 @h[12], h[13] + LDRSH r6, [r1], #2 @x[13] + LDRSH r9, [r1], #2 @x[14] + + SMLABB r10, r4, r3, r10 @x[12] * h[12] + SMLABB r11, r6, r3, r11 @x[13] * h[12] + + SMLABT r10, r6, r3, r10 @x[13] * h[13] + SMLABT r11, r9, r3, r11 @x[14] * h[13] + + LDR r3, [r2], #4 @h[14], h[15] + LDRSH r4, [r1], #2 @x[15] + LDRSH r6, [r1], #2 @x[16] + + SMLABB r10, r9, r3, r10 @x[14] * h[14] + SMLABB r11, r4, r3, r11 @x[15] * h[14] + + SMLABT r10, r4, r3, r10 @x[15] * h[15] + SMLABT r11, r6, r3, r11 @x[16] * h[15] + + LDR r3, [r2], #4 @h[16], h[17] + LDRSH r9, [r1], #2 @x[17] + LDRSH r4, [r1], #2 @x[18] + + SMLABB r10, r6, r3, r10 @x[16] * h[16] + SMLABB r11, r9, r3, r11 @x[17] * h[16] + + SMLABT r10, r9, r3, r10 @x[17] * h[17] + SMLABT r11, r4, r3, r11 @x[18] * h[17] + + LDR r3, [r2], #4 @h[18], h[19] + LDRSH r6, [r1], #2 @x[19] + LDRSH r9, [r1], #2 @x[20] + + SMLABB r10, r4, r3, r10 @x[18] * h[18] + SMLABB r11, r6, r3, r11 @x[19] * h[18] + + SMLABT r10, r6, r3, r10 @x[19] * h[19] + SMLABT r11, r9, r3, r11 @x[20] * h[19] + + LDR r3, [r2], #4 @h[20], h[21] + LDRSH r4, [r1], #2 @x[21] + LDRSH r6, [r1], #2 @x[22] + + SMLABB r10, r9, r3, r10 @x[20] * h[20] + SMLABB r11, r4, r3, r11 @x[21] * h[20] + + SMLABT r10, r4, r3, r10 @x[21] * h[21] + SMLABT r11, r6, r3, r11 @x[22] * h[21] + + LDR r3, [r2], #4 @h[22], h[23] + LDRSH r9, [r1], #2 @x[23] + LDRSH r4, [r1], #2 @x[24] + + SMLABB r10, r6, r3, r10 @x[22] * h[22] + SMLABB r11, r9, r3, r11 @x[23] * h[22] + + SMLABT r10, r9, r3, r10 @x[23] * h[23] + SMLABT r11, r4, r3, r11 @x[24] * h[23] + + LDR r3, [r2], #4 @h[24], h[25] + LDRSH r6, [r1], #2 @x[25] + LDRSH r9, [r1], #2 @x[26] + + SMLABB r10, r4, r3, r10 @x[24] * h[24] + SMLABB r11, r6, r3, r11 @x[25] * h[24] + + SMLABT r10, r6, r3, r10 @x[25] * h[25] + SMLABT r11, r9, r3, r11 @x[26] * h[25] + + LDR r3, [r2], #4 @h[26], h[27] + LDRSH r4, [r1], #2 @x[27] + LDRSH r6, [r1], #2 @x[28] + + SMLABB r10, r9, r3, r10 @x[26] * h[26] + SMLABB r11, r4, r3, r11 @x[27] * h[26] + + SMLABT r10, r4, r3, r10 @x[27] * h[27] + SMLABT r11, r6, r3, r11 @x[28] * h[27] + + LDR r3, [r2], #4 @h[28], h[29] + LDRSH r9, [r1], #2 @x[29] + LDRSH r4, [r1], #2 @x[30] + + SMLABB r10, r6, r3, r10 @x[28] * h[28] + SMLABB r11, r9, r3, r11 @x[29] * h[28] + + SMLABT r10, r9, r3, r10 @x[29] * h[29] + SMLABT r11, r4, r3, r11 @x[30] * h[29] + + LDR r3, [r2], #4 @h[30], h[31] + LDRSH r6, [r1], #2 @x[31] + LDRSH r9, [r1], #2 @x[32] + + SMLABB r10, r4, r3, r10 @x[30] * h[30] + SMLABB r11, r6, r3, r11 @x[31] * h[30] + + SMLABT r10, r6, r3, r10 @x[31] * h[31] + SMLABT r11, r9, r3, r11 @x[32] * h[31] + + @SSAT r10, #32, r10, LSL #2 + @SSAT r11, #32, r11, LSL #2 + MOV r10, r10, LSL #1 + MOV r11, r11, LSL #1 + + QADD r10, r10, r10 + QADD r11, r11, r11 + + QADD r10, r10, r5 + QADD r11, r11, r5 + + MOV r10, r10, ASR #16 + MOV r11, r11, ASR #16 + + STRH r10, [r0], #2 + STRH r11, [r0], #2 + + +pred_lt4_end: + LDMFD r13!, {r4 - r12, r15} + +Table: + .word inter4_2 + @ENDFUNC + .END + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s new file mode 100644 index 0000000000000000000000000000000000000000..060d9c775f2b5e2afbcd4765a3790ea0b7e6174d --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s @@ -0,0 +1,228 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@void Residu( +@ Word16 a[], /* (i) Q12 : prediction coefficients */ +@ Word16 x[], /* (i) : speech (values x[-m..-1] are needed */ +@ Word16 y[], /* (o) x2 : residual signal */ +@ Word16 lg /* (i) : size of filtering */ +@ ) +@a[] --- r0 +@x[] --- r1 +@y[] --- r2 +@lg --- r3 + + .section .text + .global Residu_opt + +Residu_opt: + + STMFD r13!, {r4 - r12, r14} + + LDRH r5, [r0], #2 + LDRH r6, [r0], #2 + ORR r5, r6, r5, LSL #16 @r5 --- a0, a1 + + LDRH r6, [r0], #2 + LDRH r7, [r0], #2 + ORR r6, r7, r6, LSL #16 @r6 --- a2, a3 + + LDRH r7, [r0], #2 + LDRH r8, [r0], #2 + ORR r7, r8, r7, LSL #16 @r7 --- a4, a5 + + LDRH r8, [r0], #2 + LDRH r9, [r0], #2 + ORR r8, r9, r8, LSL #16 @r8 --- a6, a7 + + LDRH r9, [r0], #2 + LDRH r10, [r0], #2 + ORR r9, r10, r9, LSL #16 @r9 --- a8, a9 + + LDRH r10, [r0], #2 + LDRH r11, [r0], #2 + ORR r10, r11, r10, LSL #16 @r10 --- a10, a11 + + LDRH r11, [r0], #2 + LDRH r12, [r0], #2 + ORR r11, r12, r11, LSL #16 @r11 --- a12, a13 + + LDRH r12, [r0], #2 + LDRH r4, [r0], #2 + ORR r12, r4, r12, LSL #16 @r12 --- a14, a15 + + + STMFD r13!, {r8 - r12} @store r8-r12 + LDRH r4, [r0], #2 @load a16 + MOV r14, r3, ASR #2 @one loop get 4 outputs + ADD r1, r1, #4 + MOV r0, r2 + ORR r14, r4, r14, LSL #16 @r14 --- loopnum, a16 + +residu_loop: + + LDR r10, [r1], #-4 @r10 --- x[3], x[2] + LDR r2, [r1], #-4 @r2 --- x[1], x[0] + + SMULTB r3, r5, r2 @i1(0) --- r3 = x[0] * a0 + SMULTT r4, r5, r2 @i2(0) --- r4 = x[1] * a0 + SMULTB r11, r5, r10 @i3(0) --- r11 = x[2] * a0 + SMULTT r12, r5, r10 @i4(0) --- r12 = x[3] * a0 + + SMLABB r4, r5, r2, r4 @i2(1) --- r4 += x[0] * a1 + SMLABT r11, r5, r2, r11 @i3(1) --- r11 += x[1] * a0 + SMLABB r12, r5, r10, r12 @i4(1) --- r12 += x[2] * a1 + + SMLATB r11, r6, r2, r11 @i3(2) --- r11 += x[0] * a2 + SMLATT r12, r6, r2, r12 @i4(2) --- r12 += x[1] * a2 + SMLABB r12, r6, r2, r12 @i4(3) --- r12 += x[0] * a3 + + LDR r2, [r1], #-4 @r2 ---- x[-1], x[-2] + + SMLABT r3, r5, r2, r3 @i1(1) --- r3 += x[-1] * a1 + SMLATT r4, r6, r2, r4 @i2(2) --- r4 += x[-1] * a2 + SMLABT r11, r6, r2, r11 @i3(3) --- r11 += x[-1] * a3 + SMLATT r12, r7, r2, r12 @i4(4) --- r12 += x[-1] * a4 + SMLATB r3, r6, r2, r3 @i1(2) --- r3 += x[-2] * a2 + + SMLABB r4, r6, r2, r4 @ i2 (3) + SMLATB r11,r7, r2, r11 @ i3 (4) + SMLABB r12,r7, r2, r12 @ i4 (5) + + LDR r2,[r1],#-4 + SMLABT r3, r6, r2, r3 @ i1 (3) + SMLATT r4, r7, r2, r4 @ i2 (4) + SMLABT r11,r7, r2, r11 @ i3 (5) + SMLATT r12,r8, r2, r12 @ i4 (6) + SMLATB r3, r7, r2, r3 @ i1 (4) + SMLABB r4, r7, r2, r4 @ i2 (5) + SMLATB r11,r8, r2, r11 @ i3 (6) + SMLABB r12,r8, r2, r12 @ i4 (7) + + LDR r2,[r1],#-4 + SMLABT r3, r7, r2, r3 @ i1 (5) + SMLATT r4, r8, r2, r4 @ i2 (6) + SMLABT r11,r8, r2, r11 @ i3 (7) + SMLATT r12,r9, r2, r12 @ i4 (8) + SMLATB r3, r8, r2, r3 @ i1 (6) + SMLABB r4, r8, r2, r4 @ i2 (7) + SMLATB r11,r9, r2, r11 @ i3 (8) + SMLABB r12,r9, r2, r12 @ i4 (9) + LDR r10, [r13, #8] @ [ a10 | a11] + + LDR r2,[r1],#-4 + SMLABT r3, r8, r2, r3 @ i1 (7) + SMLATT r4, r9, r2, r4 @ i2 (8) + SMLABT r11,r9, r2, r11 @ i3 (9) + SMLATT r12,r10, r2, r12 @ i4 (10) + SMLATB r3, r9, r2, r3 @ i1 (8) + SMLABB r4, r9, r2, r4 @ i2 (9) + SMLATB r11,r10, r2, r11 @ i3 (10) + SMLABB r12,r10, r2, r12 @ i4 (11) + LDR r8, [r13, #12] @ [ a12 | a13 ] + + LDR r2,[r1],#-4 + SMLABT r3, r9, r2, r3 @ i1 (9) + SMLATT r4, r10, r2, r4 @ i2 (10) + SMLABT r11,r10, r2, r11 @ i3 (11) + SMLATT r12,r8, r2, r12 @ i4 (12) + SMLATB r3, r10, r2, r3 @ i1 (10) + SMLABB r4, r10, r2, r4 @ i2 (11) + SMLATB r11,r8, r2, r11 @ i3 (12) + SMLABB r12,r8, r2, r12 @ i4 (13) + LDR r9, [r13, #16] @ [ a14 | a15 ] + + LDR r2,[r1],#-4 + SMLABT r3, r10, r2, r3 @ i1 (11) + SMLATT r4, r8, r2, r4 @ i2 (12) + SMLABT r11,r8, r2, r11 @ i3 (13) + SMLATT r12,r9, r2, r12 @ i4 (14) + SMLATB r3, r8, r2, r3 @ i1 (12) + SMLABB r4, r8, r2, r4 @ i2 (13) + SMLATB r11,r9, r2, r11 @ i3 (14) + SMLABB r12,r9, r2, r12 @ i4 (15) + + + LDR r2,[r1],#-4 + SMLABT r3, r8, r2, r3 @ i1 (13) + SMLATT r4, r9, r2, r4 @ i2 (14) + SMLABT r11,r9, r2, r11 @ i3 (15) + SMLABT r12,r14, r2, r12 @ i4 (16) + SMLATB r3, r9, r2, r3 @ i1 (14) + SMLABB r4, r9, r2, r4 @ i2 (15) + SMLABB r11,r14, r2, r11 @ i3 (16) + LDR r8, [r13] @ [ a6 | a7 ] + + LDR r2,[r1],#44 @ Change + SMLABT r3, r9, r2, r3 + SMLABB r3, r14, r2, r3 + SMLABT r4, r14, r2, r4 + LDR r9, [r13, #4] @ [ a8 | a9 ] + + + QADD r3,r3,r3 + QADD r4,r4,r4 + QADD r11,r11,r11 + QADD r12,r12,r12 + + QADD r3,r3,r3 + QADD r4,r4,r4 + QADD r11,r11,r11 + QADD r12,r12,r12 + + QADD r3,r3,r3 + QADD r4,r4,r4 + QADD r11,r11,r11 + QADD r12,r12,r12 + + QADD r3,r3,r3 + QADD r4,r4,r4 + QADD r11,r11,r11 + QADD r12,r12,r12 + + MOV r2,#32768 + + QDADD r3,r2,r3 + QDADD r4,r2,r4 + QDADD r11,r2,r11 + QDADD r12,r2,r12 + + + MOV r3,r3,asr #16 + MOV r4,r4,asr #16 + MOV r11,r11,asr #16 + MOV r12,r12,asr #16 + + STRH r3,[r0],#2 + STRH r4,[r0],#2 + STRH r11,[r0],#2 + STRH r12,[r0],#2 + + MOV r2,r14,asr #16 + SUB r14, r14, #0x10000 + SUBS r2,r2,#1 + BNE residu_loop +end: + LDMFD r13!, {r8 -r12} + LDMFD r13!, {r4 -r12,pc} + + @ENDFUNC + .END + + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s new file mode 100644 index 0000000000000000000000000000000000000000..aa9f4644d3f9b26939ccded1140fc74ef2a8f810 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s @@ -0,0 +1,75 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@void Scale_sig( +@ Word16 x[], /* (i/o) : signal to scale */ +@ Word16 lg, /* (i) : size of x[] */ +@ Word16 exp /* (i) : exponent: x = round(x << exp) */ +@ ) +@ +@r0 --- x[] +@r1 --- lg +@r2 --- exp + + .section .text + .global Scale_sig_opt + +Scale_sig_opt: + + STMFD r13!, {r4 - r12, r14} + SUB r3, r1, #1 @i = lg - 1 + CMP r2, #0 @Compare exp and 0 + RSB r7, r2, #0 @exp = -exp + ADD r10, r2, #16 @16 + exp + ADD r4, r0, r3, LSL #1 @x[i] address + MOV r8, #0x7fffffff + MOV r9, #0x8000 + BLE LOOP2 + +LOOP1: + + LDRSH r5, [r4] @load x[i] + MOV r12, r5, LSL r10 + TEQ r5, r12, ASR r10 + EORNE r12, r8, r5, ASR #31 + SUBS r3, r3, #1 + QADD r11, r12, r9 + MOV r12, r11, ASR #16 + STRH r12, [r4], #-2 + BGE LOOP1 + BL The_end + +LOOP2: + + LDRSH r5, [r4] @load x[i] + MOV r6, r5, LSL #16 @L_tmp = x[i] << 16 + MOV r5, r6, ASR r7 @L_tmp >>= exp + QADD r11, r5, r9 + MOV r12, r11, ASR #16 + SUBS r3, r3, #1 + STRH r12, [r4], #-2 + BGE LOOP2 + +The_end: + LDMFD r13!, {r4 - r12, r15} + + @ENDFUNC + .END + + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s new file mode 100644 index 0000000000000000000000000000000000000000..e05e9e022ede49380260d6cadd980c0dc5a85478 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s @@ -0,0 +1,238 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@**********************************************************************/ +@void Syn_filt( +@ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */ +@ Word16 x[], /* (i) : input signal */ +@ Word16 y[], /* (o) : output signal */ +@ Word16 mem[], /* (i/o) : memory associated with this filtering. */ +@) +@*********************************************************************** +@ a[] --- r0 +@ x[] --- r1 +@ y[] --- r2 +@ mem[] --- r3 +@ m --- 16 lg --- 80 update --- 1 + + .section .text + .global Syn_filt_asm + .extern voAWB_Copy + +Syn_filt_asm: + + STMFD r13!, {r4 - r12, r14} + SUB r13, r13, #700 @ y_buf[L_FRAME16k + M16k] + + MOV r4, r3 @ copy mem[] address + MOV r5, r13 @ copy yy = y_buf address + + @ for(i = 0@ i < m@ i++) + @{ + @ *yy++ = mem[i]@ + @} + + LDRH r6, [r4], #2 + LDRH r7, [r4], #2 + LDRH r8, [r4], #2 + LDRH r9, [r4], #2 + LDRH r10, [r4], #2 + LDRH r11, [r4], #2 + LDRH r12, [r4], #2 + LDRH r14, [r4], #2 + + STRH r6, [r5], #2 + STRH r7, [r5], #2 + STRH r8, [r5], #2 + STRH r9, [r5], #2 + STRH r10, [r5], #2 + STRH r11, [r5], #2 + STRH r12, [r5], #2 + STRH r14, [r5], #2 + + LDRH r6, [r4], #2 + LDRH r7, [r4], #2 + LDRH r8, [r4], #2 + LDRH r9, [r4], #2 + LDRH r10, [r4], #2 + LDRH r11, [r4], #2 + LDRH r12, [r4], #2 + LDRH r14, [r4], #2 + + STRH r6, [r5], #2 + STRH r7, [r5], #2 + STRH r8, [r5], #2 + STRH r9, [r5], #2 + STRH r10, [r5], #2 + STRH r11, [r5], #2 + STRH r12, [r5], #2 + STRH r14, [r5], #2 + + LDRSH r5, [r0] @ load a[0] + MOV r8, #0 @ i = 0 + MOV r5, r5, ASR #1 @ a0 = a[0] >> 1 + @MOV r4, r13 + @ load all a[] + + LDR r14, =0xffff + LDRSH r6, [r0, #2] @ load a[1] + LDRSH r7, [r0, #4] @ load a[2] + LDRSH r9, [r0, #6] @ load a[3] + LDRSH r11,[r0, #8] @ load a[4] + AND r6, r6, r14 + AND r9, r9, r14 + ORR r10, r6, r7, LSL #16 @ -a[2] -- -a[1] + ORR r12, r9, r11, LSL #16 @ -a[4] -- -a[3] + STR r10, [r13, #-4] + STR r12, [r13, #-8] + + LDRSH r6, [r0, #10] @ load a[5] + LDRSH r7, [r0, #12] @ load a[6] + LDRSH r9, [r0, #14] @ load a[7] + LDRSH r11,[r0, #16] @ load a[8] + AND r6, r6, r14 + AND r9, r9, r14 + ORR r10, r6, r7, LSL #16 @ -a[6] -- -a[5] + ORR r12, r9, r11, LSL #16 @ -a[8] -- -a[7] + STR r10, [r13, #-12] + STR r12, [r13, #-16] + + LDRSH r6, [r0, #18] @ load a[9] + LDRSH r7, [r0, #20] @ load a[10] + LDRSH r9, [r0, #22] @ load a[11] + LDRSH r11,[r0, #24] @ load a[12] + AND r6, r6, r14 + AND r9, r9, r14 + ORR r10, r6, r7, LSL #16 @ -a[10] -- -a[9] + ORR r12, r9, r11, LSL #16 @ -a[12] -- -a[11] + STR r10, [r13, #-20] + STR r12, [r13, #-24] + + LDRSH r6, [r0, #26] @ load a[13] + LDRSH r7, [r0, #28] @ load a[14] + LDRSH r9, [r0, #30] @ load a[15] + LDRSH r11,[r0, #32] @ load a[16] + AND r6, r6, r14 + AND r9, r9, r14 + ORR r10, r6, r7, LSL #16 @ -a[14] -- -a[13] + ORR r12, r9, r11, LSL #16 @ -a[16] -- -a[15] + STR r10, [r13, #-28] + STR r12, [r13, #-32] + + ADD r4, r13, #32 +LOOP: + LDRSH r6, [r1], #2 @ load x[i] + ADD r10, r4, r8, LSL #1 @ temp_p = yy + i + + MUL r0, r5, r6 @ L_tmp = x[i] * a0 + @ for(j = 1@ j <= m, j+=8) + LDR r7, [r13, #-4] @ -a[2] -a[1] + LDRSH r9, [r10, #-2] @ *(temp_p - 1) + LDRSH r12, [r10, #-4] @ *(temp_p - 2) + + + SMULBB r14, r9, r7 @ -a[1] * (*(temp_p -1)) + + LDRSH r6, [r10, #-6] @ *(temp_p - 3) + + SMLABT r14, r12, r7, r14 @ -a[2] * (*(temp_p - 2)) + + LDR r7, [r13, #-8] @ -a[4] -a[3] + LDRSH r11, [r10, #-8] @ *(temp_p - 4) + + SMLABB r14, r6, r7, r14 @ -a[3] * (*(temp_p -3)) + + LDRSH r9, [r10, #-10] @ *(temp_p - 5) + + SMLABT r14, r11, r7, r14 @ -a[4] * (*(temp_p -4)) + + LDR r7, [r13, #-12] @ -a[6] -a[5] + LDRSH r12, [r10, #-12] @ *(temp_p - 6) + + SMLABB r14, r9, r7, r14 @ -a[5] * (*(temp_p -5)) + + LDRSH r6, [r10, #-14] @ *(temp_p - 7) + + SMLABT r14, r12, r7, r14 @ -a[6] * (*(temp_p - 6)) + + LDR r7, [r13, #-16] @ -a[8] -a[7] + LDRSH r11, [r10, #-16] @ *(temp_p - 8) + + SMLABB r14, r6, r7, r14 @ -a[7] * (*(temp_p -7)) + + LDRSH r9, [r10, #-18] @ *(temp_p - 9) + + SMLABT r14, r11, r7, r14 @ -a[8] * (*(temp_p -8)) + + LDR r7, [r13, #-20] @ -a[10] -a[9] + LDRSH r12, [r10, #-20] @ *(temp_p - 10) + + SMLABB r14, r9, r7, r14 @ -a[9] * (*(temp_p -9)) + + LDRSH r6, [r10, #-22] @ *(temp_p - 11) + + SMLABT r14, r12, r7, r14 @ -a[10] * (*(temp_p - 10)) + + LDR r7, [r13, #-24] @ -a[12] -a[11] + LDRSH r11, [r10, #-24] @ *(temp_p - 12) + + SMLABB r14, r6, r7, r14 @ -a[11] * (*(temp_p -11)) + + LDRSH r9, [r10, #-26] @ *(temp_p - 13) + + SMLABT r14, r11, r7, r14 @ -a[12] * (*(temp_p -12)) + + LDR r7, [r13, #-28] @ -a[14] -a[13] + LDRSH r12, [r10, #-28] @ *(temp_p - 14) + + SMLABB r14, r9, r7, r14 @ -a[13] * (*(temp_p -13)) + + LDRSH r6, [r10, #-30] @ *(temp_p - 15) + + SMLABT r14, r12, r7, r14 @ -a[14] * (*(temp_p - 14)) + + LDR r7, [r13, #-32] @ -a[16] -a[15] + LDRSH r11, [r10, #-32] @ *(temp_p - 16) + + SMLABB r14, r6, r7, r14 @ -a[15] * (*(temp_p -15)) + + SMLABT r14, r11, r7, r14 @ -a[16] * (*(temp_p -16)) + + RSB r14, r14, r0 + + MOV r7, r14, LSL #4 @ L_tmp <<=4 + ADD r8, r8, #1 + ADD r14, r7, #0x8000 + MOV r7, r14, ASR #16 @ (L_tmp + 0x8000) >> 16 + CMP r8, #80 + STRH r7, [r10] @ yy[i] + STRH r7, [r2], #2 @ y[i] + BLT LOOP + + @ update mem[] + ADD r5, r13, #160 @ yy[64] address + MOV r1, r3 + MOV r0, r5 + MOV r2, #16 + BL voAWB_Copy + +Syn_filt_asm_end: + + ADD r13, r13, #700 + LDMFD r13!, {r4 - r12, r15} + @ENDFUNC + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s new file mode 100644 index 0000000000000000000000000000000000000000..acb60c32ee1d11489f9e59e2d6ff1d041dd20100 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s @@ -0,0 +1,102 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@void Deemph_32( +@ Word16 x_hi[], /* (i) : input signal (bit31..16) */ +@ Word16 x_lo[], /* (i) : input signal (bit15..4) */ +@ Word16 y[], /* (o) : output signal (x16) */ +@ Word16 mu, /* (i) Q15 : deemphasis factor */ +@ Word16 L, /* (i) : vector size */ +@ Word16 * mem /* (i/o) : memory (y[-1]) */ +@ ) + +@x_hi RN R0 +@x_lo RN R1 +@y[] RN R2 +@*mem RN R3 + + .section .text + .global Deemph_32_asm + +Deemph_32_asm: + + STMFD r13!, {r4 - r12, r14} + MOV r4, #2 @i=0 + LDRSH r6, [r0], #2 @load x_hi[0] + LDRSH r7, [r1], #2 @load x_lo[0] + LDR r5, =22282 @r5---mu + MOV r11, #0x8000 + + @y[0] + MOV r10, r6, LSL #16 @L_tmp = x_hi[0]<<16 + MOV r8, r5, ASR #1 @fac = mu >> 1 + LDR r5, [r3] + ADD r12, r10, r7, LSL #4 @L_tmp += x_lo[0] << 4 + MOV r10, r12, LSL #3 @L_tmp <<= 3 + MUL r9, r5, r8 + LDRSH r6, [r0], #2 @load x_hi[1] + QDADD r10, r10, r9 + LDRSH r7, [r1], #2 @load x_lo[1] + MOV r12, r10, LSL #1 @L_tmp = L_mac(L_tmp, *mem, fac) + QADD r10, r12, r11 + MOV r14, r10, ASR #16 @y[0] = round(L_tmp) + + + MOV r10, r6, LSL #16 + ADD r12, r10, r7, LSL #4 + STRH r14, [r2], #2 @update y[0] + MOV r10, r12, LSL #3 + MUL r9, r14, r8 + QDADD r10, r10, r9 + MOV r12, r10, LSL #1 + QADD r10, r12, r11 + MOV r14, r10, ASR #16 @y[1] = round(L_tmp) + +LOOP: + LDRSH r6, [r0], #2 @load x_hi[] + LDRSH r7, [r1], #2 + STRH r14, [r2], #2 + MOV r10, r6, LSL #16 + ADD r12, r10, r7, LSL #4 + MUL r9, r14, r8 + MOV r10, r12, LSL #3 + QDADD r10, r10, r9 + LDRSH r6, [r0], #2 @load x_hi[] + MOV r12, r10, LSL #1 + QADD r10, r12, r11 + LDRSH r7, [r1], #2 + MOV r14, r10, ASR #16 + + MOV r10, r6, LSL #16 + ADD r12, r10, r7, LSL #4 + STRH r14, [r2], #2 + MUL r9, r14, r8 + MOV r10, r12, LSL #3 + QDADD r10, r10, r9 + ADD r4, r4, #2 + MOV r12, r10, LSL #1 + QADD r10, r12, r11 + CMP r4, #64 + MOV r14, r10, ASR #16 + + BLT LOOP + STR r14, [r3] + STRH r14, [r2] + + LDMFD r13!, {r4 - r12, r15} + + .END + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s new file mode 100644 index 0000000000000000000000000000000000000000..07ca34483e91e1780753b283210f42565a3dd2f8 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s @@ -0,0 +1,127 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@**********************************************************************/ +@Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */ +@ Word16 x[], /* (i) 12bits: x vector */ +@ Word16 y[], /* (i) 12bits: y vector */ +@ Word16 lg, /* (i) : vector length */ +@ Word16 * exp /* (o) : exponent of result (0..+30) */ +@) +@************************************************************************ +@ x[] --- r0 +@ y[] --- r1 +@ lg --- r2 +@ *exp --- r3 + + .section .text + .global Dot_product12_asm + +Dot_product12_asm: + + STMFD r13!, {r4 - r12, r14} + CMP r0, r1 + BEQ LOOP_EQ + + VLD1.S16 {Q0, Q1}, [r0]! @load 16 Word16 x[] + VLD1.S16 {Q2, Q3}, [r0]! @load 16 Word16 x[] + VLD1.S16 {Q4, Q5}, [r0]! @load 16 Word16 x[] + VLD1.S16 {Q6, Q7}, [r0]! @load 16 Word16 x[] + VLD1.S16 {Q8, Q9}, [r1]! @load 16 Word16 y[] + VLD1.S16 {Q10, Q11}, [r1]! @load 16 Word16 y[] + VLD1.S16 {Q12, Q13}, [r1]! @load 16 Word16 y[] + + VMULL.S16 Q15, D16, D0 + VMLAL.S16 Q15, D17, D1 + VMLAL.S16 Q15, D18, D2 + VMLAL.S16 Q15, D19, D3 + VLD1.S16 {Q0, Q1}, [r1]! @load 16 Word16 y[] + VMLAL.S16 Q15, D20, D4 + VMLAL.S16 Q15, D21, D5 + VMLAL.S16 Q15, D22, D6 + VMLAL.S16 Q15, D23, D7 + VMLAL.S16 Q15, D24, D8 + VMLAL.S16 Q15, D25, D9 + VMLAL.S16 Q15, D26, D10 + VMLAL.S16 Q15, D27, D11 + VMLAL.S16 Q15, D0, D12 + VMLAL.S16 Q15, D1, D13 + VMLAL.S16 Q15, D2, D14 + VMLAL.S16 Q15, D3, D15 + + CMP r2, #64 + BEQ Lable1 + VLD1.S16 {Q0, Q1}, [r0]! @load 16 Word16 x[] + VLD1.S16 {Q2, Q3}, [r1]! + VMLAL.S16 Q15, D4, D0 + VMLAL.S16 Q15, D5, D1 + VMLAL.S16 Q15, D6, D2 + VMLAL.S16 Q15, D7, D3 + BL Lable1 + +LOOP_EQ: + VLD1.S16 {Q0, Q1}, [r0]! + VLD1.S16 {Q2, Q3}, [r0]! + VLD1.S16 {Q4, Q5}, [r0]! + VLD1.S16 {Q6, Q7}, [r0]! + VMULL.S16 Q15, D0, D0 + VMLAL.S16 Q15, D1, D1 + VMLAL.S16 Q15, D2, D2 + VMLAL.S16 Q15, D3, D3 + VMLAL.S16 Q15, D4, D4 + VMLAL.S16 Q15, D5, D5 + VMLAL.S16 Q15, D6, D6 + VMLAL.S16 Q15, D7, D7 + VMLAL.S16 Q15, D8, D8 + VMLAL.S16 Q15, D9, D9 + VMLAL.S16 Q15, D10, D10 + VMLAL.S16 Q15, D11, D11 + VMLAL.S16 Q15, D12, D12 + VMLAL.S16 Q15, D13, D13 + VMLAL.S16 Q15, D14, D14 + VMLAL.S16 Q15, D15, D15 + + CMP r2, #64 + BEQ Lable1 + VLD1.S16 {Q0, Q1}, [r0]! + VMLAL.S16 Q15, D0, D0 + VMLAL.S16 Q15, D1, D1 + VMLAL.S16 Q15, D2, D2 + VMLAL.S16 Q15, D3, D3 + +Lable1: + + VQADD.S32 D30, D30, D31 + VPADD.S32 D30, D30, D30 + VMOV.S32 r12, D30[0] + + ADD r12, r12, r12 + ADD r12, r12, #1 @ L_sum = (L_sum << 1) + 1 + MOV r4, r12 + CMP r12, #0 + RSBLT r4, r12, #0 + CLZ r10, r4 + SUB r10, r10, #1 @ sft = norm_l(L_sum) + MOV r0, r12, LSL r10 @ L_sum = L_sum << sft + RSB r11, r10, #30 @ *exp = 30 - sft + STRH r11, [r3] + +Dot_product12_end: + + LDMFD r13!, {r4 - r12, r15} + + .END + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s new file mode 100644 index 0000000000000000000000000000000000000000..1880024e2ec821e15609f52ebeaa05a6fc104b55 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s @@ -0,0 +1,228 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@**********************************************************************/ +@void Filt_6k_7k( +@ Word16 signal[], /* input: signal */ +@ Word16 lg, /* input: length of input */ +@ Word16 mem[] /* in/out: memory (size=30) */ +@) +@*********************************************************************** +@ r0 --- signal[] +@ r1 --- lg +@ r2 --- mem[] + + .section .text + .global Filt_6k_7k_asm + .extern fir_6k_7k + +Filt_6k_7k_asm: + + STMFD r13!, {r0 - r12, r14} + SUB r13, r13, #240 @ x[L_SUBFR16k + (L_FIR - 1)] + MOV r8, r0 @ copy signal[] address + MOV r5, r2 @ copy mem[] address + + MOV r0, r2 + MOV r1, r13 + + VLD1.S16 {D0, D1, D2, D3}, [r0]! + VLD1.S16 {D4, D5, D6, D7}, [r0]! + + VST1.S16 {D0, D1, D2, D3}, [r1]! + VST1.S16 {D4, D5, D6}, [r1]! + VST1.S16 D7[0], [r1]! + VST1.S16 D7[1], [r1]! + + + + LDR r10, Lable1 @ get fir_7k address + MOV r3, r8 @ change myMemCopy to Copy, due to Copy will change r3 content + ADD r6, r13, #60 @ get x[L_FIR - 1] address + MOV r7, r3 @ get signal[i] + @for (i = lg - 1@ i >= 0@ i--) + @{ + @ x[i + L_FIR - 1] = signal[i] >> 2@ + @} + VLD1.S16 {Q0, Q1}, [r7]! @ signal[0] ~ signal[15] + VLD1.S16 {Q2, Q3}, [r7]! @ signal[16] ~ signal[31] + VLD1.S16 {Q4, Q5}, [r7]! @ signal[32] ~ signal[47] + VLD1.S16 {Q6, Q7}, [r7]! @ signal[48] ~ signal[63] + VLD1.S16 {Q8, Q9}, [r7]! @ signal[64] ~ signal[79] + VSHR.S16 Q10, Q0, #2 + VSHR.S16 Q11, Q1, #2 + VSHR.S16 Q12, Q2, #2 + VSHR.S16 Q13, Q3, #2 + VST1.S16 {Q10, Q11}, [r6]! + VSHR.S16 Q0, Q4, #2 + VSHR.S16 Q1, Q5, #2 + VSHR.S16 Q10, Q6, #2 + VSHR.S16 Q11, Q7, #2 + VSHR.S16 Q2, Q8, #2 + VSHR.S16 Q3, Q9, #2 + VST1.S16 {Q12, Q13}, [r6]! + VST1.S16 {Q0, Q1}, [r6]! + VST1.S16 {Q10, Q11}, [r6]! + VST1.S16 {Q2, Q3}, [r6]! + + MOV r12, r5 + @STR r5, [sp, #-4] @ PUSH r5 to stack + @ not use registers: r4, r10, r12, r14, r5 + MOV r4, r13 + MOV r5, #0 @ i = 0 + + @ r4 --- x[i], r10 ---- fir_6k_7k + VLD1.S16 {Q0, Q1}, [r10]! @fir_6k_7k[0] ~ fir_6k_7k[15] + VLD1.S16 {Q2, Q3}, [r10]! @fir_6k_7k[16] ~ fir_6k_7k[31] + VMOV.S16 D7[3], r5 @set fir_6k_7K = 0 + + VLD1.S16 {Q4, Q5}, [r4]! @x[0] ~ x[15] + VLD1.S16 {Q6, Q7}, [r4]! @x[16] ~ X[31] + VLD1.S16 {Q8}, [r4]! + VMOV.S16 Q15, #0 + +LOOP_6K7K: + + VMULL.S16 Q9,D8,D0[0] + VMULL.S16 Q10,D9,D1[0] + VMULL.S16 Q11,D9,D0[0] + VMULL.S16 Q12,D10,D1[0] + VEXT.8 Q4,Q4,Q5,#2 + VMLAL.S16 Q9,D10,D2[0] + VMLAL.S16 Q10,D11,D3[0] + VMLAL.S16 Q11,D11,D2[0] + VMLAL.S16 Q12,D12,D3[0] + VEXT.8 Q5,Q5,Q6,#2 + VMLAL.S16 Q9,D12,D4[0] + VMLAL.S16 Q10,D13,D5[0] + VMLAL.S16 Q11,D13,D4[0] + VMLAL.S16 Q12,D14,D5[0] + VEXT.8 Q6,Q6,Q7,#2 + VMLAL.S16 Q9,D14,D6[0] + VMLAL.S16 Q10,D15,D7[0] + VMLAL.S16 Q11,D15,D6[0] + VMLAL.S16 Q12,D16,D7[0] + VEXT.8 Q7,Q7,Q8,#2 + + VMLAL.S16 Q9,D8,D0[1] + VMLAL.S16 Q10,D9,D1[1] + VEXT.8 Q8,Q8,Q15,#2 + VMLAL.S16 Q11,D9,D0[1] + VMLAL.S16 Q12,D10,D1[1] + VEXT.8 Q4,Q4,Q5,#2 + VMLAL.S16 Q9,D10,D2[1] + VMLAL.S16 Q10,D11,D3[1] + VMLAL.S16 Q11,D11,D2[1] + VMLAL.S16 Q12,D12,D3[1] + VEXT.8 Q5,Q5,Q6,#2 + VMLAL.S16 Q9,D12,D4[1] + VMLAL.S16 Q10,D13,D5[1] + VMLAL.S16 Q11,D13,D4[1] + VMLAL.S16 Q12,D14,D5[1] + VEXT.8 Q6,Q6,Q7,#2 + VMLAL.S16 Q9,D14,D6[1] + VMLAL.S16 Q10,D15,D7[1] + VMLAL.S16 Q11,D15,D6[1] + VMLAL.S16 Q12,D16,D7[1] + VEXT.8 Q7,Q7,Q8,#2 + + VMLAL.S16 Q9,D8,D0[2] + VMLAL.S16 Q10,D9,D1[2] + VEXT.8 Q8,Q8,Q15,#2 + VMLAL.S16 Q11,D9,D0[2] + VMLAL.S16 Q12,D10,D1[2] + VEXT.8 Q4,Q4,Q5,#2 + VMLAL.S16 Q9,D10,D2[2] + VMLAL.S16 Q10,D11,D3[2] + VMLAL.S16 Q11,D11,D2[2] + VMLAL.S16 Q12,D12,D3[2] + VEXT.8 Q5,Q5,Q6,#2 + VMLAL.S16 Q9,D12,D4[2] + VMLAL.S16 Q10,D13,D5[2] + VMLAL.S16 Q11,D13,D4[2] + VMLAL.S16 Q12,D14,D5[2] + VEXT.8 Q6,Q6,Q7,#2 + VMLAL.S16 Q9,D14,D6[2] + VMLAL.S16 Q10,D15,D7[2] + VMLAL.S16 Q11,D15,D6[2] + VMLAL.S16 Q12,D16,D7[2] + VEXT.8 Q7,Q7,Q8,#2 + + VMLAL.S16 Q9,D8,D0[3] + VMLAL.S16 Q10,D9,D1[3] + VEXT.8 Q8,Q8,Q15,#2 + VMLAL.S16 Q11,D9,D0[3] + VMLAL.S16 Q12,D10,D1[3] + VEXT.8 Q4,Q4,Q5,#2 + VMLAL.S16 Q9,D10,D2[3] + VMLAL.S16 Q10,D11,D3[3] + VMLAL.S16 Q11,D11,D2[3] + VMLAL.S16 Q12,D12,D3[3] + VEXT.8 Q5,Q5,Q6,#2 + VMLAL.S16 Q9,D12,D4[3] + VMLAL.S16 Q10,D13,D5[3] + VMLAL.S16 Q11,D13,D4[3] + VMLAL.S16 Q12,D14,D5[3] + VEXT.8 Q6,Q6,Q7,#2 + VMLAL.S16 Q9,D14,D6[3] + VMLAL.S16 Q10,D15,D7[3] + VMLAL.S16 Q11,D15,D6[3] + VMLAL.S16 Q12,D16,D7[3] + VEXT.8 Q7,Q7,Q8,#2 + + VMOV.S16 D8,D9 + VEXT.8 Q8,Q8,Q15,#2 + VMOV.S16 D9,D10 + VADD.S32 Q9,Q9,Q10 + VMOV.S16 D10,D11 + VMOV.S16 D11,D12 + VADD.S32 Q11,Q11,Q12 + VMOV.S16 D12,D13 + VQRSHRN.S32 D28,Q9,#15 + VMOV.S16 D13,D14 + VMOV.S16 D14,D15 + VQRSHRN.S32 D29,Q11,#15 + VMOV.S16 D15,D16 + + VLD1.S16 {Q8},[r4]! + ADD r5, r5, #8 + CMP r5, #80 + VST1.S16 {D28,D29},[r3]! + BLT LOOP_6K7K + + ADD r0, r13, #160 @x + lg + MOV r1, r12 + @LDR r1, [sp, #-4] @mem address + + VLD1.S16 {D0, D1, D2, D3}, [r0]! + VLD1.S16 {D4, D5, D6, D7}, [r0]! + + VST1.S16 {D0, D1, D2, D3}, [r1]! + VST1.S16 {D4, D5, D6}, [r1]! + VST1.S16 D7[0], [r1]! + VST1.S16 D7[1], [r1]! + +Filt_6k_7k_end: + + ADD r13, r13, #240 + LDMFD r13!, {r0 - r12, r15} + +Lable1: + .word fir_6k_7k + @ENDFUNC + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s new file mode 100644 index 0000000000000000000000000000000000000000..60e9adec166a1436d6198aa0e9cc786869993a23 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s @@ -0,0 +1,270 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@static void Norm_Corr (Word16 exc[], /* (i) : excitation buffer */ +@ Word16 xn[], /* (i) : target vector */ +@ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */ +@ Word16 L_subfr, /* (i) : sub-frame length */ +@ Word16 t_min, /* (i) : minimum value of pitch lag. */ +@ Word16 t_max, /* (i) : maximum value of pitch lag. */ +@ Word16 corr_norm[]) /* (o) Q15 : normalized correlation */ +@ + +@ r0 --- exc[] +@ r1 --- xn[] +@ r2 --- h[] +@ r3 --- L_subfr +@ r4 --- t_min +@ r5 --- t_max +@ r6 --- corr_norm[] + + + .section .text + .global Norm_corr_asm + .extern Convolve_asm + .extern Isqrt_n +@****************************** +@ constant +@****************************** +.equ EXC , 0 +.equ XN , 4 +.equ H , 8 +.equ L_SUBFR , 12 +.equ voSTACK , 172 +.equ T_MIN , 212 +.equ T_MAX , 216 +.equ CORR_NORM , 220 + +Norm_corr_asm: + + STMFD r13!, {r4 - r12, r14} + SUB r13, r13, #voSTACK + + ADD r8, r13, #20 @get the excf[L_SUBFR] + LDR r4, [r13, #T_MIN] @get t_min + RSB r11, r4, #0 @k = -t_min + ADD r5, r0, r11, LSL #1 @get the &exc[k] + + @transfer Convolve function + STMFD sp!, {r0 - r3} + MOV r0, r5 + MOV r1, r2 + MOV r2, r8 @r2 --- excf[] + BL Convolve_asm + LDMFD sp!, {r0 - r3} + + @ r8 --- excf[] + + MOV r14, r1 @copy xn[] address + MOV r7, #1 + VLD1.S16 {Q0, Q1}, [r14]! + VLD1.S16 {Q2, Q3}, [r14]! + VLD1.S16 {Q4, Q5}, [r14]! + VLD1.S16 {Q6, Q7}, [r14]! + + VMULL.S16 Q10, D0, D0 + VMLAL.S16 Q10, D1, D1 + VMLAL.S16 Q10, D2, D2 + VMLAL.S16 Q10, D3, D3 + VMLAL.S16 Q10, D4, D4 + VMLAL.S16 Q10, D5, D5 + VMLAL.S16 Q10, D6, D6 + VMLAL.S16 Q10, D7, D7 + VMLAL.S16 Q10, D8, D8 + VMLAL.S16 Q10, D9, D9 + VMLAL.S16 Q10, D10, D10 + VMLAL.S16 Q10, D11, D11 + VMLAL.S16 Q10, D12, D12 + VMLAL.S16 Q10, D13, D13 + VMLAL.S16 Q10, D14, D14 + VMLAL.S16 Q10, D15, D15 + + VQADD.S32 D20, D20, D21 + VMOV.S32 r9, D20[0] + VMOV.S32 r10, D20[1] + QADD r6, r9, r10 + QADD r6, r6, r6 + QADD r9, r6, r7 @L_tmp = (L_tmp << 1) + 1; + CLZ r7, r9 + SUB r6, r7, #1 @exp = norm_l(L_tmp) + RSB r7, r6, #32 @exp = 32 - exp + MOV r6, r7, ASR #1 + RSB r7, r6, #0 @scale = -(exp >> 1) + + @loop for every possible period + @for(t = t_min@ t <= t_max@ t++) + @r7 --- scale r4 --- t_min r8 --- excf[] + +LOOPFOR: + ADD r14, r13, #20 @copy of excf[] + MOV r12, r1 @copy of xn[] + MOV r8, #0x8000 + + VLD1.S16 {Q0, Q1}, [r14]! @ load 16 excf[] + VLD1.S16 {Q2, Q3}, [r14]! @ load 16 excf[] + VLD1.S16 {Q4, Q5}, [r12]! @ load 16 x[] + VLD1.S16 {Q6, Q7}, [r12]! @ load 16 x[] + VMULL.S16 Q10, D0, D0 @L_tmp1 += excf[] * excf[] + VMULL.S16 Q11, D0, D8 @L_tmp += x[] * excf[] + VMLAL.S16 Q10, D1, D1 + VMLAL.S16 Q11, D1, D9 + VMLAL.S16 Q10, D2, D2 + VMLAL.S16 Q11, D2, D10 + VMLAL.S16 Q10, D3, D3 + VMLAL.S16 Q11, D3, D11 + VMLAL.S16 Q10, D4, D4 + VMLAL.S16 Q11, D4, D12 + VMLAL.S16 Q10, D5, D5 + VMLAL.S16 Q11, D5, D13 + VMLAL.S16 Q10, D6, D6 + VMLAL.S16 Q11, D6, D14 + VMLAL.S16 Q10, D7, D7 + VMLAL.S16 Q11, D7, D15 + + VLD1.S16 {Q0, Q1}, [r14]! @ load 16 excf[] + VLD1.S16 {Q2, Q3}, [r14]! @ load 16 excf[] + VLD1.S16 {Q4, Q5}, [r12]! @ load 16 x[] + VLD1.S16 {Q6, Q7}, [r12]! @ load 16 x[] + VMLAL.S16 Q10, D0, D0 + VMLAL.S16 Q11, D0, D8 + VMLAL.S16 Q10, D1, D1 + VMLAL.S16 Q11, D1, D9 + VMLAL.S16 Q10, D2, D2 + VMLAL.S16 Q11, D2, D10 + VMLAL.S16 Q10, D3, D3 + VMLAL.S16 Q11, D3, D11 + VMLAL.S16 Q10, D4, D4 + VMLAL.S16 Q11, D4, D12 + VMLAL.S16 Q10, D5, D5 + VMLAL.S16 Q11, D5, D13 + VMLAL.S16 Q10, D6, D6 + VMLAL.S16 Q11, D6, D14 + VMLAL.S16 Q10, D7, D7 + VMLAL.S16 Q11, D7, D15 + + VQADD.S32 D20, D20, D21 + VQADD.S32 D22, D22, D23 + + VPADD.S32 D20, D20, D20 @D20[0] --- L_tmp1 << 1 + VPADD.S32 D22, D22, D22 @D22[0] --- L_tmp << 1 + + VMOV.S32 r6, D20[0] + VMOV.S32 r5, D22[0] + + @r5 --- L_tmp, r6 --- L_tmp1 + MOV r10, #1 + ADD r5, r10, r5, LSL #1 @L_tmp = (L_tmp << 1) + 1 + ADD r6, r10, r6, LSL #1 @L_tmp1 = (L_tmp1 << 1) + 1 + + CLZ r10, r5 + CMP r5, #0 + RSBLT r11, r5, #0 + CLZLT r10, r11 + SUB r10, r10, #1 @exp = norm_l(L_tmp) + + MOV r5, r5, LSL r10 @L_tmp = (L_tmp << exp) + RSB r10, r10, #30 @exp_corr = 30 - exp + MOV r11, r5, ASR #16 @corr = extract_h(L_tmp) + + CLZ r5, r6 + SUB r5, r5, #1 + MOV r6, r6, LSL r5 @L_tmp = (L_tmp1 << exp) + RSB r5, r5, #30 @exp_norm = 30 - exp + + @r10 --- exp_corr, r11 --- corr + @r6 --- L_tmp, r5 --- exp_norm + + @Isqrt_n(&L_tmp, &exp_norm) + + MOV r14, r0 + MOV r12, r1 + + STMFD sp!, {r0 - r4, r7 - r12, r14} + ADD r1, sp, #4 + ADD r0, sp, #0 + STR r6, [sp] + STRH r5, [sp, #4] + BL Isqrt_n + LDR r6, [sp] + LDRSH r5, [sp, #4] + LDMFD sp!, {r0 - r4, r7 - r12, r14} + MOV r0, r14 + MOV r1, r12 + + + MOV r6, r6, ASR #16 @norm = extract_h(L_tmp) + MUL r12, r6, r11 + ADD r12, r12, r12 @L_tmp = vo_L_mult(corr, norm) + + ADD r6, r10, r5 + ADD r6, r6, r7 @exp_corr + exp_norm + scale + + CMP r6, #0 + RSBLT r6, r6, #0 + MOVLT r12, r12, ASR r6 + MOVGT r12, r12, LSL r6 @L_tmp = L_shl(L_tmp, exp_corr + exp_norm + scale) + + ADD r12, r12, r8 + MOV r12, r12, ASR #16 @vo_round(L_tmp) + + LDR r5, [r13, #CORR_NORM] @ get corr_norm address + LDR r6, [r13, #T_MAX] @ get t_max + ADD r10, r5, r4, LSL #1 @ get corr_norm[t] address + STRH r12, [r10] @ corr_norm[t] = vo_round(L_tmp) + + CMP r4, r6 + BEQ Norm_corr_asm_end + + ADD r4, r4, #1 @ t_min ++ + RSB r5, r4, #0 @ k + + MOV r6, #63 @ i = 63 + MOV r8, r0 @ exc[] + MOV r9, r2 @ h[] + ADD r10, r13, #20 @ excf[] + + ADD r8, r8, r5, LSL #1 @ exc[k] address + ADD r9, r9, r6, LSL #1 @ h[i] address + ADD r10, r10, r6, LSL #1 @ excf[i] address + LDRSH r11, [r8] @ tmp = exc[k] + +LOOPK: + LDRSH r8, [r9], #-2 @ load h[i] + LDRSH r12, [r10, #-2] @ load excf[i - 1] + MUL r14, r11, r8 + MOV r8, r14, ASR #15 + ADD r14, r8, r12 + STRH r14, [r10], #-2 + SUBS r6, r6, #1 + BGT LOOPK + + LDRSH r8, [r9] @ load h[0] + MUL r14, r11, r8 + LDR r6, [r13, #T_MAX] @ get t_max + MOV r8, r14, ASR #15 + STRH r8, [r10] + + CMP r4, r6 + BLE LOOPFOR + +Norm_corr_asm_end: + + ADD r13, r13, #voSTACK + LDMFD r13!, {r4 - r12, r15} + + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s new file mode 100644 index 0000000000000000000000000000000000000000..cb1764f6e74b44367ce8f973fd1f01c5d23f1da6 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s @@ -0,0 +1,133 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@**********************************************************************/ +@void Syn_filt_32( +@ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */ +@ Word16 m, /* (i) : order of LP filter */ +@ Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */ +@ Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */ +@ Word16 sig_hi[], /* (o) /16 : synthesis high */ +@ Word16 sig_lo[], /* (o) /16 : synthesis low */ +@ Word16 lg /* (i) : size of filtering */ +@) +@*********************************************************************** +@ a[] --- r0 +@ m --- r1 +@ exc[] --- r2 +@ Qnew --- r3 +@ sig_hi[] --- r4 +@ sig_lo[] --- r5 +@ lg --- r6 + + .section .text + .global Syn_filt_32_asm + +Syn_filt_32_asm: + + STMFD r13!, {r4 - r12, r14} + LDR r4, [r13, #40] @ get sig_hi[] address + LDR r5, [r13, #44] @ get sig_lo[] address + + LDRSH r6, [r0], #2 @ load Aq[0] + ADD r7, r3, #4 @ 4 + Q_new + MOV r3, r6, ASR r7 @ a0 = Aq[0] >> (4 + Q_new) + + SUB r10, r4, #32 @ sig_hi[-16] address + SUB r11, r5, #32 @ sig_lo[-16] address + + VLD1.S16 {D0, D1, D2, D3}, [r0]! @a[1] ~ a[16] + + MOV r8, #0 @ i = 0 + + VLD1.S16 {D4, D5, D6, D7}, [r10]! @ sig_hi[-16] ~ sig_hi[-1] + VREV64.16 D0, D0 + VREV64.16 D1, D1 + VLD1.S16 {D8, D9, D10, D11}, [r11]! @ sig_lo[-16] ~ sig_lo[-1] + VREV64.16 D2, D2 + VREV64.16 D3, D3 + VDUP.S32 Q15, r8 + +SYN_LOOP: + + LDRSH r6, [r2], #2 @exc[i] + @L_tmp = L_msu(L_tmp, sig_lo[i - j], a[j])@ + VMULL.S16 Q10, D8, D3 + VEXT.8 D8, D8, D9, #2 + VMLAL.S16 Q10, D9, D2 + VMLAL.S16 Q10, D10, D1 + VMLAL.S16 Q10, D11, D0 + + VEXT.8 D9, D9, D10, #2 + VEXT.8 D10, D10, D11, #2 + + VPADD.S32 D28, D20, D21 + MUL r12, r6, r3 @exc[i] * a0 + VPADD.S32 D29, D28, D28 + VDUP.S32 Q10, D29[0] @result1 + + VMULL.S16 Q11, D4, D3 + VMLAL.S16 Q11, D5, D2 + VSUB.S32 Q10, Q15, Q10 + @L_tmp = L_msu(L_tmp, sig_hi[i - j], a[j])@ + + VMLAL.S16 Q11, D6, D1 + VEXT.8 D4, D4, D5, #2 + VMLAL.S16 Q11, D7, D0 + + + VEXT.8 D5, D5, D6, #2 + VEXT.8 D6, D6, D7, #2 + + VPADD.S32 D28, D22, D23 + VPADD.S32 D29, D28, D28 + MOV r14, r12, LSL #1 @exc[i] * a0 << 1 + VDUP.S32 Q11, D29[0] @result2 + + + + VSHR.S32 Q10, Q10, #11 @result1 >>= 11 + VSHL.S32 Q11, Q11, #1 @result2 <<= 1 + VDUP.S32 Q12, r14 + VADD.S32 Q12, Q12, Q10 @L_tmp = L_tmp - (result1 >>= 11) - (result2 <<= 1) + VSUB.S32 Q12, Q12, Q11 + + VSHL.S32 Q12, Q12, #3 @L_tmp <<= 3 + + + VSHRN.S32 D20, Q12, #16 @sig_hi[i] = L_tmp >> 16@ + VMOV.S16 r10, D20[0] + VSHR.S32 Q12, Q12, #4 @L_tmp >>= 4 + VEXT.8 D7, D7, D20, #2 + STRH r10, [r4], #2 @store sig_hi[i] + VMOV.S32 r11, D24[0] @r11 --- L_tmp >>= 4 + ADD r8, r8, #1 + SUB r12, r11, r10, LSL #12 + @MOV r11, r12, ASR #16 @sig_lo[i] + VDUP.S16 D21, r12 + VEXT.8 D11, D11, D21, #2 + STRH r12, [r5], #2 @stroe sig_lo[i] + + CMP r8, #64 + BLT SYN_LOOP + +Syn_filt_32_end: + + LDMFD r13!, {r4 - r12, r15} + @ENDFUNC + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s new file mode 100644 index 0000000000000000000000000000000000000000..189e33bb194b3c865b50b4db5c36a04520479695 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s @@ -0,0 +1,178 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@*void Convolve ( +@* Word16 x[], /* (i) : input vector */ +@* Word16 h[], /* (i) : impulse response */ +@* Word16 y[], /* (o) : output vector */ +@* Word16 L /* (i) : vector size */ +@*) +@ +@ r0 --- x[] +@ r1 --- h[] +@ r2 --- y[] +@ r3 --- L + + .section .text + .global Convolve_asm + +Convolve_asm: + + STMFD r13!, {r4 - r12, r14} + MOV r3, #0 + MOV r11, #0x8000 + +LOOP: + @MOV r8, #0 @ s = 0 + ADD r4, r1, r3, LSL #1 @ tmpH address + ADD r5, r3, #1 @ i = n + 1 + MOV r6, r0 + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4] @ *tmpH-- + SUB r5, r5, #1 + VMOV.S32 Q10, #0 + MUL r8, r9, r10 + +LOOP1: + CMP r5, #0 + BLE L1 + SUB r4, r4, #8 + MOV r9, r4 + VLD1.S16 D0, [r6]! + VLD1.S16 D1, [r9]! + VREV64.16 D1, D1 + SUBS r5, r5, #4 + VMLAL.S16 Q10, D0, D1 + B LOOP1 +L1: + VADD.S32 D20, D20, D21 + VPADD.S32 D20, D20, D20 + VMOV.S32 r5, D20[0] + ADD r5, r5, r8 + ADD r5, r11, r5, LSL #1 + MOV r5, r5, LSR #16 @extract_h(s) + ADD r3, r3, #1 + STRH r5, [r2], #2 @y[n] + + + @MOV r8, #0 + ADD r4, r1, r3, LSL #1 @tmpH address + ADD r5, r3, #1 + MOV r6, r0 + LDRSH r9, [r6], #2 @ *tmpX++ + LDRSH r10, [r4], #-2 + LDRSH r12, [r6], #2 + LDRSH r14, [r4] + + MUL r8, r9, r10 + SUB r5, r5, #2 + MLA r8, r12, r14, r8 + + VMOV.S32 Q10, #0 +LOOP2: + CMP r5, #0 + BLE L2 + SUB r4, r4, #8 + MOV r9, r4 + VLD1.S16 D0, [r6]! + VLD1.S16 D1, [r9]! + SUBS r5, r5, #4 + VREV64.16 D1, D1 + VMLAL.S16 Q10, D0, D1 + B LOOP2 +L2: + VADD.S32 D20, D20, D21 + VPADD.S32 D20, D20, D20 + VMOV.S32 r5, D20[0] + ADD r8, r8, r5 + ADD r8, r11, r8, LSL #1 + MOV r8, r8, LSR #16 @extract_h(s) + ADD r3, r3, #1 + STRH r8, [r2], #2 @y[n] + + + @MOV r8, #0 + ADD r4, r1, r3, LSL #1 + ADD r5, r3, #1 + MOV r6, r0 + LDRSH r9, [r6], #2 + LDRSH r10, [r4], #-2 + LDRSH r12, [r6], #2 + LDRSH r14, [r4], #-2 + MUL r8, r9, r10 + LDRSH r9, [r6], #2 + LDRSH r10, [r4] + MLA r8, r12, r14, r8 + SUB r5, r5, #3 + MLA r8, r9, r10, r8 + + VMOV.S32 Q10, #0 +LOOP3: + CMP r5, #0 + BLE L3 + SUB r4, r4, #8 + MOV r9, r4 + VLD1.S16 D0, [r6]! + VLD1.S16 D1, [r9]! + VREV64.16 D1, D1 + SUBS r5, r5, #4 + VMLAL.S16 Q10, D0, D1 + B LOOP3 + +L3: + VADD.S32 D20, D20, D21 + VPADD.S32 D20, D20, D20 + VMOV.S32 r5, D20[0] + ADD r8, r8, r5 + ADD r8, r11, r8, LSL #1 + MOV r8, r8, LSR #16 @extract_h(s) + ADD r3, r3, #1 + STRH r8, [r2], #2 @y[n] + + ADD r5, r3, #1 @ i = n + 1 + ADD r4, r1, r5, LSL #1 @ tmpH address + MOV r6, r0 + VMOV.S32 Q10, #0 +LOOP4: + CMP r5, #0 + BLE L4 + SUB r4, r4, #8 + MOV r9, r4 + VLD1.S16 D0, [r6]! + VLD1.S16 D1, [r9]! + VREV64.16 D1, D1 + SUBS r5, r5, #4 + VMLAL.S16 Q10, D0, D1 + B LOOP4 +L4: + VADD.S32 D20, D20, D21 + VPADD.S32 D20, D20, D20 + VMOV.S32 r5, D20[0] + ADD r5, r11, r5, LSL #1 + MOV r5, r5, LSR #16 @extract_h(s) + ADD r3, r3, #1 + STRH r5, [r2], #2 @y[n] + + CMP r3, #64 + BLT LOOP + +Convolve_asm_end: + + LDMFD r13!, {r4 - r12, r15} + + @ENDFUNC + .END + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s new file mode 100644 index 0000000000000000000000000000000000000000..2e339dbddacb4587d7add6287fe6217d72d6944c --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s @@ -0,0 +1,151 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@static void cor_h_vec_012( +@ Word16 h[], /* (i) scaled impulse response */ +@ Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */ +@ Word16 track, /* (i) track to use */ +@ Word16 sign[], /* (i) sign vector */ +@ Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */ +@ Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */ +@ Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */ +@) +@r0 ---- h[] +@r1 ---- vec[] +@r2 ---- track +@r3 ---- sign[] +@r4 ---- rrixix[][NB_POS] +@r5 ---- cor_1[] +@r6 ---- cor_2[] + + .section .text + .global cor_h_vec_012_asm + +cor_h_vec_012_asm: + + STMFD r13!, {r4 - r12, r14} + LDR r4, [r13, #40] @load rrixix[][NB_POS] + ADD r7, r4, r2, LSL #5 @r7 --- p0 = rrixix[track] + MOV r4, #0 @i=0 + + @r0 --- h[], r1 --- vec[], r2 --- pos + @r3 --- sign[], r4 --- i, r7 --- p0 + +LOOPi: + MOV r5, #0 @L_sum1 = 0 + MOV r6, #0 @L_sum2 = 0 + ADD r9, r1, r2, LSL #1 @p2 = &vec[pos] + MOV r10, r0 @p1 = h + RSB r11, r2, #62 @j=62-pos + +LOOPj1: + LDRSH r12, [r10], #2 + LDRSH r8, [r9], #2 + LDRSH r14, [r9] + SUBS r11, r11, #1 + MLA r5, r12, r8, r5 + MLA r6, r12, r14, r6 + BGE LOOPj1 + + LDRSH r12, [r10], #2 @*p1++ + MOV r6, r6, LSL #2 @L_sum2 = (L_sum2 << 2) + MLA r5, r12, r14, r5 + MOV r14, #0x8000 + MOV r5, r5, LSL #2 @L_sum1 = (L_sum1 << 2) + ADD r10, r6, r14 + ADD r9, r5, r14 + MOV r5, r9, ASR #16 + MOV r6, r10, ASR #16 + ADD r9, r3, r2, LSL #1 @address of sign[pos] + ADD r8, r7, #32 + LDRSH r10, [r9], #2 @sign[pos] + LDRSH r11, [r9] @sign[pos + 1] + MUL r12, r5, r10 + MUL r14, r6, r11 + MOV r5, r12, ASR #15 + MOV r6, r14, ASR #15 + LDR r9, [r13, #44] + LDR r12, [r13, #48] + LDRSH r10, [r7], #2 @*p0++ + LDRSH r11, [r8] @*p3++ + ADD r9, r9, r4, LSL #1 + ADD r12, r12, r4, LSL #1 + ADD r5, r5, r10 + ADD r6, r6, r11 + STRH r5, [r9] + STRH r6, [r12] + + ADD r2, r2, #4 + + MOV r5, #0 @L_sum1 = 0 + MOV r6, #0 @L_sum2 = 0 + ADD r9, r1, r2, LSL #1 @p2 = &vec[pos] + MOV r10, r0 @p1 = h + RSB r11, r2, #62 @j=62-pos + ADD r4, r4, #1 @i++ + +LOOPj2: + LDRSH r12, [r10], #2 + LDRSH r8, [r9], #2 + LDRSH r14, [r9] + SUBS r11, r11, #1 + MLA r5, r12, r8, r5 + MLA r6, r12, r14, r6 + BGE LOOPj2 + + LDRSH r12, [r10], #2 @*p1++ + MOV r6, r6, LSL #2 @L_sum2 = (L_sum2 << 2) + MLA r5, r12, r14, r5 + MOV r14, #0x8000 + MOV r5, r5, LSL #2 @L_sum1 = (L_sum1 << 2) + ADD r10, r6, r14 + ADD r9, r5, r14 + + MOV r5, r9, ASR #16 + MOV r6, r10, ASR #16 + ADD r9, r3, r2, LSL #1 @address of sign[pos] + ADD r8, r7, #32 + LDRSH r10, [r9], #2 @sign[pos] + LDRSH r11, [r9] @sign[pos + 1] + MUL r12, r5, r10 + MUL r14, r6, r11 + MOV r5, r12, ASR #15 + MOV r6, r14, ASR #15 + LDR r9, [r13, #44] + LDR r12, [r13, #48] + LDRSH r10, [r7], #2 @*p0++ + LDRSH r11, [r8] @*p3++ + ADD r9, r9, r4, LSL #1 + ADD r12, r12, r4, LSL #1 + ADD r5, r5, r10 + ADD r6, r6, r11 + STRH r5, [r9] + STRH r6, [r12] + ADD r4, r4, #1 @i+1 + ADD r2, r2, #4 @pos += STEP + CMP r4, #16 + + BLT LOOPi + +the_end: + LDMFD r13!, {r4 - r12, r15} + + .END + + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s new file mode 100644 index 0000000000000000000000000000000000000000..3b8853f04fd56abdc73c9dc6a4b53ba4e4c1b043 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s @@ -0,0 +1,100 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@void Pred_lt4( +@ Word16 exc[], /* in/out: excitation buffer */ +@ Word16 T0, /* input : integer pitch lag */ +@ Word16 frac, /* input : fraction of lag */ +@ Word16 L_subfr /* input : subframe size */ +@) +@*********************************************************************** +@ r0 --- exc[] +@ r1 --- T0 +@ r2 --- frac +@ r3 --- L_subfr + + .section .text + .global pred_lt4_asm + .extern inter4_2 + +pred_lt4_asm: + + STMFD r13!, {r4 - r12, r14} + SUB r4, r0, r1, LSL #1 @ x = exc - T0 + RSB r2, r2, #0 @ frac = - frac + SUB r4, r4, #30 @ x -= L_INTERPOL2 - 1 + CMP r2, #0 + ADDLT r2, r2, #4 @ frac += UP_SAMP + SUBLT r4, r4, #2 @ x-- + + LDR r11, Lable1 + RSB r2, r2, #3 @ k = UP_SAMP - 1 - frac + MOV r8, #0 @ j = 0 + ADD r11, r11, r2, LSL #6 @ get inter4_2[k][] + + VLD1.S16 {Q0, Q1}, [r11]! + VLD1.S16 {Q2, Q3}, [r11]! + + MOV r6, #0x8000 + + VLD1.S16 {Q4, Q5}, [r4]! @load 16 x[] + VLD1.S16 {Q6, Q7}, [r4]! @load 16 x[] + +LOOP: + VQDMULL.S16 Q15, D8, D0 + VQDMLAL.S16 Q15, D9, D1 + VQDMLAL.S16 Q15, D10, D2 + VQDMLAL.S16 Q15, D11, D3 + + VQDMLAL.S16 Q15, D12, D4 + VQDMLAL.S16 Q15, D13, D5 + VQDMLAL.S16 Q15, D14, D6 + VQDMLAL.S16 Q15, D15, D7 + + LDRSH r12, [r4], #2 + + VEXT.S16 D8, D8, D9, #1 + VEXT.S16 D9, D9, D10, #1 + VEXT.S16 D10, D10, D11, #1 + VEXT.S16 D11, D11, D12, #1 + VDUP.S16 D24, r12 + VEXT.S16 D12, D12, D13, #1 + VEXT.S16 D13, D13, D14, #1 + + VQADD.S32 D30, D30, D31 + MOV r11, #0x8000 + VPADD.S32 D30, D30, D30 + ADD r8, r8, #1 + VMOV.S32 r12, D30[0] + VEXT.S16 D14, D14, D15, #1 + + QADD r1, r12, r12 @ L_sum = (L_sum << 2) + VEXT.S16 D15, D15, D24, #1 + QADD r5, r1, r6 + MOV r1, r5, ASR #16 + CMP r8, r3 + STRH r1, [r0], #2 @ exc[j] = (L_sum + 0x8000) >> 16 + BLT LOOP + +pred_lt4_end: + + LDMFD r13!, {r4 - r12, r15} + +Lable1: + .word inter4_2 + @ENDFUNC + .END + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s new file mode 100644 index 0000000000000000000000000000000000000000..b9e6b23c6a59e9cc4dfd16090d53cbe3ff8efb59 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s @@ -0,0 +1,127 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@void Residu ( +@ Word16 a[], /* (i) : prediction coefficients */ +@ Word16 x[], /* (i) : speech signal */ +@ Word16 y[], /* (o) : residual signal */ +@ Word16 lg /* (i) : size of filtering */ +@) +@a[] RN r0 +@x[] RN r1 +@y[] RN r2 +@lg RN r3 + + .section .text + .global Residu_opt + +Residu_opt: + + STMFD r13!, {r4 - r12, r14} + SUB r7, r3, #4 @i = lg - 4 + + VLD1.S16 {D0, D1, D2, D3}, [r0]! @get all a[] + VLD1.S16 {D4}, [r0]! + VMOV.S32 Q8, #0x8000 + +LOOP1: + ADD r9, r1, r7, LSL #1 @copy the address + ADD r10, r2, r7, LSL #1 + MOV r8, r9 + VLD1.S16 D5, [r8]! @get x[i], x[i+1], x[i+2], x[i+3] + VQDMULL.S16 Q10, D5, D0[0] @finish the first L_mult + + SUB r8, r9, #2 @get the x[i-1] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D0[1] + + SUB r8, r9, #4 @load the x[i-2] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D0[2] + + SUB r8, r9, #6 @load the x[i-3] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D0[3] + + SUB r8, r9, #8 @load the x[i-4] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D1[0] + + SUB r8, r9, #10 @load the x[i-5] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D1[1] + + SUB r8, r9, #12 @load the x[i-6] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D1[2] + + SUB r8, r9, #14 @load the x[i-7] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D1[3] + + SUB r8, r9, #16 @load the x[i-8] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D2[0] + + SUB r8, r9, #18 @load the x[i-9] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D2[1] + + SUB r8, r9, #20 @load the x[i-10] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D2[2] + + SUB r8, r9, #22 @load the x[i-11] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D2[3] + + SUB r8, r9, #24 @load the x[i-12] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D3[0] + + SUB r8, r9, #26 @load the x[i-13] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D3[1] + + SUB r8, r9, #28 @load the x[i-14] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D3[2] + + SUB r8, r9, #30 @load the x[i-15] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D3[3] + + SUB r8, r9, #32 @load the x[i-16] address + VLD1.S16 D5, [r8]! + VQDMLAL.S16 Q10, D5, D4[0] + + SUB r7, r7, #4 @i-=4 + VQSHL.S32 Q10, Q10, #4 + VQADD.S32 Q10, Q10, Q8 + VSHRN.S32 D5, Q10, #16 + VST1.S16 D5, [r10]! + CMP r7, #0 + + BGE LOOP1 + +Residu_asm_end: + + LDMFD r13!, {r4 - r12, r15} + + @ENDFUNC + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s new file mode 100644 index 0000000000000000000000000000000000000000..14957d81b165d8d76a72ceab9fdaa1cc6e893ad7 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s @@ -0,0 +1,138 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@**********************************************************************/ +@void Scale_sig( +@ Word16 x[], /* (i/o) : signal to scale */ +@ Word16 lg, /* (i) : size of x[] */ +@ Word16 exp /* (i) : exponent: x = round(x << exp) */ +@) +@*********************************************************************** +@ x[] --- r0 +@ lg --- r1 +@ exp --- r2 + + .section .text + .global Scale_sig_opt + +Scale_sig_opt: + + STMFD r13!, {r4 - r12, r14} + MOV r4, #4 + VMOV.S32 Q15, #0x8000 + VDUP.S32 Q14, r2 + MOV r5, r0 @ copy x[] address + CMP r1, #64 + MOVEQ r4, #1 + BEQ LOOP + CMP r1, #128 + MOVEQ r4, #2 + BEQ LOOP + CMP r1, #256 + BEQ LOOP + CMP r1, #80 + MOVEQ r4, #1 + BEQ LOOP1 + +LOOP1: + VLD1.S16 {Q0, Q1}, [r5]! @load 16 Word16 x[] + VSHLL.S16 Q10, D0, #16 + VSHLL.S16 Q11, D1, #16 + VSHLL.S16 Q12, D2, #16 + VSHLL.S16 Q13, D3, #16 + VSHL.S32 Q10, Q10, Q14 + VSHL.S32 Q11, Q11, Q14 + VSHL.S32 Q12, Q12, Q14 + VSHL.S32 Q13, Q13, Q14 + VADDHN.S32 D16, Q10, Q15 + VADDHN.S32 D17, Q11, Q15 + VADDHN.S32 D18, Q12, Q15 + VADDHN.S32 D19, Q13, Q15 + VST1.S16 {Q8, Q9}, [r0]! @store 16 Word16 x[] + +LOOP: + VLD1.S16 {Q0, Q1}, [r5]! @load 16 Word16 x[] + VLD1.S16 {Q2, Q3}, [r5]! @load 16 Word16 x[] + VLD1.S16 {Q4, Q5}, [r5]! @load 16 Word16 x[] + VLD1.S16 {Q6, Q7}, [r5]! @load 16 Word16 x[] + + VSHLL.S16 Q8, D0, #16 + VSHLL.S16 Q9, D1, #16 + VSHLL.S16 Q10, D2, #16 + VSHLL.S16 Q11, D3, #16 + VSHL.S32 Q8, Q8, Q14 + VSHL.S32 Q9, Q9, Q14 + VSHL.S32 Q10, Q10, Q14 + VSHL.S32 Q11, Q11, Q14 + VADDHN.S32 D16, Q8, Q15 + VADDHN.S32 D17, Q9, Q15 + VADDHN.S32 D18, Q10, Q15 + VADDHN.S32 D19, Q11, Q15 + VST1.S16 {Q8, Q9}, [r0]! @store 16 Word16 x[] + + + VSHLL.S16 Q12, D4, #16 + VSHLL.S16 Q13, D5, #16 + VSHLL.S16 Q10, D6, #16 + VSHLL.S16 Q11, D7, #16 + VSHL.S32 Q12, Q12, Q14 + VSHL.S32 Q13, Q13, Q14 + VSHL.S32 Q10, Q10, Q14 + VSHL.S32 Q11, Q11, Q14 + VADDHN.S32 D16, Q12, Q15 + VADDHN.S32 D17, Q13, Q15 + VADDHN.S32 D18, Q10, Q15 + VADDHN.S32 D19, Q11, Q15 + VST1.S16 {Q8, Q9}, [r0]! @store 16 Word16 x[] + + VSHLL.S16 Q10, D8, #16 + VSHLL.S16 Q11, D9, #16 + VSHLL.S16 Q12, D10, #16 + VSHLL.S16 Q13, D11, #16 + VSHL.S32 Q10, Q10, Q14 + VSHL.S32 Q11, Q11, Q14 + VSHL.S32 Q12, Q12, Q14 + VSHL.S32 Q13, Q13, Q14 + VADDHN.S32 D16, Q10, Q15 + VADDHN.S32 D17, Q11, Q15 + VADDHN.S32 D18, Q12, Q15 + VADDHN.S32 D19, Q13, Q15 + VST1.S16 {Q8, Q9}, [r0]! @store 16 Word16 x[] + + VSHLL.S16 Q10, D12, #16 + VSHLL.S16 Q11, D13, #16 + VSHLL.S16 Q12, D14, #16 + VSHLL.S16 Q13, D15, #16 + VSHL.S32 Q10, Q10, Q14 + VSHL.S32 Q11, Q11, Q14 + VSHL.S32 Q12, Q12, Q14 + VSHL.S32 Q13, Q13, Q14 + VADDHN.S32 D16, Q10, Q15 + VADDHN.S32 D17, Q11, Q15 + VADDHN.S32 D18, Q12, Q15 + VADDHN.S32 D19, Q13, Q15 + VST1.S16 {Q8, Q9}, [r0]! @store 16 Word16 x[] + SUBS r4, r4, #1 + BGT LOOP + + +Scale_sig_asm_end: + + LDMFD r13!, {r4 - r12, r15} + @ENDFUNC + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s new file mode 100644 index 0000000000000000000000000000000000000000..dc3d4a8de605a6b76130b6f36a2304c365702d0e --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s @@ -0,0 +1,106 @@ +@/* +@ ** Copyright 2003-2010, VisualOn, Inc. +@ ** +@ ** 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. +@ */ +@ +@void Syn_filt( +@ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */ +@ Word16 x[], /* (i) : input signal */ +@ Word16 y[], /* (o) : output signal */ +@ Word16 mem[], /* (i/o) : memory associated with this filtering. */ +@) +@*********************************************************************** +@ a[] --- r0 +@ x[] --- r1 +@ y[] --- r2 +@ mem[] --- r3 +@ m --- 16 lg --- 80 update --- 1 + + .section .text + .global Syn_filt_asm + +Syn_filt_asm: + + STMFD r13!, {r4 - r12, r14} + SUB r13, r13, #700 @ y_buf[L_FRAME16k + M16k] + + MOV r4, r3 @ copy mem[] address + MOV r5, r13 @ copy yy = y_buf address + + @ for(i = 0@ i < m@ i++) + @{ + @ *yy++ = mem[i]@ + @} + VLD1.S16 {D0, D1, D2, D3}, [r4]! @load 16 mems + VST1.S16 {D0, D1, D2, D3}, [r5]! @store 16 mem[] to *yy + + LDRSH r5, [r0], #2 @ load a[0] + MOV r8, #0 @ i = 0 + MOV r5, r5, ASR #1 @ a0 = a[0] >> 1 + VMOV.S16 D8[0], r5 + @ load all a[] + VLD1.S16 {D0, D1, D2, D3}, [r0]! @ load a[1] ~ a[16] + VREV64.16 D0, D0 + VREV64.16 D1, D1 + VREV64.16 D2, D2 + VREV64.16 D3, D3 + MOV r8, #0 @ loop times + MOV r10, r13 @ temp = y_buf + ADD r4, r13, #32 @ yy[i] address + + VLD1.S16 {D4, D5, D6, D7}, [r10]! @ first 16 temp_p + +SYN_LOOP: + + LDRSH r6, [r1], #2 @ load x[i] + MUL r12, r6, r5 @ L_tmp = x[i] * a0 + ADD r10, r4, r8, LSL #1 @ y[i], yy[i] address + + VDUP.S32 Q10, r12 + VMULL.S16 Q5, D3, D4 + VMLAL.S16 Q5, D2, D5 + VMLAL.S16 Q5, D1, D6 + VMLAL.S16 Q5, D0, D7 + VEXT.8 D4, D4, D5, #2 + VEXT.8 D5, D5, D6, #2 + VEXT.8 D6, D6, D7, #2 + VPADD.S32 D12, D10, D11 + ADD r8, r8, #1 + VPADD.S32 D10, D12, D12 + + VDUP.S32 Q7, D10[0] + + VSUB.S32 Q9, Q10, Q7 + VQRSHRN.S32 D20, Q9, #12 + VMOV.S16 r9, D20[0] + VEXT.8 D7, D7, D20, #2 + CMP r8, #80 + STRH r9, [r10] @ yy[i] + STRH r9, [r2], #2 @ y[i] + + BLT SYN_LOOP + + @ update mem[] + ADD r5, r13, #160 @ yy[64] address + VLD1.S16 {D0, D1, D2, D3}, [r5]! + VST1.S16 {D0, D1, D2, D3}, [r3]! + +Syn_filt_asm_end: + + ADD r13, r13, #700 + LDMFD r13!, {r4 - r12, r15} + @ENDFUNC + .END + + diff --git a/media/libstagefright/codecs/amrwbenc/src/autocorr.c b/media/libstagefright/codecs/amrwbenc/src/autocorr.c new file mode 100644 index 0000000000000000000000000000000000000000..33ed6706b93e289c687b970000fba682caac69e9 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/autocorr.c @@ -0,0 +1,127 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + + +/*********************************************************************** +* File: autocorr.c * +* * +* Description:Compute autocorrelations of signal with windowing * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "acelp.h" +#include "ham_wind.tab" + +void Autocorr( + Word16 x[], /* (i) : Input signal */ + Word16 m, /* (i) : LPC order */ + Word16 r_h[], /* (o) Q15: Autocorrelations (msb) */ + Word16 r_l[] /* (o) : Autocorrelations (lsb) */ + ) +{ + Word32 i, norm, shift; + Word16 y[L_WINDOW]; + Word32 L_sum, L_sum1, L_tmp, F_LEN; + Word16 *p1,*p2,*p3; + const Word16 *p4; + /* Windowing of signal */ + p1 = x; + p4 = vo_window; + p3 = y; + + for (i = 0; i < L_WINDOW; i+=4) + { + *p3++ = vo_mult_r((*p1++), (*p4++)); + *p3++ = vo_mult_r((*p1++), (*p4++)); + *p3++ = vo_mult_r((*p1++), (*p4++)); + *p3++ = vo_mult_r((*p1++), (*p4++)); + } + + /* calculate energy of signal */ + L_sum = vo_L_deposit_h(16); /* sqrt(256), avoid overflow after rounding */ + for (i = 0; i < L_WINDOW; i++) + { + L_tmp = vo_L_mult(y[i], y[i]); + L_tmp = (L_tmp >> 8); + L_sum += L_tmp; + } + + /* scale signal to avoid overflow in autocorrelation */ + norm = norm_l(L_sum); + shift = 4 - (norm >> 1); + if(shift > 0) + { + p1 = y; + for (i = 0; i < L_WINDOW; i+=4) + { + *p1 = vo_shr_r(*p1, shift); + p1++; + *p1 = vo_shr_r(*p1, shift); + p1++; + *p1 = vo_shr_r(*p1, shift); + p1++; + *p1 = vo_shr_r(*p1, shift); + p1++; + } + } + + /* Compute and normalize r[0] */ + L_sum = 1; + for (i = 0; i < L_WINDOW; i+=4) + { + L_sum += vo_L_mult(y[i], y[i]); + L_sum += vo_L_mult(y[i+1], y[i+1]); + L_sum += vo_L_mult(y[i+2], y[i+2]); + L_sum += vo_L_mult(y[i+3], y[i+3]); + } + + norm = norm_l(L_sum); + L_sum = (L_sum << norm); + + r_h[0] = L_sum >> 16; + r_l[0] = (L_sum & 0xffff)>>1; + + /* Compute r[1] to r[m] */ + for (i = 1; i <= 8; i++) + { + L_sum1 = 0; + L_sum = 0; + F_LEN = (Word32)(L_WINDOW - 2*i); + p1 = y; + p2 = y + (2*i)-1; + do{ + L_sum1 += *p1 * *p2++; + L_sum += *p1++ * *p2; + }while(--F_LEN!=0); + + L_sum1 += *p1 * *p2++; + + L_sum1 = L_sum1<> 15; + r_l[(2*i)-1] = L_sum1 & 0x00007fff; + r_h[(2*i)] = L_sum >> 15; + r_l[(2*i)] = L_sum & 0x00007fff; + } + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/az_isp.c b/media/libstagefright/codecs/amrwbenc/src/az_isp.c new file mode 100644 index 0000000000000000000000000000000000000000..8259f91ec51e7af85f2e869cf0348112c77559b5 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/az_isp.c @@ -0,0 +1,268 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: az_isp.c +* +* Description: +*-----------------------------------------------------------------------* +* Compute the ISPs from the LPC coefficients (order=M) * +*-----------------------------------------------------------------------* +* * +* The ISPs are the roots of the two polynomials F1(z) and F2(z) * +* defined as * +* F1(z) = A(z) + z^-m A(z^-1) * +* and F2(z) = A(z) - z^-m A(z^-1) * +* * +* For a even order m=2n, F1(z) has M/2 conjugate roots on the unit * +* circle and F2(z) has M/2-1 conjugate roots on the unit circle in * +* addition to two roots at 0 and pi. * +* * +* For a 16th order LP analysis, F1(z) and F2(z) can be written as * +* * +* F1(z) = (1 + a[M]) PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) * +* i=0,2,4,6,8,10,12,14 * +* * +* F2(z) = (1 - a[M]) (1 - z^-2) PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) * +* i=1,3,5,7,9,11,13 * +* * +* The ISPs are the M-1 frequencies w_i, i=0...M-2 plus the last * +* predictor coefficient a[M]. * +*-----------------------------------------------------------------------* + +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "stdio.h" +#include "grid100.tab" + +#define M 16 +#define NC (M/2) + +/* local function */ +static __inline Word16 Chebps2(Word16 x, Word16 f[], Word32 n); + +void Az_isp( + Word16 a[], /* (i) Q12 : predictor coefficients */ + Word16 isp[], /* (o) Q15 : Immittance spectral pairs */ + Word16 old_isp[] /* (i) : old isp[] (in case not found M roots) */ + ) +{ + Word32 i, j, nf, ip, order; + Word16 xlow, ylow, xhigh, yhigh, xmid, ymid, xint; + Word16 x, y, sign, exp; + Word16 *coef; + Word16 f1[NC + 1], f2[NC]; + Word32 t0; + /*-------------------------------------------------------------* + * find the sum and diff polynomials F1(z) and F2(z) * + * F1(z) = [A(z) + z^M A(z^-1)] * + * F2(z) = [A(z) - z^M A(z^-1)]/(1-z^-2) * + * * + * for (i=0; i> 1) + (xhigh >> 1); /* xmid = (xlow + xhigh)/2 */ + ymid = Chebps2(xmid, coef, order); + if ((ylow * ymid) <= (Word32) 0) + { + yhigh = ymid; + xhigh = xmid; + } else + { + ylow = ymid; + xlow = xmid; + } + } + /*-------------------------------------------------------------* + * Linear interpolation * + * xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow); * + *-------------------------------------------------------------*/ + x = xhigh - xlow; + y = yhigh - ylow; + if (y == 0) + { + xint = xlow; + } else + { + sign = y; + y = abs_s(y); + exp = norm_s(y); + y = y << exp; + y = div_s((Word16) 16383, y); + t0 = x * y; + t0 = (t0 >> (19 - exp)); + y = vo_extract_l(t0); /* y= (xhigh-xlow)/(yhigh-ylow) in Q11 */ + if (sign < 0) + y = -y; + t0 = ylow * y; /* result in Q26 */ + t0 = (t0 >> 10); /* result in Q15 */ + xint = vo_sub(xlow, vo_extract_l(t0)); /* xint = xlow - ylow*y */ + } + isp[nf] = xint; + xlow = xint; + nf++; + if (ip == 0) + { + ip = 1; + coef = f2; + order = NC - 1; + } else + { + ip = 0; + coef = f1; + order = NC; + } + ylow = Chebps2(xlow, coef, order); + } + } + /* Check if M-1 roots found */ + if(nf < M - 1) + { + for (i = 0; i < M; i++) + { + isp[i] = old_isp[i]; + } + } else + { + isp[M - 1] = a[M] << 3; /* From Q12 to Q15 with saturation */ + } + return; +} + +/*--------------------------------------------------------------* +* function Chebps2: * +* ~~~~~~~ * +* Evaluates the Chebishev polynomial series * +*--------------------------------------------------------------* +* * +* The polynomial order is * +* n = M/2 (M is the prediction order) * +* The polynomial is given by * +* C(x) = f(0)T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2 * +* Arguments: * +* x: input value of evaluation; x = cos(frequency) in Q15 * +* f[]: coefficients of the pol. in Q11 * +* n: order of the pol. * +* * +* The value of C(x) is returned. (Satured to +-1.99 in Q14) * +* * +*--------------------------------------------------------------*/ + +static __inline Word16 Chebps2(Word16 x, Word16 f[], Word32 n) +{ + Word32 i, cheb; + Word16 b0_h, b0_l, b1_h, b1_l, b2_h, b2_l; + Word32 t0; + + /* Note: All computation are done in Q24. */ + + t0 = f[0] << 13; + b2_h = t0 >> 16; + b2_l = (t0 & 0xffff)>>1; + + t0 = ((b2_h * x)<<1) + (((b2_l * x)>>15)<<1); + t0 <<= 1; + t0 += (f[1] << 13); /* + f[1] in Q24 */ + + b1_h = t0 >> 16; + b1_l = (t0 & 0xffff) >> 1; + + for (i = 2; i < n; i++) + { + t0 = ((b1_h * x)<<1) + (((b1_l * x)>>15)<<1); + + t0 += (b2_h * (-16384))<<1; + t0 += (f[i] << 12); + t0 <<= 1; + t0 -= (b2_l << 1); /* t0 = 2.0*x*b1 - b2 + f[i]; */ + + b0_h = t0 >> 16; + b0_l = (t0 & 0xffff) >> 1; + + b2_l = b1_l; /* b2 = b1; */ + b2_h = b1_h; + b1_l = b0_l; /* b1 = b0; */ + b1_h = b0_h; + } + + t0 = ((b1_h * x)<<1) + (((b1_l * x)>>15)<<1); + t0 += (b2_h * (-32768))<<1; /* t0 = x*b1 - b2 */ + t0 -= (b2_l << 1); + t0 += (f[n] << 12); /* t0 = x*b1 - b2 + f[i]/2 */ + + t0 = L_shl2(t0, 6); /* Q24 to Q30 with saturation */ + + cheb = extract_h(t0); /* Result in Q14 */ + + if (cheb == -32768) + { + cheb = -32767; /* to avoid saturation in Az_isp */ + } + return (cheb); +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/bits.c b/media/libstagefright/codecs/amrwbenc/src/bits.c new file mode 100644 index 0000000000000000000000000000000000000000..90d1a00e41f924b0c55e2449908e216a192a1774 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/bits.c @@ -0,0 +1,210 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** + File: bits.c + + Description: Performs bit stream manipulation + +************************************************************************/ + +#include +#include +#include "typedef.h" +#include "basic_op.h" +#include "cnst.h" +#include "bits.h" +#include "acelp.h" +#include "dtx.h" +#include "mime_io.tab" + + +int PackBits(Word16 prms[], /* i: analysis parameters */ + Word16 coding_mode, /* i: coding bit-stream ratio mode */ + Word16 mode, /* i: coding bit-stream ratio mode*/ + Coder_State *st /*i/o: coder global parameters struct */ + ) +{ + Word16 i, frame_type; + UWord8 temp; + UWord8 *stream_ptr; + Word16 bitstreamformat = st->frameType; + + unsigned short* dataOut = st->outputStream; + + if (coding_mode == MRDTX) + { + st->sid_update_counter--; + + if (st->prev_ft == TX_SPEECH) + { + frame_type = TX_SID_FIRST; + st->sid_update_counter = 3; + } else + { + if ((st->sid_handover_debt > 0) && (st->sid_update_counter > 2)) + { + /* ensure extra updates are properly delayed after a possible SID_FIRST */ + frame_type = TX_SID_UPDATE; + st->sid_handover_debt--; + } else + { + if (st->sid_update_counter == 0) + { + frame_type = TX_SID_UPDATE; + st->sid_update_counter = 8; + } else + { + frame_type = TX_NO_DATA; + } + } + } + } else + { + st->sid_update_counter = 8; + frame_type = TX_SPEECH; + } + st->prev_ft = frame_type; + + if(bitstreamformat == 0) /* default file format */ + { + *(dataOut) = TX_FRAME_TYPE; + *(dataOut + 1) = frame_type; + *(dataOut + 2) = mode; + for (i = 0; i < nb_of_bits[coding_mode]; i++) + { + *(dataOut + 3 + i) = prms[i]; + } + return (3 + nb_of_bits[coding_mode])<<1; + } else + { + if (bitstreamformat == 1) /* ITU file format */ + { + *(dataOut) = 0x6b21; + if(frame_type != TX_NO_DATA && frame_type != TX_SID_FIRST) + { + *(dataOut + 1) = nb_of_bits[coding_mode]; + for (i = 0; i < nb_of_bits[coding_mode]; i++) + { + if(prms[i] == BIT_0){ + *(dataOut + 2 + i) = BIT_0_ITU; + } + else{ + *(dataOut + 2 + i) = BIT_1_ITU; + } + } + return (2 + nb_of_bits[coding_mode])<<1; + } else + { + *(dataOut + 1) = 0; + return 2<<1; + } + } else /* MIME/storage file format */ + { +#define MRSID 9 + /* change mode index in case of SID frame */ + if (coding_mode == MRDTX) + { + coding_mode = MRSID; + if (frame_type == TX_SID_FIRST) + { + for (i = 0; i < NBBITS_SID; i++) prms[i] = BIT_0; + } + } + /* -> force NO_DATA frame */ + if (coding_mode < 0 || coding_mode > 15 || (coding_mode > MRSID && coding_mode < 14)) + { + coding_mode = 15; + } + /* mark empty frames between SID updates as NO_DATA frames */ + if (coding_mode == MRSID && frame_type == TX_NO_DATA) + { + coding_mode = 15; + } + /* set pointer for packed frame, note that we handle data as bytes */ + stream_ptr = (UWord8*)dataOut; + /* insert table of contents (ToC) byte at the beginning of the packet */ + *stream_ptr = toc_byte[coding_mode]; + stream_ptr++; + temp = 0; + /* sort and pack AMR-WB speech or SID bits */ + for (i = 1; i < unpacked_size[coding_mode] + 1; i++) + { + if (prms[sort_ptr[coding_mode][i-1]] == BIT_1) + { + temp++; + } + if (i&0x7) + { + temp <<= 1; + } + else + { + *stream_ptr = temp; + stream_ptr++; + temp = 0; + } + } + /* insert SID type indication and speech mode in case of SID frame */ + if (coding_mode == MRSID) + { + if (frame_type == TX_SID_UPDATE) + { + temp++; + } + temp <<= 4; + temp += mode & 0x000F; + } + /* insert unused bits (zeros) at the tail of the last byte */ + if (unused_size[coding_mode]) + { + temp <<= (unused_size[coding_mode] - 1); + } + *stream_ptr = temp; + /* write packed frame into file (1 byte added to cover ToC entry) */ + return (1 + packed_size[coding_mode]); + } + } +} + +/*-----------------------------------------------------* +* Parm_serial -> convert parameters to serial stream * +*-----------------------------------------------------*/ + +void Parm_serial( + Word16 value, /* input : parameter value */ + Word16 no_of_bits, /* input : number of bits */ + Word16 ** prms + ) +{ + Word16 i, bit; + *prms += no_of_bits; + for (i = 0; i < no_of_bits; i++) + { + bit = (Word16) (value & 0x0001); /* get lsb */ + if (bit == 0) + *--(*prms) = BIT_0; + else + *--(*prms) = BIT_1; + value >>= 1; + } + *prms += no_of_bits; + return; +} + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c new file mode 100644 index 0000000000000000000000000000000000000000..39fc4c578603e7068c21cf3287f05069659719da --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c @@ -0,0 +1,297 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/************************************************************************ +* File: c2t64fx.c * +* * +* Description:Performs algebraic codebook search for 6.60kbits mode* +* * +*************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "math_op.h" +#include "acelp.h" +#include "cnst.h" + +#define NB_TRACK 2 +#define STEP 2 +#define NB_POS 32 +#define MSIZE 1024 + +/************************************************************************* +* Function: ACELP_2t64_fx() * +* * +* 12 bits algebraic codebook. * +* 2 tracks x 32 positions per track = 64 samples. * +* * +* 12 bits --> 2 pulses in a frame of 64 samples. * +* * +* All pulses can have two (2) possible amplitudes: +1 or -1. * +* Each pulse can have 32 possible positions. * +**************************************************************************/ + +void ACELP_2t64_fx( + Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */ + Word16 cn[], /* (i) <12b : residual after long term prediction */ + Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */ + Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */ + Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */ + Word16 * index /* (o) : index (12): 5+1+5+1 = 11 bits. */ + ) +{ + Word32 i, j, k, i0, i1, ix, iy, pos, pos2; + Word16 ps, psk, ps1, ps2, alpk, alp1, alp2, sq; + Word16 alp, val, exp, k_cn, k_dn; + Word16 *p0, *p1, *p2, *psign; + Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf; + + Word16 sign[L_SUBFR], vec[L_SUBFR], dn2[L_SUBFR]; + Word16 h_buf[4 * L_SUBFR] = {0}; + Word16 rrixix[NB_TRACK][NB_POS]; + Word16 rrixiy[MSIZE]; + Word32 s, cor; + + /*----------------------------------------------------------------* + * Find sign for each pulse position. * + *----------------------------------------------------------------*/ + alp = 8192; /* alp = 2.0 (Q12) */ + + /* calculate energy for normalization of cn[] and dn[] */ + /* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */ +#ifdef ASM_OPT /* asm optimization branch */ + s = Dot_product12_asm(cn, cn, L_SUBFR, &exp); +#else + s = Dot_product12(cn, cn, L_SUBFR, &exp); +#endif + + Isqrt_n(&s, &exp); + s = L_shl(s, add1(exp, 5)); + k_cn = vo_round(s); + + /* set k_dn = 32..512 (ener_dn = 2^30..2^22) */ +#ifdef ASM_OPT /* asm optimization branch */ + s = Dot_product12_asm(dn, dn, L_SUBFR, &exp); +#else + s = Dot_product12(dn, dn, L_SUBFR, &exp); +#endif + + Isqrt_n(&s, &exp); + k_dn = vo_round(L_shl(s, (exp + 8))); /* k_dn = 256..4096 */ + k_dn = vo_mult_r(alp, k_dn); /* alp in Q12 */ + + /* mix normalized cn[] and dn[] */ + p0 = cn; + p1 = dn; + p2 = dn2; + + for (i = 0; i < L_SUBFR/4; i++) + { + s = (k_cn* (*p0++))+(k_dn * (*p1++)); + *p2++ = s >> 7; + s = (k_cn* (*p0++))+(k_dn * (*p1++)); + *p2++ = s >> 7; + s = (k_cn* (*p0++))+(k_dn * (*p1++)); + *p2++ = s >> 7; + s = (k_cn* (*p0++))+(k_dn * (*p1++)); + *p2++ = s >> 7; + } + + /* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[] */ + for (i = 0; i < L_SUBFR; i ++) + { + val = dn[i]; + ps = dn2[i]; + if (ps >= 0) + { + sign[i] = 32767; /* sign = +1 (Q12) */ + vec[i] = -32768; + } else + { + sign[i] = -32768; /* sign = -1 (Q12) */ + vec[i] = 32767; + dn[i] = -val; + } + } + /*------------------------------------------------------------* + * Compute h_inv[i]. * + *------------------------------------------------------------*/ + /* impulse response buffer for fast computation */ + h = h_buf + L_SUBFR; + h_inv = h + (L_SUBFR<<1); + + for (i = 0; i < L_SUBFR; i++) + { + h[i] = H[i]; + h_inv[i] = vo_negate(h[i]); + } + + /*------------------------------------------------------------* + * Compute rrixix[][] needed for the codebook search. * + * Result is multiplied by 0.5 * + *------------------------------------------------------------*/ + /* Init pointers to last position of rrixix[] */ + p0 = &rrixix[0][NB_POS - 1]; + p1 = &rrixix[1][NB_POS - 1]; + + ptr_h1 = h; + cor = 0x00010000L; /* for rounding */ + for (i = 0; i < NB_POS; i++) + { + cor += ((*ptr_h1) * (*ptr_h1) << 1); + ptr_h1++; + *p1-- = (extract_h(cor) >> 1); + cor += ((*ptr_h1) * (*ptr_h1) << 1); + ptr_h1++; + *p0-- = (extract_h(cor) >> 1); + } + + /*------------------------------------------------------------* + * Compute rrixiy[][] needed for the codebook search. * + *------------------------------------------------------------*/ + pos = MSIZE - 1; + pos2 = MSIZE - 2; + ptr_hf = h + 1; + + for (k = 0; k < NB_POS; k++) + { + p1 = &rrixiy[pos]; + p0 = &rrixiy[pos2]; + cor = 0x00008000L; /* for rounding */ + ptr_h1 = h; + ptr_h2 = ptr_hf; + + for (i = (k + 1); i < NB_POS; i++) + { + cor += ((*ptr_h1) * (*ptr_h2))<<1; + ptr_h1++; + ptr_h2++; + *p1 = extract_h(cor); + cor += ((*ptr_h1) * (*ptr_h2))<<1; + ptr_h1++; + ptr_h2++; + *p0 = extract_h(cor); + + p1 -= (NB_POS + 1); + p0 -= (NB_POS + 1); + } + cor += ((*ptr_h1) * (*ptr_h2))<<1; + ptr_h1++; + ptr_h2++; + *p1 = extract_h(cor); + + pos -= NB_POS; + pos2--; + ptr_hf += STEP; + } + + /*------------------------------------------------------------* + * Modification of rrixiy[][] to take signs into account. * + *------------------------------------------------------------*/ + p0 = rrixiy; + for (i = 0; i < L_SUBFR; i += STEP) + { + psign = sign; + if (psign[i] < 0) + { + psign = vec; + } + for (j = 1; j < L_SUBFR; j += STEP) + { + *p0 = vo_mult(*p0, psign[j]); + p0++; + } + } + /*-------------------------------------------------------------------* + * search 2 pulses: * + * ~@~~~~~~~~~~~~~~ * + * 32 pos x 32 pos = 1024 tests (all combinaisons is tested) * + *-------------------------------------------------------------------*/ + p0 = rrixix[0]; + p1 = rrixix[1]; + p2 = rrixiy; + + psk = -1; + alpk = 1; + ix = 0; + iy = 1; + + for (i0 = 0; i0 < L_SUBFR; i0 += STEP) + { + ps1 = dn[i0]; + alp1 = (*p0++); + pos = -1; + for (i1 = 1; i1 < L_SUBFR; i1 += STEP) + { + ps2 = add1(ps1, dn[i1]); + alp2 = add1(alp1, add1(*p1++, *p2++)); + sq = vo_mult(ps2, ps2); + s = vo_L_mult(alpk, sq) - ((psk * alp2)<<1); + if (s > 0) + { + psk = sq; + alpk = alp2; + pos = i1; + } + } + p1 -= NB_POS; + if (pos >= 0) + { + ix = i0; + iy = pos; + } + } + /*-------------------------------------------------------------------* + * Build the codeword, the filtered codeword and index of codevector.* + *-------------------------------------------------------------------*/ + + for (i = 0; i < L_SUBFR; i++) + { + code[i] = 0; + } + + i0 = (ix >> 1); /* pos of pulse 1 (0..31) */ + i1 = (iy >> 1); /* pos of pulse 2 (0..31) */ + if (sign[ix] > 0) + { + code[ix] = 512; /* codeword in Q9 format */ + p0 = h - ix; + } else + { + code[ix] = -512; + i0 += NB_POS; + p0 = h_inv - ix; + } + if (sign[iy] > 0) + { + code[iy] = 512; + p1 = h - iy; + } else + { + code[iy] = -512; + i1 += NB_POS; + p1 = h_inv - iy; + } + *index = add1((i0 << 6), i1); + for (i = 0; i < L_SUBFR; i++) + { + y[i] = vo_shr_r(add1((*p0++), (*p1++)), 3); + } + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c new file mode 100644 index 0000000000000000000000000000000000000000..27ba95ddc879b2aa84ddb66f81b9bf47d1667f35 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c @@ -0,0 +1,1043 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: c4t64fx.c * +* * +* Description:Performs algebraic codebook search for higher modes * +* * +************************************************************************/ + +/************************************************************************ +* Function: ACELP_4t64_fx() * +* * +* 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook. * +* 4 tracks x 16 positions per track = 64 samples. * +* * +* 20 bits --> 4 pulses in a frame of 64 samples. * +* 36 bits --> 8 pulses in a frame of 64 samples. * +* 44 bits --> 10 pulses in a frame of 64 samples. * +* 52 bits --> 12 pulses in a frame of 64 samples. * +* 64 bits --> 16 pulses in a frame of 64 samples. * +* 72 bits --> 18 pulses in a frame of 64 samples. * +* 88 bits --> 24 pulses in a frame of 64 samples. * +* * +* All pulses can have two (2) possible amplitudes: +1 or -1. * +* Each pulse can have sixteen (16) possible positions. * +*************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "math_op.h" +#include "acelp.h" +#include "cnst.h" + +#include "q_pulse.h" + +static Word16 tipos[36] = { + 0, 1, 2, 3, /* starting point &ipos[0], 1st iter */ + 1, 2, 3, 0, /* starting point &ipos[4], 2nd iter */ + 2, 3, 0, 1, /* starting point &ipos[8], 3rd iter */ + 3, 0, 1, 2, /* starting point &ipos[12], 4th iter */ + 0, 1, 2, 3, + 1, 2, 3, 0, + 2, 3, 0, 1, + 3, 0, 1, 2, + 0, 1, 2, 3}; /* end point for 24 pulses &ipos[35], 4th iter */ + +#define NB_PULSE_MAX 24 + +#define L_SUBFR 64 +#define NB_TRACK 4 +#define STEP 4 +#define NB_POS 16 +#define MSIZE 256 +#define NB_MAX 8 +#define NPMAXPT ((NB_PULSE_MAX+NB_TRACK-1)/NB_TRACK) + +/* Private functions */ +void cor_h_vec_012( + Word16 h[], /* (i) scaled impulse response */ + Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */ + Word16 track, /* (i) track to use */ + Word16 sign[], /* (i) sign vector */ + Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */ + Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */ + Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */ + ); + +void cor_h_vec_012_asm( + Word16 h[], /* (i) scaled impulse response */ + Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */ + Word16 track, /* (i) track to use */ + Word16 sign[], /* (i) sign vector */ + Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */ + Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */ + Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */ + ); + +void cor_h_vec_30( + Word16 h[], /* (i) scaled impulse response */ + Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */ + Word16 track, /* (i) track to use */ + Word16 sign[], /* (i) sign vector */ + Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */ + Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */ + Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */ + ); + +void search_ixiy( + Word16 nb_pos_ix, /* (i) nb of pos for pulse 1 (1..8) */ + Word16 track_x, /* (i) track of pulse 1 */ + Word16 track_y, /* (i) track of pulse 2 */ + Word16 * ps, /* (i/o) correlation of all fixed pulses */ + Word16 * alp, /* (i/o) energy of all fixed pulses */ + Word16 * ix, /* (o) position of pulse 1 */ + Word16 * iy, /* (o) position of pulse 2 */ + Word16 dn[], /* (i) corr. between target and h[] */ + Word16 dn2[], /* (i) vector of selected positions */ + Word16 cor_x[], /* (i) corr. of pulse 1 with fixed pulses */ + Word16 cor_y[], /* (i) corr. of pulse 2 with fixed pulses */ + Word16 rrixiy[][MSIZE] /* (i) corr. of pulse 1 with pulse 2 */ + ); + + +void ACELP_4t64_fx( + Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */ + Word16 cn[], /* (i) <12b : residual after long term prediction */ + Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */ + Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */ + Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */ + Word16 nbbits, /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits */ + Word16 ser_size, /* (i) : bit rate */ + Word16 _index[] /* (o) : index (20): 5+5+5+5 = 20 bits. */ + /* (o) : index (36): 9+9+9+9 = 36 bits. */ + /* (o) : index (44): 13+9+13+9 = 44 bits. */ + /* (o) : index (52): 13+13+13+13 = 52 bits. */ + /* (o) : index (64): 2+2+2+2+14+14+14+14 = 64 bits. */ + /* (o) : index (72): 10+2+10+2+10+14+10+14 = 72 bits. */ + /* (o) : index (88): 11+11+11+11+11+11+11+11 = 88 bits. */ + ) +{ + Word32 i, j, k; + Word16 st, ix, iy, pos, index, track, nb_pulse, nbiter, j_temp; + Word16 psk, ps, alpk, alp, val, k_cn, k_dn, exp; + Word16 *p0, *p1, *p2, *p3, *psign; + Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf, h_shift; + Word32 s, cor, L_tmp, L_index; + Word16 dn2[L_SUBFR], sign[L_SUBFR], vec[L_SUBFR]; + Word16 ind[NPMAXPT * NB_TRACK]; + Word16 codvec[NB_PULSE_MAX], nbpos[10]; + Word16 cor_x[NB_POS], cor_y[NB_POS], pos_max[NB_TRACK]; + Word16 h_buf[4 * L_SUBFR]; + Word16 rrixix[NB_TRACK][NB_POS], rrixiy[NB_TRACK][MSIZE]; + Word16 ipos[NB_PULSE_MAX]; + + switch (nbbits) + { + case 20: /* 20 bits, 4 pulses, 4 tracks */ + nbiter = 4; /* 4x16x16=1024 loop */ + alp = 8192; /* alp = 2.0 (Q12) */ + nb_pulse = 4; + nbpos[0] = 4; + nbpos[1] = 8; + break; + case 36: /* 36 bits, 8 pulses, 4 tracks */ + nbiter = 4; /* 4x20x16=1280 loop */ + alp = 4096; /* alp = 1.0 (Q12) */ + nb_pulse = 8; + nbpos[0] = 4; + nbpos[1] = 8; + nbpos[2] = 8; + break; + case 44: /* 44 bits, 10 pulses, 4 tracks */ + nbiter = 4; /* 4x26x16=1664 loop */ + alp = 4096; /* alp = 1.0 (Q12) */ + nb_pulse = 10; + nbpos[0] = 4; + nbpos[1] = 6; + nbpos[2] = 8; + nbpos[3] = 8; + break; + case 52: /* 52 bits, 12 pulses, 4 tracks */ + nbiter = 4; /* 4x26x16=1664 loop */ + alp = 4096; /* alp = 1.0 (Q12) */ + nb_pulse = 12; + nbpos[0] = 4; + nbpos[1] = 6; + nbpos[2] = 8; + nbpos[3] = 8; + break; + case 64: /* 64 bits, 16 pulses, 4 tracks */ + nbiter = 3; /* 3x36x16=1728 loop */ + alp = 3277; /* alp = 0.8 (Q12) */ + nb_pulse = 16; + nbpos[0] = 4; + nbpos[1] = 4; + nbpos[2] = 6; + nbpos[3] = 6; + nbpos[4] = 8; + nbpos[5] = 8; + break; + case 72: /* 72 bits, 18 pulses, 4 tracks */ + nbiter = 3; /* 3x35x16=1680 loop */ + alp = 3072; /* alp = 0.75 (Q12) */ + nb_pulse = 18; + nbpos[0] = 2; + nbpos[1] = 3; + nbpos[2] = 4; + nbpos[3] = 5; + nbpos[4] = 6; + nbpos[5] = 7; + nbpos[6] = 8; + break; + case 88: /* 88 bits, 24 pulses, 4 tracks */ + if(ser_size > 462) + nbiter = 1; + else + nbiter = 2; /* 2x53x16=1696 loop */ + + alp = 2048; /* alp = 0.5 (Q12) */ + nb_pulse = 24; + nbpos[0] = 2; + nbpos[1] = 2; + nbpos[2] = 3; + nbpos[3] = 4; + nbpos[4] = 5; + nbpos[5] = 6; + nbpos[6] = 7; + nbpos[7] = 8; + nbpos[8] = 8; + nbpos[9] = 8; + break; + default: + nbiter = 0; + alp = 0; + nb_pulse = 0; + } + + for (i = 0; i < nb_pulse; i++) + { + codvec[i] = i; + } + + /*----------------------------------------------------------------* + * Find sign for each pulse position. * + *----------------------------------------------------------------*/ + /* calculate energy for normalization of cn[] and dn[] */ + /* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */ +#ifdef ASM_OPT /* asm optimization branch */ + s = Dot_product12_asm(cn, cn, L_SUBFR, &exp); +#else + s = Dot_product12(cn, cn, L_SUBFR, &exp); +#endif + + Isqrt_n(&s, &exp); + s = L_shl(s, (exp + 5)); + k_cn = extract_h(L_add(s, 0x8000)); + + /* set k_dn = 32..512 (ener_dn = 2^30..2^22) */ +#ifdef ASM_OPT /* asm optimization branch */ + s = Dot_product12_asm(dn, dn, L_SUBFR, &exp); +#else + s = Dot_product12(dn, dn, L_SUBFR, &exp); +#endif + + Isqrt_n(&s, &exp); + k_dn = (L_shl(s, (exp + 5 + 3)) + 0x8000) >> 16; /* k_dn = 256..4096 */ + k_dn = vo_mult_r(alp, k_dn); /* alp in Q12 */ + + /* mix normalized cn[] and dn[] */ + p0 = cn; + p1 = dn; + p2 = dn2; + + for (i = 0; i < L_SUBFR/4; i++) + { + s = (k_cn* (*p0++))+(k_dn * (*p1++)); + *p2++ = s >> 7; + s = (k_cn* (*p0++))+(k_dn * (*p1++)); + *p2++ = s >> 7; + s = (k_cn* (*p0++))+(k_dn * (*p1++)); + *p2++ = s >> 7; + s = (k_cn* (*p0++))+(k_dn * (*p1++)); + *p2++ = s >> 7; + } + + /* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[] */ + for(i = 0; i < L_SUBFR; i++) + { + val = dn[i]; + ps = dn2[i]; + if (ps >= 0) + { + sign[i] = 32767; /* sign = +1 (Q12) */ + vec[i] = -32768; + } else + { + sign[i] = -32768; /* sign = -1 (Q12) */ + vec[i] = 32767; + dn[i] = -val; + dn2[i] = -ps; + } + } + /*----------------------------------------------------------------* + * Select NB_MAX position per track according to max of dn2[]. * + *----------------------------------------------------------------*/ + pos = 0; + for (i = 0; i < NB_TRACK; i++) + { + for (k = 0; k < NB_MAX; k++) + { + ps = -1; + for (j = i; j < L_SUBFR; j += STEP) + { + if(dn2[j] > ps) + { + ps = dn2[j]; + pos = j; + } + } + dn2[pos] = (k - NB_MAX); /* dn2 < 0 when position is selected */ + if (k == 0) + { + pos_max[i] = pos; + } + } + } + + /*--------------------------------------------------------------* + * Scale h[] to avoid overflow and to get maximum of precision * + * on correlation. * + * * + * Maximum of h[] (h[0]) is fixed to 2048 (MAX16 / 16). * + * ==> This allow addition of 16 pulses without saturation. * + * * + * Energy worst case (on resonant impulse response), * + * - energy of h[] is approximately MAX/16. * + * - During search, the energy is divided by 8 to avoid * + * overflow on "alp". (energy of h[] = MAX/128). * + * ==> "alp" worst case detected is 22854 on sinusoidal wave. * + *--------------------------------------------------------------*/ + + /* impulse response buffer for fast computation */ + + h = h_buf; + h_inv = h_buf + (2 * L_SUBFR); + L_tmp = 0; + for (i = 0; i < L_SUBFR; i++) + { + *h++ = 0; + *h_inv++ = 0; + L_tmp += (H[i] * H[i]) << 1; + } + /* scale h[] down (/2) when energy of h[] is high with many pulses used */ + val = extract_h(L_tmp); + h_shift = 0; + + if ((nb_pulse >= 12) && (val > 1024)) + { + h_shift = 1; + } + p0 = H; + p1 = h; + p2 = h_inv; + + for (i = 0; i < L_SUBFR/4; i++) + { + *p1 = *p0++ >> h_shift; + *p2++ = -(*p1++); + *p1 = *p0++ >> h_shift; + *p2++ = -(*p1++); + *p1 = *p0++ >> h_shift; + *p2++ = -(*p1++); + *p1 = *p0++ >> h_shift; + *p2++ = -(*p1++); + } + + /*------------------------------------------------------------* + * Compute rrixix[][] needed for the codebook search. * + * This algorithm compute impulse response energy of all * + * positions (16) in each track (4). Total = 4x16 = 64. * + *------------------------------------------------------------*/ + + /* storage order --> i3i3, i2i2, i1i1, i0i0 */ + + /* Init pointers to last position of rrixix[] */ + p0 = &rrixix[0][NB_POS - 1]; + p1 = &rrixix[1][NB_POS - 1]; + p2 = &rrixix[2][NB_POS - 1]; + p3 = &rrixix[3][NB_POS - 1]; + + ptr_h1 = h; + cor = 0x00008000L; /* for rounding */ + for (i = 0; i < NB_POS; i++) + { + cor += vo_L_mult((*ptr_h1), (*ptr_h1)); + ptr_h1++; + *p3-- = extract_h(cor); + cor += vo_L_mult((*ptr_h1), (*ptr_h1)); + ptr_h1++; + *p2-- = extract_h(cor); + cor += vo_L_mult((*ptr_h1), (*ptr_h1)); + ptr_h1++; + *p1-- = extract_h(cor); + cor += vo_L_mult((*ptr_h1), (*ptr_h1)); + ptr_h1++; + *p0-- = extract_h(cor); + } + + /*------------------------------------------------------------* + * Compute rrixiy[][] needed for the codebook search. * + * This algorithm compute correlation between 2 pulses * + * (2 impulses responses) in 4 possible adjacents tracks. * + * (track 0-1, 1-2, 2-3 and 3-0). Total = 4x16x16 = 1024. * + *------------------------------------------------------------*/ + + /* storage order --> i2i3, i1i2, i0i1, i3i0 */ + + pos = MSIZE - 1; + ptr_hf = h + 1; + + for (k = 0; k < NB_POS; k++) + { + p3 = &rrixiy[2][pos]; + p2 = &rrixiy[1][pos]; + p1 = &rrixiy[0][pos]; + p0 = &rrixiy[3][pos - NB_POS]; + + cor = 0x00008000L; /* for rounding */ + ptr_h1 = h; + ptr_h2 = ptr_hf; + + for (i = k + 1; i < NB_POS; i++) + { + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p3 = extract_h(cor); + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p2 = extract_h(cor); + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p1 = extract_h(cor); + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p0 = extract_h(cor); + + p3 -= (NB_POS + 1); + p2 -= (NB_POS + 1); + p1 -= (NB_POS + 1); + p0 -= (NB_POS + 1); + } + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p3 = extract_h(cor); + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p2 = extract_h(cor); + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p1 = extract_h(cor); + + pos -= NB_POS; + ptr_hf += STEP; + } + + /* storage order --> i3i0, i2i3, i1i2, i0i1 */ + + pos = MSIZE - 1; + ptr_hf = h + 3; + + for (k = 0; k < NB_POS; k++) + { + p3 = &rrixiy[3][pos]; + p2 = &rrixiy[2][pos - 1]; + p1 = &rrixiy[1][pos - 1]; + p0 = &rrixiy[0][pos - 1]; + + cor = 0x00008000L; /* for rounding */ + ptr_h1 = h; + ptr_h2 = ptr_hf; + + for (i = k + 1; i < NB_POS; i++) + { + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p3 = extract_h(cor); + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p2 = extract_h(cor); + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p1 = extract_h(cor); + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p0 = extract_h(cor); + + p3 -= (NB_POS + 1); + p2 -= (NB_POS + 1); + p1 -= (NB_POS + 1); + p0 -= (NB_POS + 1); + } + cor += vo_L_mult((*ptr_h1), (*ptr_h2)); + ptr_h1++; + ptr_h2++; + *p3 = extract_h(cor); + + pos--; + ptr_hf += STEP; + } + + /*------------------------------------------------------------* + * Modification of rrixiy[][] to take signs into account. * + *------------------------------------------------------------*/ + + p0 = &rrixiy[0][0]; + + for (k = 0; k < NB_TRACK; k++) + { + j_temp = (k + 1)&0x03; + for (i = k; i < L_SUBFR; i += STEP) + { + psign = sign; + if (psign[i] < 0) + { + psign = vec; + } + j = j_temp; + for (; j < L_SUBFR; j += STEP) + { + *p0 = vo_mult(*p0, psign[j]); + p0++; + } + } + } + + /*-------------------------------------------------------------------* + * Deep first search * + *-------------------------------------------------------------------*/ + + psk = -1; + alpk = 1; + + for (k = 0; k < nbiter; k++) + { + j_temp = k<<2; + for (i = 0; i < nb_pulse; i++) + ipos[i] = tipos[j_temp + i]; + + if(nbbits == 20) + { + pos = 0; + ps = 0; + alp = 0; + for (i = 0; i < L_SUBFR; i++) + { + vec[i] = 0; + } + } else if ((nbbits == 36) || (nbbits == 44)) + { + /* first stage: fix 2 pulses */ + pos = 2; + + ix = ind[0] = pos_max[ipos[0]]; + iy = ind[1] = pos_max[ipos[1]]; + ps = dn[ix] + dn[iy]; + i = ix >> 2; /* ix / STEP */ + j = iy >> 2; /* iy / STEP */ + s = rrixix[ipos[0]][i] << 13; + s += rrixix[ipos[1]][j] << 13; + i = (i << 4) + j; /* (ix/STEP)*NB_POS + (iy/STEP) */ + s += rrixiy[ipos[0]][i] << 14; + alp = (s + 0x8000) >> 16; + if (sign[ix] < 0) + p0 = h_inv - ix; + else + p0 = h - ix; + if (sign[iy] < 0) + p1 = h_inv - iy; + else + p1 = h - iy; + + for (i = 0; i < L_SUBFR; i++) + { + vec[i] = (*p0++) + (*p1++); + } + + if(nbbits == 44) + { + ipos[8] = 0; + ipos[9] = 1; + } + } else + { + /* first stage: fix 4 pulses */ + pos = 4; + + ix = ind[0] = pos_max[ipos[0]]; + iy = ind[1] = pos_max[ipos[1]]; + i = ind[2] = pos_max[ipos[2]]; + j = ind[3] = pos_max[ipos[3]]; + ps = add1(add1(add1(dn[ix], dn[iy]), dn[i]), dn[j]); + + if (sign[ix] < 0) + p0 = h_inv - ix; + else + p0 = h - ix; + + if (sign[iy] < 0) + p1 = h_inv - iy; + else + p1 = h - iy; + + if (sign[i] < 0) + p2 = h_inv - i; + else + p2 = h - i; + + if (sign[j] < 0) + p3 = h_inv - j; + else + p3 = h - j; + + L_tmp = 0L; + for(i = 0; i < L_SUBFR; i++) + { + vec[i] = add1(add1(add1(*p0++, *p1++), *p2++), *p3++); + L_tmp += (vec[i] * vec[i]) << 1; + } + + alp = ((L_tmp >> 3) + 0x8000) >> 16; + + if(nbbits == 72) + { + ipos[16] = 0; + ipos[17] = 1; + } + } + + /* other stages of 2 pulses */ + + for (j = pos, st = 0; j < nb_pulse; j += 2, st++) + { + /*--------------------------------------------------* + * Calculate correlation of all possible positions * + * of the next 2 pulses with previous fixed pulses. * + * Each pulse can have 16 possible positions. * + *--------------------------------------------------*/ + if(ipos[j] == 3) + { + cor_h_vec_30(h, vec, ipos[j], sign, rrixix, cor_x, cor_y); + } + else + { +#ifdef ASM_OPT /* asm optimization branch */ + cor_h_vec_012_asm(h, vec, ipos[j], sign, rrixix, cor_x, cor_y); +#else + cor_h_vec_012(h, vec, ipos[j], sign, rrixix, cor_x, cor_y); +#endif + } + /*--------------------------------------------------* + * Find best positions of 2 pulses. * + *--------------------------------------------------*/ + search_ixiy(nbpos[st], ipos[j], ipos[j + 1], &ps, &alp, + &ix, &iy, dn, dn2, cor_x, cor_y, rrixiy); + + ind[j] = ix; + ind[j + 1] = iy; + + if (sign[ix] < 0) + p0 = h_inv - ix; + else + p0 = h - ix; + if (sign[iy] < 0) + p1 = h_inv - iy; + else + p1 = h - iy; + + for (i = 0; i < L_SUBFR; i+=4) + { + vec[i] += add1((*p0++), (*p1++)); + vec[i+1] += add1((*p0++), (*p1++)); + vec[i+2] += add1((*p0++), (*p1++)); + vec[i+3] += add1((*p0++), (*p1++)); + } + } + /* memorise the best codevector */ + ps = vo_mult(ps, ps); + s = vo_L_msu(vo_L_mult(alpk, ps), psk, alp); + if (s > 0) + { + psk = ps; + alpk = alp; + for (i = 0; i < nb_pulse; i++) + { + codvec[i] = ind[i]; + } + for (i = 0; i < L_SUBFR; i++) + { + y[i] = vec[i]; + } + } + } + /*-------------------------------------------------------------------* + * Build the codeword, the filtered codeword and index of codevector.* + *-------------------------------------------------------------------*/ + for (i = 0; i < NPMAXPT * NB_TRACK; i++) + { + ind[i] = -1; + } + for (i = 0; i < L_SUBFR; i++) + { + code[i] = 0; + y[i] = vo_shr_r(y[i], 3); /* Q12 to Q9 */ + } + val = (512 >> h_shift); /* codeword in Q9 format */ + for (k = 0; k < nb_pulse; k++) + { + i = codvec[k]; /* read pulse position */ + j = sign[i]; /* read sign */ + index = i >> 2; /* index = pos of pulse (0..15) */ + track = (Word16) (i & 0x03); /* track = i % NB_TRACK (0..3) */ + + if (j > 0) + { + code[i] += val; + codvec[k] += 128; + } else + { + code[i] -= val; + index += NB_POS; + } + + i = (Word16)((vo_L_mult(track, NPMAXPT) >> 1)); + + while (ind[i] >= 0) + { + i += 1; + } + ind[i] = index; + } + + k = 0; + /* Build index of codevector */ + if(nbbits == 20) + { + for (track = 0; track < NB_TRACK; track++) + { + _index[track] = (Word16)(quant_1p_N1(ind[k], 4)); + k += NPMAXPT; + } + } else if(nbbits == 36) + { + for (track = 0; track < NB_TRACK; track++) + { + _index[track] = (Word16)(quant_2p_2N1(ind[k], ind[k + 1], 4)); + k += NPMAXPT; + } + } else if(nbbits == 44) + { + for (track = 0; track < NB_TRACK - 2; track++) + { + _index[track] = (Word16)(quant_3p_3N1(ind[k], ind[k + 1], ind[k + 2], 4)); + k += NPMAXPT; + } + for (track = 2; track < NB_TRACK; track++) + { + _index[track] = (Word16)(quant_2p_2N1(ind[k], ind[k + 1], 4)); + k += NPMAXPT; + } + } else if(nbbits == 52) + { + for (track = 0; track < NB_TRACK; track++) + { + _index[track] = (Word16)(quant_3p_3N1(ind[k], ind[k + 1], ind[k + 2], 4)); + k += NPMAXPT; + } + } else if(nbbits == 64) + { + for (track = 0; track < NB_TRACK; track++) + { + L_index = quant_4p_4N(&ind[k], 4); + _index[track] = (Word16)((L_index >> 14) & 3); + _index[track + NB_TRACK] = (Word16)(L_index & 0x3FFF); + k += NPMAXPT; + } + } else if(nbbits == 72) + { + for (track = 0; track < NB_TRACK - 2; track++) + { + L_index = quant_5p_5N(&ind[k], 4); + _index[track] = (Word16)((L_index >> 10) & 0x03FF); + _index[track + NB_TRACK] = (Word16)(L_index & 0x03FF); + k += NPMAXPT; + } + for (track = 2; track < NB_TRACK; track++) + { + L_index = quant_4p_4N(&ind[k], 4); + _index[track] = (Word16)((L_index >> 14) & 3); + _index[track + NB_TRACK] = (Word16)(L_index & 0x3FFF); + k += NPMAXPT; + } + } else if(nbbits == 88) + { + for (track = 0; track < NB_TRACK; track++) + { + L_index = quant_6p_6N_2(&ind[k], 4); + _index[track] = (Word16)((L_index >> 11) & 0x07FF); + _index[track + NB_TRACK] = (Word16)(L_index & 0x07FF); + k += NPMAXPT; + } + } + return; +} + + +/*-------------------------------------------------------------------* + * Function cor_h_vec() * + * ~~~~~~~~~~~~~~~~~~~~~ * + * Compute correlations of h[] with vec[] for the specified track. * + *-------------------------------------------------------------------*/ +void cor_h_vec_30( + Word16 h[], /* (i) scaled impulse response */ + Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */ + Word16 track, /* (i) track to use */ + Word16 sign[], /* (i) sign vector */ + Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */ + Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */ + Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */ + ) +{ + Word32 i, j, pos, corr; + Word16 *p0, *p1, *p2,*p3,*cor_x,*cor_y; + Word32 L_sum1,L_sum2; + cor_x = cor_1; + cor_y = cor_2; + p0 = rrixix[track]; + p3 = rrixix[0]; + pos = track; + + for (i = 0; i < NB_POS; i+=2) + { + L_sum1 = L_sum2 = 0L; + p1 = h; + p2 = &vec[pos]; + for (j=pos;j < L_SUBFR; j++) + { + L_sum1 += *p1 * *p2; + p2-=3; + L_sum2 += *p1++ * *p2; + p2+=4; + } + p2-=3; + L_sum2 += *p1++ * *p2++; + L_sum2 += *p1++ * *p2++; + L_sum2 += *p1++ * *p2++; + + L_sum1 = (L_sum1 << 2); + L_sum2 = (L_sum2 << 2); + + corr = vo_round(L_sum1); + *cor_x++ = vo_mult(corr, sign[pos]) + (*p0++); + corr = vo_round(L_sum2); + *cor_y++ = vo_mult(corr, sign[pos-3]) + (*p3++); + pos += STEP; + + L_sum1 = L_sum2 = 0L; + p1 = h; + p2 = &vec[pos]; + for (j=pos;j < L_SUBFR; j++) + { + L_sum1 += *p1 * *p2; + p2-=3; + L_sum2 += *p1++ * *p2; + p2+=4; + } + p2-=3; + L_sum2 += *p1++ * *p2++; + L_sum2 += *p1++ * *p2++; + L_sum2 += *p1++ * *p2++; + + L_sum1 = (L_sum1 << 2); + L_sum2 = (L_sum2 << 2); + + corr = vo_round(L_sum1); + *cor_x++ = vo_mult(corr, sign[pos]) + (*p0++); + corr = vo_round(L_sum2); + *cor_y++ = vo_mult(corr, sign[pos-3]) + (*p3++); + pos += STEP; + } + return; +} + +void cor_h_vec_012( + Word16 h[], /* (i) scaled impulse response */ + Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */ + Word16 track, /* (i) track to use */ + Word16 sign[], /* (i) sign vector */ + Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */ + Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */ + Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */ + ) +{ + Word32 i, j, pos, corr; + Word16 *p0, *p1, *p2,*p3,*cor_x,*cor_y; + Word32 L_sum1,L_sum2; + cor_x = cor_1; + cor_y = cor_2; + p0 = rrixix[track]; + p3 = rrixix[track+1]; + pos = track; + + for (i = 0; i < NB_POS; i+=2) + { + L_sum1 = L_sum2 = 0L; + p1 = h; + p2 = &vec[pos]; + for (j=62-pos ;j >= 0; j--) + { + L_sum1 += *p1 * *p2++; + L_sum2 += *p1++ * *p2; + } + L_sum1 += *p1 * *p2; + L_sum1 = (L_sum1 << 2); + L_sum2 = (L_sum2 << 2); + + corr = (L_sum1 + 0x8000) >> 16; + cor_x[i] = vo_mult(corr, sign[pos]) + (*p0++); + corr = (L_sum2 + 0x8000) >> 16; + cor_y[i] = vo_mult(corr, sign[pos + 1]) + (*p3++); + pos += STEP; + + L_sum1 = L_sum2 = 0L; + p1 = h; + p2 = &vec[pos]; + for (j= 62-pos;j >= 0; j--) + { + L_sum1 += *p1 * *p2++; + L_sum2 += *p1++ * *p2; + } + L_sum1 += *p1 * *p2; + L_sum1 = (L_sum1 << 2); + L_sum2 = (L_sum2 << 2); + + corr = (L_sum1 + 0x8000) >> 16; + cor_x[i+1] = vo_mult(corr, sign[pos]) + (*p0++); + corr = (L_sum2 + 0x8000) >> 16; + cor_y[i+1] = vo_mult(corr, sign[pos + 1]) + (*p3++); + pos += STEP; + } + return; +} + +/*-------------------------------------------------------------------* + * Function search_ixiy() * + * ~~~~~~~~~~~~~~~~~~~~~~~ * + * Find the best positions of 2 pulses in a subframe. * + *-------------------------------------------------------------------*/ + +void search_ixiy( + Word16 nb_pos_ix, /* (i) nb of pos for pulse 1 (1..8) */ + Word16 track_x, /* (i) track of pulse 1 */ + Word16 track_y, /* (i) track of pulse 2 */ + Word16 * ps, /* (i/o) correlation of all fixed pulses */ + Word16 * alp, /* (i/o) energy of all fixed pulses */ + Word16 * ix, /* (o) position of pulse 1 */ + Word16 * iy, /* (o) position of pulse 2 */ + Word16 dn[], /* (i) corr. between target and h[] */ + Word16 dn2[], /* (i) vector of selected positions */ + Word16 cor_x[], /* (i) corr. of pulse 1 with fixed pulses */ + Word16 cor_y[], /* (i) corr. of pulse 2 with fixed pulses */ + Word16 rrixiy[][MSIZE] /* (i) corr. of pulse 1 with pulse 2 */ + ) +{ + Word32 x, y, pos, thres_ix; + Word16 ps1, ps2, sq, sqk; + Word16 alp_16, alpk; + Word16 *p0, *p1, *p2; + Word32 s, alp0, alp1, alp2; + + p0 = cor_x; + p1 = cor_y; + p2 = rrixiy[track_x]; + + thres_ix = nb_pos_ix - NB_MAX; + + alp0 = L_deposit_h(*alp); + alp0 = (alp0 + 0x00008000L); /* for rounding */ + + sqk = -1; + alpk = 1; + + for (x = track_x; x < L_SUBFR; x += STEP) + { + ps1 = *ps + dn[x]; + alp1 = alp0 + ((*p0++)<<13); + + if (dn2[x] < thres_ix) + { + pos = -1; + for (y = track_y; y < L_SUBFR; y += STEP) + { + ps2 = add1(ps1, dn[y]); + + alp2 = alp1 + ((*p1++)<<13); + alp2 = alp2 + ((*p2++)<<14); + alp_16 = extract_h(alp2); + sq = vo_mult(ps2, ps2); + s = vo_L_mult(alpk, sq) - ((sqk * alp_16)<<1); + + if (s > 0) + { + sqk = sq; + alpk = alp_16; + pos = y; + } + } + p1 -= NB_POS; + + if (pos >= 0) + { + *ix = x; + *iy = pos; + } + } else + { + p2 += NB_POS; + } + } + + *ps = add1(*ps, add1(dn[*ix], dn[*iy])); + *alp = alpk; + + return; +} + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c b/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c new file mode 100644 index 0000000000000000000000000000000000000000..c17264c15dbc323eed30eb1055f9c3010bb7b424 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c @@ -0,0 +1,73 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: cmnMemory.c + + Content: sample code for memory operator implementation + +*******************************************************************************/ +#include "cmnMemory.h" + +#include +#if defined LINUX +#include +#endif + +//VO_MEM_OPERATOR g_memOP; + +VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo) +{ + if (!pMemInfo) + return VO_ERR_INVALID_ARG; + + pMemInfo->VBuffer = malloc (pMemInfo->Size); + return 0; +} + +VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pMem) +{ + free (pMem); + return 0; +} + +VO_U32 cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize) +{ + memset (pBuff, uValue, uSize); + return 0; +} + +VO_U32 cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) +{ + memcpy (pDest, pSource, uSize); + return 0; +} + +VO_U32 cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize) +{ + return 0; +} + +VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize) +{ + return memcmp(pBuffer1, pBuffer2, uSize); +} + +VO_U32 cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) +{ + memmove (pDest, pSource, uSize); + return 0; +} + diff --git a/media/libstagefright/codecs/amrwbenc/src/convolve.c b/media/libstagefright/codecs/amrwbenc/src/convolve.c new file mode 100644 index 0000000000000000000000000000000000000000..66c74d63cf56721e82983d81a6d42978e0affd59 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/convolve.c @@ -0,0 +1,109 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** + File: convolve.c + + Description:Perform the convolution between two vectors x[] and h[] + and write the result in the vector y[] + +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + +void Convolve ( + Word16 x[], /* (i) : input vector */ + Word16 h[], /* (i) : impulse response */ + Word16 y[], /* (o) : output vector */ + Word16 L /* (i) : vector size */ + ) +{ + Word32 i, n; + Word16 *tmpH,*tmpX; + Word32 s; + for (n = 0; n < 64;) + { + tmpH = h+n; + tmpX = x; + i=n+1; + s = vo_mult32((*tmpX++), (*tmpH--));i--; + while(i>0) + { + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + i -= 4; + } + y[n] = ((s<<1) + 0x8000)>>16; + n++; + + tmpH = h+n; + tmpX = x; + i=n+1; + s = vo_mult32((*tmpX++), (*tmpH--));i--; + s += vo_mult32((*tmpX++), (*tmpH--));i--; + + while(i>0) + { + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + i -= 4; + } + y[n] = ((s<<1) + 0x8000)>>16; + n++; + + tmpH = h+n; + tmpX = x; + i=n+1; + s = vo_mult32((*tmpX++), (*tmpH--));i--; + s += vo_mult32((*tmpX++), (*tmpH--));i--; + s += vo_mult32((*tmpX++), (*tmpH--));i--; + + while(i>0) + { + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + i -= 4; + } + y[n] = ((s<<1) + 0x8000)>>16; + n++; + + s = 0; + tmpH = h+n; + tmpX = x; + i=n+1; + while(i>0) + { + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + s += vo_mult32((*tmpX++), (*tmpH--)); + i -= 4; + } + y[n] = ((s<<1) + 0x8000)>>16; + n++; + } + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c b/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c new file mode 100644 index 0000000000000000000000000000000000000000..3c2e9d591cd31cc5007e300910a89f2923563d10 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c @@ -0,0 +1,127 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: cor_h_x.c * +* * +* Description:Compute correlation between target "x[]" and "h[]" * +* Designed for codebook search (24 pulses, 4 tracks, * +* 4 pulses per track, 16 positions in each track) to * +* avoid saturation. * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "math_op.h" + +#define L_SUBFR 64 +#define NB_TRACK 4 +#define STEP 4 + +void cor_h_x( + Word16 h[], /* (i) Q12 : impulse response of weighted synthesis filter */ + Word16 x[], /* (i) Q0 : target vector */ + Word16 dn[] /* (o) <12bit : correlation between target and h[] */ + ) +{ + Word32 i, j; + Word32 L_tmp, y32[L_SUBFR], L_tot; + Word16 *p1, *p2; + Word32 *p3; + Word32 L_max, L_max1, L_max2, L_max3; + /* first keep the result on 32 bits and find absolute maximum */ + L_tot = 1; + L_max = 0; + L_max1 = 0; + L_max2 = 0; + L_max3 = 0; + for (i = 0; i < L_SUBFR; i += STEP) + { + L_tmp = 1; /* 1 -> to avoid null dn[] */ + p1 = &x[i]; + p2 = &h[0]; + for (j = i; j < L_SUBFR; j++) + L_tmp += vo_L_mult(*p1++, *p2++); + + y32[i] = L_tmp; + L_tmp = (L_tmp > 0)? L_tmp:-L_tmp; + if(L_tmp > L_max) + { + L_max = L_tmp; + } + + L_tmp = 1L; + p1 = &x[i+1]; + p2 = &h[0]; + for (j = i+1; j < L_SUBFR; j++) + L_tmp += vo_L_mult(*p1++, *p2++); + + y32[i+1] = L_tmp; + L_tmp = (L_tmp > 0)? L_tmp:-L_tmp; + if(L_tmp > L_max1) + { + L_max1 = L_tmp; + } + + L_tmp = 1; + p1 = &x[i+2]; + p2 = &h[0]; + for (j = i+2; j < L_SUBFR; j++) + L_tmp += vo_L_mult(*p1++, *p2++); + + y32[i+2] = L_tmp; + L_tmp = (L_tmp > 0)? L_tmp:-L_tmp; + if(L_tmp > L_max2) + { + L_max2 = L_tmp; + } + + L_tmp = 1; + p1 = &x[i+3]; + p2 = &h[0]; + for (j = i+3; j < L_SUBFR; j++) + L_tmp += vo_L_mult(*p1++, *p2++); + + y32[i+3] = L_tmp; + L_tmp = (L_tmp > 0)? L_tmp:-L_tmp; + if(L_tmp > L_max3) + { + L_max3 = L_tmp; + } + } + /* tot += 3*max / 8 */ + L_max = ((L_max + L_max1 + L_max2 + L_max3) >> 2); + L_tot = vo_L_add(L_tot, L_max); /* +max/4 */ + L_tot = vo_L_add(L_tot, (L_max >> 1)); /* +max/8 */ + + /* Find the number of right shifts to do on y32[] so that */ + /* 6.0 x sumation of max of dn[] in each track not saturate. */ + j = norm_l(L_tot) - 4; /* 4 -> 16 x tot */ + p1 = dn; + p3 = y32; + for (i = 0; i < L_SUBFR; i+=4) + { + *p1++ = vo_round(L_shl(*p3++, j)); + *p1++ = vo_round(L_shl(*p3++, j)); + *p1++ = vo_round(L_shl(*p3++, j)); + *p1++ = vo_round(L_shl(*p3++, j)); + } + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/decim54.c b/media/libstagefright/codecs/amrwbenc/src/decim54.c new file mode 100644 index 0000000000000000000000000000000000000000..429a7d61e657caf955da5cc016a1169369296023 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/decim54.c @@ -0,0 +1,146 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: decim54.c * +* * +* Description:Decimation of 16kHz signal to 12.8kHz * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "acelp.h" +#include "cnst.h" + +#define FAC5 5 +#define DOWN_FAC 26215 /* 4/5 in Q15 */ + +#define NB_COEF_DOWN 15 + +/* Local functions */ +static void Down_samp( + Word16 * sig, /* input: signal to downsampling */ + Word16 * sig_d, /* output: downsampled signal */ + Word16 L_frame_d /* input: length of output */ + ); + +/* 1/5 resolution interpolation filter (in Q14) */ +/* -1.5dB @ 6kHz, -6dB @ 6.4kHz, -10dB @ 6.6kHz, -20dB @ 6.9kHz, -25dB @ 7kHz, -55dB @ 8kHz */ + +static Word16 fir_down1[4][30] = +{ + {-5, 24, -50, 54, 0, -128, 294, -408, 344, 0, -647, 1505, -2379, 3034, 13107, 3034, -2379, 1505, -647, 0, 344, -408, + 294, -128, 0, 54, -50, 24, -5, 0}, + + {-6, 19, -26, 0, 77, -188, 270, -233, 0, 434, -964, 1366, -1293, 0, 12254, 6575, -2746, 1030, 0, -507, 601, -441, + 198, 0, -95, 99, -58, 18, 0, -1}, + + {-3, 9, 0, -41, 111, -170, 153, 0, -295, 649, -888, 770, 0, -1997, 9894, 9894, -1997, 0, 770, -888, 649, -295, 0, + 153, -170, 111, -41, 0, 9, -3}, + + {-1, 0, 18, -58, 99, -95, 0, 198, -441, 601, -507, 0, 1030, -2746, 6575, 12254, 0, -1293, 1366, -964, 434, 0, + -233, 270, -188, 77, 0, -26, 19, -6} +}; + +void Init_Decim_12k8( + Word16 mem[] /* output: memory (2*NB_COEF_DOWN) set to zeros */ + ) +{ + Set_zero(mem, 2 * NB_COEF_DOWN); + return; +} + +void Decim_12k8( + Word16 sig16k[], /* input: signal to downsampling */ + Word16 lg, /* input: length of input */ + Word16 sig12k8[], /* output: decimated signal */ + Word16 mem[] /* in/out: memory (2*NB_COEF_DOWN) */ + ) +{ + Word16 lg_down; + Word16 signal[L_FRAME16k + (2 * NB_COEF_DOWN)]; + + Copy(mem, signal, 2 * NB_COEF_DOWN); + + Copy(sig16k, signal + (2 * NB_COEF_DOWN), lg); + + lg_down = (lg * DOWN_FAC)>>15; + + Down_samp(signal + NB_COEF_DOWN, sig12k8, lg_down); + + Copy(signal + lg, mem, 2 * NB_COEF_DOWN); + + return; +} + +static void Down_samp( + Word16 * sig, /* input: signal to downsampling */ + Word16 * sig_d, /* output: downsampled signal */ + Word16 L_frame_d /* input: length of output */ + ) +{ + Word32 i, j, frac, pos; + Word16 *x, *y; + Word32 L_sum; + + pos = 0; /* position is in Q2 -> 1/4 resolution */ + for (j = 0; j < L_frame_d; j++) + { + i = (pos >> 2); /* integer part */ + frac = pos & 3; /* fractional part */ + x = sig + i - NB_COEF_DOWN + 1; + y = (Word16 *)(fir_down1 + frac); + + L_sum = vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x++),(*y++)); + L_sum += vo_mult32((*x),(*y)); + + L_sum = L_shl2(L_sum, 2); + sig_d[j] = extract_h(L_add(L_sum, 0x8000)); + pos += FAC5; /* pos + 5/4 */ + } + return; +} + + diff --git a/media/libstagefright/codecs/amrwbenc/src/deemph.c b/media/libstagefright/codecs/amrwbenc/src/deemph.c new file mode 100644 index 0000000000000000000000000000000000000000..6ad528d9dd6eaafa0799bcb8bf4222313304c04b --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/deemph.c @@ -0,0 +1,117 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: deemph.c * +* * +* Description:filtering through 1/(1-mu z^ -1) * +* Deemph2 --> signal is divided by 2 * +* Deemph_32 --> for 32 bits signal. * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "math_op.h" + +void Deemph( + Word16 x[], /* (i/o) : input signal overwritten by the output */ + Word16 mu, /* (i) Q15 : deemphasis factor */ + Word16 L, /* (i) : vector size */ + Word16 * mem /* (i/o) : memory (y[-1]) */ + ) +{ + Word32 i; + Word32 L_tmp; + + L_tmp = L_deposit_h(x[0]); + L_tmp = L_mac(L_tmp, *mem, mu); + x[0] = vo_round(L_tmp); + + for (i = 1; i < L; i++) + { + L_tmp = L_deposit_h(x[i]); + L_tmp = L_mac(L_tmp, x[i - 1], mu); + x[i] = voround(L_tmp); + } + + *mem = x[L - 1]; + + return; +} + + +void Deemph2( + Word16 x[], /* (i/o) : input signal overwritten by the output */ + Word16 mu, /* (i) Q15 : deemphasis factor */ + Word16 L, /* (i) : vector size */ + Word16 * mem /* (i/o) : memory (y[-1]) */ + ) +{ + Word32 i; + Word32 L_tmp; + L_tmp = x[0] << 15; + L_tmp += ((*mem) * mu)<<1; + x[0] = (L_tmp + 0x8000)>>16; + for (i = 1; i < L; i++) + { + L_tmp = x[i] << 15; + L_tmp += (x[i - 1] * mu)<<1; + x[i] = (L_tmp + 0x8000)>>16; + } + *mem = x[L - 1]; + return; +} + + +void Deemph_32( + Word16 x_hi[], /* (i) : input signal (bit31..16) */ + Word16 x_lo[], /* (i) : input signal (bit15..4) */ + Word16 y[], /* (o) : output signal (x16) */ + Word16 mu, /* (i) Q15 : deemphasis factor */ + Word16 L, /* (i) : vector size */ + Word16 * mem /* (i/o) : memory (y[-1]) */ + ) +{ + Word16 fac; + Word32 i, L_tmp; + + fac = mu >> 1; /* Q15 --> Q14 */ + + L_tmp = L_deposit_h(x_hi[0]); + L_tmp += (x_lo[0] * 8)<<1; + L_tmp = (L_tmp << 3); + L_tmp += ((*mem) * fac)<<1; + L_tmp = (L_tmp << 1); + y[0] = (L_tmp + 0x8000)>>16; + + for (i = 1; i < L; i++) + { + L_tmp = L_deposit_h(x_hi[i]); + L_tmp += (x_lo[i] * 8)<<1; + L_tmp = (L_tmp << 3); + L_tmp += (y[i - 1] * fac)<<1; + L_tmp = (L_tmp << 1); + y[i] = (L_tmp + 0x8000)>>16; + } + + *mem = y[L - 1]; + + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/dtx.c b/media/libstagefright/codecs/amrwbenc/src/dtx.c new file mode 100644 index 0000000000000000000000000000000000000000..02921eb650c884e3bc92503cc93a8a1d8387ab0e --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/dtx.c @@ -0,0 +1,605 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: dtx.c * +* * +* Description:DTX functions * +* * +************************************************************************/ + +#include +#include +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "math_op.h" +#include "cnst.h" +#include "acelp.h" /* prototype of functions */ +#include "bits.h" +#include "dtx.h" +#include "log2.h" +#include "mem_align.h" + +static void aver_isf_history( + Word16 isf_old[], + Word16 indices[], + Word32 isf_aver[] + ); + +static void find_frame_indices( + Word16 isf_old_tx[], + Word16 indices[], + dtx_encState * st + ); + +static Word16 dithering_control( + dtx_encState * st + ); + +/* excitation energy adjustment depending on speech coder mode used, Q7 */ +static Word16 en_adjust[9] = +{ + 230, /* mode0 = 7k : -5.4dB */ + 179, /* mode1 = 9k : -4.2dB */ + 141, /* mode2 = 12k : -3.3dB */ + 128, /* mode3 = 14k : -3.0dB */ + 122, /* mode4 = 16k : -2.85dB */ + 115, /* mode5 = 18k : -2.7dB */ + 115, /* mode6 = 20k : -2.7dB */ + 115, /* mode7 = 23k : -2.7dB */ + 115 /* mode8 = 24k : -2.7dB */ +}; + +/************************************************************************** +* +* Function : dtx_enc_init +* +**************************************************************************/ +Word16 dtx_enc_init(dtx_encState ** st, Word16 isf_init[], VO_MEM_OPERATOR *pMemOP) +{ + dtx_encState *s; + + if (st == (dtx_encState **) NULL) + { + fprintf(stderr, "dtx_enc_init: invalid parameter\n"); + return -1; + } + *st = NULL; + + /* allocate memory */ + if ((s = (dtx_encState *)mem_malloc(pMemOP, sizeof(dtx_encState), 32, VO_INDEX_ENC_AMRWB)) == NULL) + { + fprintf(stderr, "dtx_enc_init: can not malloc state structure\n"); + return -1; + } + dtx_enc_reset(s, isf_init); + *st = s; + return 0; +} + +/************************************************************************** +* +* Function : dtx_enc_reset +* +**************************************************************************/ +Word16 dtx_enc_reset(dtx_encState * st, Word16 isf_init[]) +{ + Word32 i; + + if (st == (dtx_encState *) NULL) + { + fprintf(stderr, "dtx_enc_reset: invalid parameter\n"); + return -1; + } + st->hist_ptr = 0; + st->log_en_index = 0; + + /* Init isf_hist[] */ + for (i = 0; i < DTX_HIST_SIZE; i++) + { + Copy(isf_init, &st->isf_hist[i * M], M); + } + st->cng_seed = RANDOM_INITSEED; + + /* Reset energy history */ + Set_zero(st->log_en_hist, DTX_HIST_SIZE); + + st->dtxHangoverCount = DTX_HANG_CONST; + st->decAnaElapsedCount = 32767; + + for (i = 0; i < 28; i++) + { + st->D[i] = 0; + } + + for (i = 0; i < DTX_HIST_SIZE - 1; i++) + { + st->sumD[i] = 0; + } + + return 1; +} + +/************************************************************************** +* +* Function : dtx_enc_exit +* +**************************************************************************/ +void dtx_enc_exit(dtx_encState ** st, VO_MEM_OPERATOR *pMemOP) +{ + if (st == NULL || *st == NULL) + return; + /* deallocate memory */ + mem_free(pMemOP, *st, VO_INDEX_ENC_AMRWB); + *st = NULL; + return; +} + + +/************************************************************************** +* +* Function : dtx_enc +* +**************************************************************************/ +Word16 dtx_enc( + dtx_encState * st, /* i/o : State struct */ + Word16 isf[M], /* o : CN ISF vector */ + Word16 * exc2, /* o : CN excitation */ + Word16 ** prms + ) +{ + Word32 i, j; + Word16 indice[7]; + Word16 log_en, gain, level, exp, exp0, tmp; + Word16 log_en_int_e, log_en_int_m; + Word32 L_isf[M], ener32, level32; + Word16 isf_order[3]; + Word16 CN_dith; + + /* VOX mode computation of SID parameters */ + log_en = 0; + for (i = 0; i < M; i++) + { + L_isf[i] = 0; + } + /* average energy and isf */ + for (i = 0; i < DTX_HIST_SIZE; i++) + { + /* Division by DTX_HIST_SIZE = 8 has been done in dtx_buffer. log_en is in Q10 */ + log_en = add(log_en, st->log_en_hist[i]); + + } + find_frame_indices(st->isf_hist, isf_order, st); + aver_isf_history(st->isf_hist, isf_order, L_isf); + + for (j = 0; j < M; j++) + { + isf[j] = (Word16)(L_isf[j] >> 3); /* divide by 8 */ + } + + /* quantize logarithmic energy to 6 bits (-6 : 66 dB) which corresponds to -2:22 in log2(E). */ + /* st->log_en_index = (short)( (log_en + 2.0) * 2.625 ); */ + + /* increase dynamics to 7 bits (Q8) */ + log_en = (log_en >> 2); + + /* Add 2 in Q8 = 512 to get log2(E) between 0:24 */ + log_en = add(log_en, 512); + + /* Multiply by 2.625 to get full 6 bit range. 2.625 = 21504 in Q13. The result is in Q6 */ + log_en = mult(log_en, 21504); + + /* Quantize Energy */ + st->log_en_index = shr(log_en, 6); + + if(st->log_en_index > 63) + { + st->log_en_index = 63; + } + if (st->log_en_index < 0) + { + st->log_en_index = 0; + } + /* Quantize ISFs */ + Qisf_ns(isf, isf, indice); + + + Parm_serial(indice[0], 6, prms); + Parm_serial(indice[1], 6, prms); + Parm_serial(indice[2], 6, prms); + Parm_serial(indice[3], 5, prms); + Parm_serial(indice[4], 5, prms); + + Parm_serial((st->log_en_index), 6, prms); + + CN_dith = dithering_control(st); + Parm_serial(CN_dith, 1, prms); + + /* level = (float)( pow( 2.0f, (float)st->log_en_index / 2.625 - 2.0 ) ); */ + /* log2(E) in Q9 (log2(E) lies in between -2:22) */ + log_en = shl(st->log_en_index, 15 - 6); + + /* Divide by 2.625; log_en will be between 0:24 */ + log_en = mult(log_en, 12483); + /* the result corresponds to log2(gain) in Q10 */ + + /* Find integer part */ + log_en_int_e = (log_en >> 10); + + /* Find fractional part */ + log_en_int_m = (Word16) (log_en & 0x3ff); + log_en_int_m = shl(log_en_int_m, 5); + + /* Subtract 2 from log_en in Q9, i.e divide the gain by 2 (energy by 4) */ + /* Add 16 in order to have the result of pow2 in Q16 */ + log_en_int_e = add(log_en_int_e, 16 - 1); + + level32 = Pow2(log_en_int_e, log_en_int_m); /* Q16 */ + exp0 = norm_l(level32); + level32 = (level32 << exp0); /* level in Q31 */ + exp0 = (15 - exp0); + level = extract_h(level32); /* level in Q15 */ + + /* generate white noise vector */ + for (i = 0; i < L_FRAME; i++) + { + exc2[i] = (Random(&(st->cng_seed)) >> 4); + } + + /* gain = level / sqrt(ener) * sqrt(L_FRAME) */ + + /* energy of generated excitation */ + ener32 = Dot_product12(exc2, exc2, L_FRAME, &exp); + + Isqrt_n(&ener32, &exp); + + gain = extract_h(ener32); + + gain = mult(level, gain); /* gain in Q15 */ + + exp = add(exp0, exp); + + /* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */ + exp += 4; + + for (i = 0; i < L_FRAME; i++) + { + tmp = mult(exc2[i], gain); /* Q0 * Q15 */ + exc2[i] = shl(tmp, exp); + } + + return 0; +} + +/************************************************************************** +* +* Function : dtx_buffer Purpose : handles the DTX buffer +* +**************************************************************************/ +Word16 dtx_buffer( + dtx_encState * st, /* i/o : State struct */ + Word16 isf_new[], /* i : isf vector */ + Word32 enr, /* i : residual energy (in L_FRAME) */ + Word16 codec_mode + ) +{ + Word16 log_en; + + Word16 log_en_e; + Word16 log_en_m; + st->hist_ptr = add(st->hist_ptr, 1); + if(st->hist_ptr == DTX_HIST_SIZE) + { + st->hist_ptr = 0; + } + /* copy lsp vector into buffer */ + Copy(isf_new, &st->isf_hist[st->hist_ptr * M], M); + + /* log_en = (float)log10(enr*0.0059322)/(float)log10(2.0f); */ + Log2(enr, &log_en_e, &log_en_m); + + /* convert exponent and mantissa to Word16 Q7. Q7 is used to simplify averaging in dtx_enc */ + log_en = shl(log_en_e, 7); /* Q7 */ + log_en = add(log_en, shr(log_en_m, 15 - 7)); + + /* Find energy per sample by multiplying with 0.0059322, i.e subtract log2(1/0.0059322) = 7.39722 The + * constant 0.0059322 takes into account windowings and analysis length from autocorrelation + * computations; 7.39722 in Q7 = 947 */ + /* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */ + /* log_en = sub( log_en, 947 + en_adjust[codec_mode] ); */ + + /* Find energy per sample (divide by L_FRAME=256), i.e subtract log2(256) = 8.0 (1024 in Q7) */ + /* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */ + + log_en = sub(log_en, add(1024, en_adjust[codec_mode])); + + /* Insert into the buffer */ + st->log_en_hist[st->hist_ptr] = log_en; + return 0; +} + +/************************************************************************** +* +* Function : tx_dtx_handler Purpose : adds extra speech hangover +* to analyze speech on +* the decoding side. +**************************************************************************/ +void tx_dtx_handler(dtx_encState * st, /* i/o : State struct */ + Word16 vad_flag, /* i : vad decision */ + Word16 * usedMode /* i/o : mode changed or not */ + ) +{ + + /* this state machine is in synch with the GSMEFR txDtx machine */ + st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1); + + if (vad_flag != 0) + { + st->dtxHangoverCount = DTX_HANG_CONST; + } else + { /* non-speech */ + if (st->dtxHangoverCount == 0) + { /* out of decoder analysis hangover */ + st->decAnaElapsedCount = 0; + *usedMode = MRDTX; + } else + { /* in possible analysis hangover */ + st->dtxHangoverCount = sub(st->dtxHangoverCount, 1); + + /* decAnaElapsedCount + dtxHangoverCount < DTX_ELAPSED_FRAMES_THRESH */ + if (sub(add(st->decAnaElapsedCount, st->dtxHangoverCount), + DTX_ELAPSED_FRAMES_THRESH) < 0) + { + *usedMode = MRDTX; + /* if short time since decoder update, do not add extra HO */ + } + /* else override VAD and stay in speech mode *usedMode and add extra hangover */ + } + } + + return; +} + + + +static void aver_isf_history( + Word16 isf_old[], + Word16 indices[], + Word32 isf_aver[] + ) +{ + Word32 i, j, k; + Word16 isf_tmp[2 * M]; + Word32 L_tmp; + + /* Memorize in isf_tmp[][] the ISF vectors to be replaced by */ + /* the median ISF vector prior to the averaging */ + for (k = 0; k < 2; k++) + { + if ((indices[k] + 1) != 0) + { + for (i = 0; i < M; i++) + { + isf_tmp[k * M + i] = isf_old[indices[k] * M + i]; + isf_old[indices[k] * M + i] = isf_old[indices[2] * M + i]; + } + } + } + + /* Perform the ISF averaging */ + for (j = 0; j < M; j++) + { + L_tmp = 0; + + for (i = 0; i < DTX_HIST_SIZE; i++) + { + L_tmp = L_add(L_tmp, L_deposit_l(isf_old[i * M + j])); + } + isf_aver[j] = L_tmp; + } + + /* Retrieve from isf_tmp[][] the ISF vectors saved prior to averaging */ + for (k = 0; k < 2; k++) + { + if ((indices[k] + 1) != 0) + { + for (i = 0; i < M; i++) + { + isf_old[indices[k] * M + i] = isf_tmp[k * M + i]; + } + } + } + + return; +} + +static void find_frame_indices( + Word16 isf_old_tx[], + Word16 indices[], + dtx_encState * st + ) +{ + Word32 L_tmp, summin, summax, summax2nd; + Word16 i, j, tmp; + Word16 ptr; + + /* Remove the effect of the oldest frame from the column */ + /* sum sumD[0..DTX_HIST_SIZE-1]. sumD[DTX_HIST_SIZE] is */ + /* not updated since it will be removed later. */ + + tmp = DTX_HIST_SIZE_MIN_ONE; + j = -1; + for (i = 0; i < DTX_HIST_SIZE_MIN_ONE; i++) + { + j = add(j, tmp); + st->sumD[i] = L_sub(st->sumD[i], st->D[j]); + tmp = sub(tmp, 1); + } + + /* Shift the column sum sumD. The element sumD[DTX_HIST_SIZE-1] */ + /* corresponding to the oldest frame is removed. The sum of */ + /* the distances between the latest isf and other isfs, */ + /* i.e. the element sumD[0], will be computed during this call. */ + /* Hence this element is initialized to zero. */ + + for (i = DTX_HIST_SIZE_MIN_ONE; i > 0; i--) + { + st->sumD[i] = st->sumD[i - 1]; + } + st->sumD[0] = 0; + + /* Remove the oldest frame from the distance matrix. */ + /* Note that the distance matrix is replaced by a one- */ + /* dimensional array to save static memory. */ + + tmp = 0; + for (i = 27; i >= 12; i = (Word16) (i - tmp)) + { + tmp = add(tmp, 1); + for (j = tmp; j > 0; j--) + { + st->D[i - j + 1] = st->D[i - j - tmp]; + } + } + + /* Compute the first column of the distance matrix D */ + /* (squared Euclidean distances from isf1[] to isf_old_tx[][]). */ + + ptr = st->hist_ptr; + for (i = 1; i < DTX_HIST_SIZE; i++) + { + /* Compute the distance between the latest isf and the other isfs. */ + ptr = sub(ptr, 1); + if (ptr < 0) + { + ptr = DTX_HIST_SIZE_MIN_ONE; + } + L_tmp = 0; + for (j = 0; j < M; j++) + { + tmp = sub(isf_old_tx[st->hist_ptr * M + j], isf_old_tx[ptr * M + j]); + L_tmp = L_mac(L_tmp, tmp, tmp); + } + st->D[i - 1] = L_tmp; + + /* Update also the column sums. */ + st->sumD[0] = L_add(st->sumD[0], st->D[i - 1]); + st->sumD[i] = L_add(st->sumD[i], st->D[i - 1]); + } + + /* Find the minimum and maximum distances */ + summax = st->sumD[0]; + summin = st->sumD[0]; + indices[0] = 0; + indices[2] = 0; + for (i = 1; i < DTX_HIST_SIZE; i++) + { + if (L_sub(st->sumD[i], summax) > 0) + { + indices[0] = i; + summax = st->sumD[i]; + } + if (L_sub(st->sumD[i], summin) < 0) + { + indices[2] = i; + summin = st->sumD[i]; + } + } + + /* Find the second largest distance */ + summax2nd = -2147483647L; + indices[1] = -1; + for (i = 0; i < DTX_HIST_SIZE; i++) + { + if ((L_sub(st->sumD[i], summax2nd) > 0) && (sub(i, indices[0]) != 0)) + { + indices[1] = i; + summax2nd = st->sumD[i]; + } + } + + for (i = 0; i < 3; i++) + { + indices[i] = sub(st->hist_ptr, indices[i]); + if (indices[i] < 0) + { + indices[i] = add(indices[i], DTX_HIST_SIZE); + } + } + + /* If maximum distance/MED_THRESH is smaller than minimum distance */ + /* then the median ISF vector replacement is not performed */ + tmp = norm_l(summax); + summax = (summax << tmp); + summin = (summin << tmp); + L_tmp = L_mult(voround(summax), INV_MED_THRESH); + if(L_tmp <= summin) + { + indices[0] = -1; + } + /* If second largest distance/MED_THRESH is smaller than */ + /* minimum distance then the median ISF vector replacement is */ + /* not performed */ + summax2nd = L_shl(summax2nd, tmp); + L_tmp = L_mult(voround(summax2nd), INV_MED_THRESH); + if(L_tmp <= summin) + { + indices[1] = -1; + } + return; +} + +static Word16 dithering_control( + dtx_encState * st + ) +{ + Word16 tmp, mean, CN_dith, gain_diff; + Word32 i, ISF_diff; + + /* determine how stationary the spectrum of background noise is */ + ISF_diff = 0; + for (i = 0; i < 8; i++) + { + ISF_diff = L_add(ISF_diff, st->sumD[i]); + } + if ((ISF_diff >> 26) > 0) + { + CN_dith = 1; + } else + { + CN_dith = 0; + } + + /* determine how stationary the energy of background noise is */ + mean = 0; + for (i = 0; i < DTX_HIST_SIZE; i++) + { + mean = add(mean, st->log_en_hist[i]); + } + mean = (mean >> 3); + gain_diff = 0; + for (i = 0; i < DTX_HIST_SIZE; i++) + { + tmp = abs_s(sub(st->log_en_hist[i], mean)); + gain_diff = add(gain_diff, tmp); + } + if (gain_diff > GAIN_THR) + { + CN_dith = 1; + } + return CN_dith; +} diff --git a/media/libstagefright/codecs/amrwbenc/src/g_pitch.c b/media/libstagefright/codecs/amrwbenc/src/g_pitch.c new file mode 100644 index 0000000000000000000000000000000000000000..570138e35f4a463f014a52a09b850d53c420ea99 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/g_pitch.c @@ -0,0 +1,79 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: g_pitch.c * +* * +* Description:Compute the gain of pitch. Result in Q12 * +* if(gain < 0) gain = 0 * +* if(gain > 1.2) gain = 1.2 * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "math_op.h" + +Word16 G_pitch( /* (o) Q14 : Gain of pitch lag saturated to 1.2 */ + Word16 xn[], /* (i) : Pitch target. */ + Word16 y1[], /* (i) : filtered adaptive codebook. */ + Word16 g_coeff[], /* : Correlations need for gain quantization. */ + Word16 L_subfr /* : Length of subframe. */ + ) +{ + Word32 i; + Word16 xy, yy, exp_xy, exp_yy, gain; + /* Compute scalar product */ +#ifdef ASM_OPT /* asm optimization branch */ + /* Compute scalar product */ + xy = extract_h(Dot_product12_asm(xn, y1, L_subfr, &exp_xy)); + yy = extract_h(Dot_product12_asm(y1, y1, L_subfr, &exp_yy)); + +#else + /* Compute scalar product */ + xy = extract_h(Dot_product12(xn, y1, L_subfr, &exp_xy)); + yy = extract_h(Dot_product12(y1, y1, L_subfr, &exp_yy)); + +#endif + + g_coeff[0] = yy; + g_coeff[1] = exp_yy; + g_coeff[2] = xy; + g_coeff[3] = exp_xy; + + /* If (xy < 0) gain = 0 */ + if (xy < 0) + return ((Word16) 0); + + /* compute gain = xy/yy */ + + xy >>= 1; /* Be sure xy < yy */ + gain = div_s(xy, yy); + + i = exp_xy; + i -= exp_yy; + + gain = shl(gain, i); + + /* if (gain > 1.2) gain = 1.2 in Q14 */ + if(gain > 19661) + { + gain = 19661; + } + return (gain); +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/gpclip.c b/media/libstagefright/codecs/amrwbenc/src/gpclip.c new file mode 100644 index 0000000000000000000000000000000000000000..e23f2f428884a7a2ee59b9b2bb5fcb548b650193 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/gpclip.c @@ -0,0 +1,110 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/************************************************************************** +* File: gpclip.c * +* * +* Description:To avoid unstable synthesis on frame erasure, the gain * +* need to be limited(gain pitch < 1.0) when the following * +* case occurs * +* a resonance on LPC filter(lp_disp < 60Hz) * +* a good pitch prediction (lp_gp > 0.95) * +* * +***************************************************************************/ +#include "typedef.h" +#include "basic_op.h" + +#define DIST_ISF_MAX 307 /* 120 Hz (6400Hz=16384) */ +#define DIST_ISF_THRES 154 /* 60 (6400Hz=16384) */ +#define GAIN_PIT_THRES 14746 /* 0.9 in Q14 */ +#define GAIN_PIT_MIN 9830 /* 0.6 in Q14 */ +#define M 16 + + +void Init_gp_clip( + Word16 mem[] /* (o) : memory of gain of pitch clipping algorithm */ + ) +{ + mem[0] = DIST_ISF_MAX; + mem[1] = GAIN_PIT_MIN; +} + + +Word16 Gp_clip( + Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */ + ) +{ + Word16 clip = 0; + if ((mem[0] < DIST_ISF_THRES) && (mem[1] > GAIN_PIT_THRES)) + clip = 1; + + return (clip); +} + + +void Gp_clip_test_isf( + Word16 isf[], /* (i) : isf values (in frequency domain) */ + Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */ + ) +{ + Word16 dist, dist_min; + Word32 i; + + dist_min = vo_sub(isf[1], isf[0]); + + for (i = 2; i < M - 1; i++) + { + dist = vo_sub(isf[i], isf[i - 1]); + if(dist < dist_min) + { + dist_min = dist; + } + } + + dist = extract_h(L_mac(vo_L_mult(26214, mem[0]), 6554, dist_min)); + + if (dist > DIST_ISF_MAX) + { + dist = DIST_ISF_MAX; + } + mem[0] = dist; + + return; +} + + +void Gp_clip_test_gain_pit( + Word16 gain_pit, /* (i) Q14 : gain of quantized pitch */ + Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */ + ) +{ + Word16 gain; + Word32 L_tmp; + L_tmp = (29491 * mem[1])<<1; + L_tmp += (3277 * gain_pit)<<1; + + gain = extract_h(L_tmp); + + if(gain < GAIN_PIT_MIN) + { + gain = GAIN_PIT_MIN; + } + mem[1] = gain; + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/homing.c b/media/libstagefright/codecs/amrwbenc/src/homing.c new file mode 100644 index 0000000000000000000000000000000000000000..015633f51b3090f2d827fd8124a81002132dd026 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/homing.c @@ -0,0 +1,46 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: homing.c * +* * +* Description:Performs the homing routines * +* * +************************************************************************/ + +#include "typedef.h" +#include "cnst.h" +#include "basic_op.h" +#include "bits.h" +#include "homing.tab" + +Word16 encoder_homing_frame_test(Word16 input_frame[]) +{ + Word32 i; + Word16 j = 0; + + /* check 320 input samples for matching EHF_MASK: defined in e_homing.h */ + for (i = 0; i < L_FRAME16k; i++) + { + j = (Word16) (input_frame[i] ^ EHF_MASK); + + if (j) + break; + } + + return (Word16) (!j); +} + diff --git a/media/libstagefright/codecs/amrwbenc/src/hp400.c b/media/libstagefright/codecs/amrwbenc/src/hp400.c new file mode 100644 index 0000000000000000000000000000000000000000..463a53ae76d7f34a265b334c0c19e8cfcbb27794 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/hp400.c @@ -0,0 +1,106 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: hp400.c * +* * +* Description: * +* 2nd order high pass filter with cut off frequency at 400 Hz. * +* Designed with cheby2 function in MATLAB. * +* Optimized for fixed-point to get the following frequency response: * +* * +* frequency: 0Hz 100Hz 200Hz 300Hz 400Hz 630Hz 1.5kHz 3kHz * +* dB loss: -infdB -30dB -20dB -10dB -3dB +6dB +1dB 0dB * +* * +* Algorithm: * +* * +* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] * +* + a[1]*y[i-1] + a[2]*y[i-2]; * +* * +* Word16 b[3] = {3660, -7320, 3660}; in Q12 * +* Word16 a[3] = {4096, 7320, -3540}; in Q12 * +* * +* float --> b[3] = {0.893554687, -1.787109375, 0.893554687}; * +* a[3] = {1.000000000, 1.787109375, -0.864257812}; * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "acelp.h" + +/* filter coefficients */ +static Word16 b[3] = {915, -1830, 915}; /* Q12 (/4) */ +static Word16 a[3] = {16384, 29280, -14160}; /* Q12 (x4) */ +/* Initialization of static values */ + +void Init_HP400_12k8(Word16 mem[]) +{ + Set_zero(mem, 6); +} + + +void HP400_12k8( + Word16 signal[], /* input signal / output is divided by 16 */ + Word16 lg, /* lenght of signal */ + Word16 mem[] /* filter memory [6] */ + ) +{ + Word16 x2; + Word16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1; + Word32 L_tmp; + Word32 num; + y2_hi = *mem++; + y2_lo = *mem++; + y1_hi = *mem++; + y1_lo = *mem++; + x0 = *mem++; + x1 = *mem; + num = (Word32)lg; + do + { + x2 = x1; + x1 = x0; + x0 = *signal; + /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2] */ + /* + a[1]*y[i-1] + a[2] * y[i-2]; */ + L_tmp = 8192L; /* rounding to maximise precision */ + L_tmp += y1_lo * a[1]; + L_tmp += y2_lo * a[2]; + L_tmp = L_tmp >> 14; + L_tmp += (y1_hi * a[1] + y2_hi * a[2] + (x0 + x2)* b[0] + x1 * b[1]) << 1; + L_tmp <<= 1; /* coeff Q12 --> Q13 */ + y2_hi = y1_hi; + y2_lo = y1_lo; + y1_hi = (Word16)(L_tmp>>16); + y1_lo = (Word16)((L_tmp & 0xffff)>>1); + + /* signal is divided by 16 to avoid overflow in energy computation */ + *signal++ = (L_tmp + 0x8000) >> 16; + }while(--num !=0); + + *mem-- = x1; + *mem-- = x0; + *mem-- = y1_lo; + *mem-- = y1_hi; + *mem-- = y2_lo; + *mem = y2_hi; + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/hp50.c b/media/libstagefright/codecs/amrwbenc/src/hp50.c new file mode 100644 index 0000000000000000000000000000000000000000..53e3d7be4304bedc1b1bebdb88ce753caab2cc12 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/hp50.c @@ -0,0 +1,106 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: hp50.c * +* * +* Description: * +* 2nd order high pass filter with cut off frequency at 31 Hz. * +* Designed with cheby2 function in MATLAB. * +* Optimized for fixed-point to get the following frequency response: * +* * +* frequency: 0Hz 14Hz 24Hz 31Hz 37Hz 41Hz 47Hz * +* dB loss: -infdB -15dB -6dB -3dB -1.5dB -1dB -0.5dB * +* * +* Algorithm: * +* * +* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] * +* + a[1]*y[i-1] + a[2]*y[i-2]; * +* * +* Word16 b[3] = {4053, -8106, 4053}; in Q12 * +* Word16 a[3] = {8192, 16211, -8021}; in Q12 * +* * +* float --> b[3] = {0.989501953, -1.979003906, 0.989501953}; * +* a[3] = {1.000000000, 1.978881836, -0.979125977}; * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "cnst.h" +#include "acelp.h" + +/* filter coefficients */ +static Word16 b[3] = {4053, -8106, 4053}; /* Q12 */ +static Word16 a[3] = {8192, 16211, -8021}; /* Q12 (x2) */ + +/* Initialization of static values */ + +void Init_HP50_12k8(Word16 mem[]) +{ + Set_zero(mem, 6); +} + + +void HP50_12k8( + Word16 signal[], /* input/output signal */ + Word16 lg, /* lenght of signal */ + Word16 mem[] /* filter memory [6] */ + ) +{ + Word16 x2; + Word16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1; + Word32 L_tmp; + Word32 num; + + y2_hi = *mem++; + y2_lo = *mem++; + y1_hi = *mem++; + y1_lo = *mem++; + x0 = *mem++; + x1 = *mem; + num = (Word32)lg; + do + { + x2 = x1; + x1 = x0; + x0 = *signal; + /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2] */ + /* + a[1]*y[i-1] + a[2] * y[i-2]; */ + L_tmp = 8192 ; /* rounding to maximise precision */ + L_tmp += y1_lo * a[1]; + L_tmp += y2_lo * a[2]; + L_tmp = L_tmp >> 14; + L_tmp += (y1_hi * a[1] + y2_hi * a[2] + (x0 + x2) * b[0] + x1 * b[1]) << 1; + L_tmp <<= 2; /* coeff Q12 --> Q13 */ + y2_hi = y1_hi; + y2_lo = y1_lo; + y1_hi = (Word16)(L_tmp>>16); + y1_lo = (Word16)((L_tmp & 0xffff)>>1); + *signal++ = extract_h((L_add((L_tmp<<1), 0x8000))); + }while(--num !=0); + + *mem-- = x1; + *mem-- = x0; + *mem-- = y1_lo; + *mem-- = y1_hi; + *mem-- = y2_lo; + *mem-- = y2_hi; + + return; +} + + diff --git a/media/libstagefright/codecs/amrwbenc/src/hp6k.c b/media/libstagefright/codecs/amrwbenc/src/hp6k.c new file mode 100644 index 0000000000000000000000000000000000000000..5ee5b20d7ba4d5ac3e2544862c44834f7dd2d66e --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/hp6k.c @@ -0,0 +1,93 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: hp6k.c * +* * +* Description:15th order band pass 6kHz to 7kHz FIR filter * +* frequency: 4kHz 5kHz 5.5kHz 6kHz 6.5kHz 7kHz 7.5kHz 8kHz * +* dB loss: -60dB -45dB -13dB -3dB 0dB -3dB -13dB -45dB * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "acelp.h" +#include "cnst.h" + +#define L_FIR 31 + +/* filter coefficients (gain=4.0) */ + +Word16 fir_6k_7k[L_FIR] = +{ + -32, 47, 32, -27, -369, + 1122, -1421, 0, 3798, -8880, + 12349, -10984, 3548, 7766, -18001, + 22118, -18001, 7766, 3548, -10984, + 12349, -8880, 3798, 0, -1421, + 1122, -369, -27, 32, 47, + -32 +}; + + +void Init_Filt_6k_7k(Word16 mem[]) /* mem[30] */ +{ + Set_zero(mem, L_FIR - 1); + return; +} + +void Filt_6k_7k( + Word16 signal[], /* input: signal */ + Word16 lg, /* input: length of input */ + Word16 mem[] /* in/out: memory (size=30) */ + ) +{ + Word16 x[L_SUBFR16k + (L_FIR - 1)]; + Word32 i, L_tmp; + + Copy(mem, x, L_FIR - 1); + for (i = lg - 1; i >= 0; i--) + { + x[i + L_FIR - 1] = signal[i] >> 2; /* gain of filter = 4 */ + } + for (i = 0; i < lg; i++) + { + L_tmp = (x[i] + x[i+ 30]) * fir_6k_7k[0]; + L_tmp += (x[i+1] + x[i + 29]) * fir_6k_7k[1]; + L_tmp += (x[i+2] + x[i + 28]) * fir_6k_7k[2]; + L_tmp += (x[i+3] + x[i + 27]) * fir_6k_7k[3]; + L_tmp += (x[i+4] + x[i + 26]) * fir_6k_7k[4]; + L_tmp += (x[i+5] + x[i + 25]) * fir_6k_7k[5]; + L_tmp += (x[i+6] + x[i + 24]) * fir_6k_7k[6]; + L_tmp += (x[i+7] + x[i + 23]) * fir_6k_7k[7]; + L_tmp += (x[i+8] + x[i + 22]) * fir_6k_7k[8]; + L_tmp += (x[i+9] + x[i + 21]) * fir_6k_7k[9]; + L_tmp += (x[i+10] + x[i + 20]) * fir_6k_7k[10]; + L_tmp += (x[i+11] + x[i + 19]) * fir_6k_7k[11]; + L_tmp += (x[i+12] + x[i + 18]) * fir_6k_7k[12]; + L_tmp += (x[i+13] + x[i + 17]) * fir_6k_7k[13]; + L_tmp += (x[i+14] + x[i + 16]) * fir_6k_7k[14]; + L_tmp += (x[i+15]) * fir_6k_7k[15]; + signal[i] = (L_tmp + 0x4000) >> 15; + } + + Copy(x + lg, mem, L_FIR - 1); + +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/hp_wsp.c b/media/libstagefright/codecs/amrwbenc/src/hp_wsp.c new file mode 100644 index 0000000000000000000000000000000000000000..7fb62a4f141e4b747961ef71652c67a10e944e14 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/hp_wsp.c @@ -0,0 +1,148 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: hp_wsp.c * +* Description: * +* 3nd order high pass filter with cut off frequency at 180Hz * +* Algorithm: * +* * +* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] + b[3]*x[i-3] * +* + a[1]*y[i-1] + a[2]*y[i-2] + a[3]*y[i-3]; * +* * +* float a_coef[HP_ORDER]= { * +* -2.64436711600664f, * +* 2.35087386625360f, * +* -0.70001156927424f}; * +* * +* float b_coef[HP_ORDER+1]= { * +* -0.83787057505665f, * +* 2.50975570071058f, * +* -2.50975570071058f, * +* 0.83787057505665f}; * +* * +*************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "acelp.h" + +/* filter coefficients in Q12 */ +static Word16 a[4] = {8192, 21663, -19258, 5734}; +static Word16 b[4] = {-3432, +10280, -10280, +3432}; + +/* Initialization of static values */ +void Init_Hp_wsp(Word16 mem[]) +{ + Set_zero(mem, 9); + + return; +} + +void scale_mem_Hp_wsp(Word16 mem[], Word16 exp) +{ + Word32 i; + Word32 L_tmp; + + for (i = 0; i < 6; i += 2) + { + L_tmp = ((mem[i] << 16) + (mem[i + 1]<<1)); + L_tmp = L_shl(L_tmp, exp); + mem[i] = L_tmp >> 16; + mem[i + 1] = (L_tmp & 0xffff)>>1; + } + + for (i = 6; i < 9; i++) + { + L_tmp = L_deposit_h(mem[i]); /* x[i] */ + L_tmp = L_shl(L_tmp, exp); + mem[i] = vo_round(L_tmp); + } + + return; +} + + +void Hp_wsp( + Word16 wsp[], /* i : wsp[] signal */ + Word16 hp_wsp[], /* o : hypass wsp[] */ + Word16 lg, /* i : lenght of signal */ + Word16 mem[] /* i/o : filter memory [9] */ + ) +{ + Word16 x0, x1, x2, x3; + Word16 y3_hi, y3_lo, y2_hi, y2_lo, y1_hi, y1_lo; + Word32 i, L_tmp; + + y3_hi = mem[0]; + y3_lo = mem[1]; + y2_hi = mem[2]; + y2_lo = mem[3]; + y1_hi = mem[4]; + y1_lo = mem[5]; + x0 = mem[6]; + x1 = mem[7]; + x2 = mem[8]; + + for (i = 0; i < lg; i++) + { + x3 = x2; + x2 = x1; + x1 = x0; + x0 = wsp[i]; + /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2] + b[3]*x[i-3] */ + /* + a[1]*y[i-1] + a[2] * y[i-2] + a[3]*y[i-3] */ + + L_tmp = 16384L; /* rounding to maximise precision */ + L_tmp += (y1_lo * a[1])<<1; + L_tmp += (y2_lo * a[2])<<1; + L_tmp += (y3_lo * a[3])<<1; + L_tmp = L_tmp >> 15; + L_tmp += (y1_hi * a[1])<<1; + L_tmp += (y2_hi * a[2])<<1; + L_tmp += (y3_hi * a[3])<<1; + L_tmp += (x0 * b[0])<<1; + L_tmp += (x1 * b[1])<<1; + L_tmp += (x2 * b[2])<<1; + L_tmp += (x3 * b[3])<<1; + + L_tmp = L_tmp << 2; + + y3_hi = y2_hi; + y3_lo = y2_lo; + y2_hi = y1_hi; + y2_lo = y1_lo; + y1_hi = L_tmp >> 16; + y1_lo = (L_tmp & 0xffff) >>1; + + hp_wsp[i] = (L_tmp + 0x4000)>>15; + } + + mem[0] = y3_hi; + mem[1] = y3_lo; + mem[2] = y2_hi; + mem[3] = y2_lo; + mem[4] = y1_hi; + mem[5] = y1_lo; + mem[6] = x0; + mem[7] = x1; + mem[8] = x2; + + return; +} + + diff --git a/media/libstagefright/codecs/amrwbenc/src/int_lpc.c b/media/libstagefright/codecs/amrwbenc/src/int_lpc.c new file mode 100644 index 0000000000000000000000000000000000000000..be1fd0b238735209d6e02c5a0c331bcf78269199 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/int_lpc.c @@ -0,0 +1,66 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: int_lpc.c * +* * +* Description:Interpolation of the LP parameters in 4 subframes. * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "cnst.h" +#include "acelp.h" + +#define MP1 (M+1) + + +void Int_isp( + Word16 isp_old[], /* input : isps from past frame */ + Word16 isp_new[], /* input : isps from present frame */ + Word16 frac[], /* input : fraction for 3 first subfr (Q15) */ + Word16 Az[] /* output: LP coefficients in 4 subframes */ + ) +{ + Word32 i, k; + Word16 fac_old, fac_new; + Word16 isp[M]; + Word32 L_tmp; + + for (k = 0; k < 3; k++) + { + fac_new = frac[k]; + fac_old = (32767 - fac_new) + 1; /* 1.0 - fac_new */ + + for (i = 0; i < M; i++) + { + L_tmp = (isp_old[i] * fac_old)<<1; + L_tmp += (isp_new[i] * fac_new)<<1; + isp[i] = (L_tmp + 0x8000)>>16; + } + Isp_Az(isp, Az, M, 0); + Az += MP1; + } + + /* 4th subframe: isp_new (frac=1.0) */ + Isp_Az(isp_new, Az, M, 0); + + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/isp_az.c b/media/libstagefright/codecs/amrwbenc/src/isp_az.c new file mode 100644 index 0000000000000000000000000000000000000000..7b44d12f9a57c302b44c5bc953848a586083bd87 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/isp_az.c @@ -0,0 +1,247 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: isp_az.c * +* * +* Description:Compute the LPC coefficients from isp (order=M) * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "cnst.h" + +#define NC (M/2) +#define NC16k (M16k/2) + +/* local function */ + +static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n); +static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n); + +void Isp_Az( + Word16 isp[], /* (i) Q15 : Immittance spectral pairs */ + Word16 a[], /* (o) Q12 : predictor coefficients (order = M) */ + Word16 m, + Word16 adaptive_scaling /* (i) 0 : adaptive scaling disabled */ + /* 1 : adaptive scaling enabled */ + ) +{ + Word32 i, j; + Word16 hi, lo; + Word32 f1[NC16k + 1], f2[NC16k]; + Word16 nc; + Word32 t0; + Word16 q, q_sug; + Word32 tmax; + + nc = (m >> 1); + if(nc > 8) + { + Get_isp_pol_16kHz(&isp[0], f1, nc); + for (i = 0; i <= nc; i++) + { + f1[i] = f1[i] << 2; + } + } else + Get_isp_pol(&isp[0], f1, nc); + + if (nc > 8) + { + Get_isp_pol_16kHz(&isp[1], f2, (nc - 1)); + for (i = 0; i <= nc - 1; i++) + { + f2[i] = f2[i] << 2; + } + } else + Get_isp_pol(&isp[1], f2, (nc - 1)); + + /*-----------------------------------------------------* + * Multiply F2(z) by (1 - z^-2) * + *-----------------------------------------------------*/ + + for (i = (nc - 1); i > 1; i--) + { + f2[i] = vo_L_sub(f2[i], f2[i - 2]); /* f2[i] -= f2[i-2]; */ + } + + /*----------------------------------------------------------* + * Scale F1(z) by (1+isp[m-1]) and F2(z) by (1-isp[m-1]) * + *----------------------------------------------------------*/ + + for (i = 0; i < nc; i++) + { + /* f1[i] *= (1.0 + isp[M-1]); */ + + hi = f1[i] >> 16; + lo = (f1[i] & 0xffff)>>1; + + t0 = Mpy_32_16(hi, lo, isp[m - 1]); + f1[i] = vo_L_add(f1[i], t0); + + /* f2[i] *= (1.0 - isp[M-1]); */ + + hi = f2[i] >> 16; + lo = (f2[i] & 0xffff)>>1; + t0 = Mpy_32_16(hi, lo, isp[m - 1]); + f2[i] = vo_L_sub(f2[i], t0); + } + + /*-----------------------------------------------------* + * A(z) = (F1(z)+F2(z))/2 * + * F1(z) is symmetric and F2(z) is antisymmetric * + *-----------------------------------------------------*/ + + /* a[0] = 1.0; */ + a[0] = 4096; + tmax = 1; + for (i = 1, j = m - 1; i < nc; i++, j--) + { + /* a[i] = 0.5*(f1[i] + f2[i]); */ + + t0 = vo_L_add(f1[i], f2[i]); /* f1[i] + f2[i] */ + tmax |= L_abs(t0); + a[i] = (Word16)(vo_L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */ + + /* a[j] = 0.5*(f1[i] - f2[i]); */ + + t0 = vo_L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */ + tmax |= L_abs(t0); + a[j] = (Word16)(vo_L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */ + } + + /* rescale data if overflow has occured and reprocess the loop */ + if(adaptive_scaling == 1) + q = 4 - norm_l(tmax); /* adaptive scaling enabled */ + else + q = 0; /* adaptive scaling disabled */ + + if (q > 0) + { + q_sug = (12 + q); + for (i = 1, j = m - 1; i < nc; i++, j--) + { + /* a[i] = 0.5*(f1[i] + f2[i]); */ + t0 = vo_L_add(f1[i], f2[i]); /* f1[i] + f2[i] */ + a[i] = (Word16)(vo_L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ + + /* a[j] = 0.5*(f1[i] - f2[i]); */ + t0 = vo_L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */ + a[j] = (Word16)(vo_L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ + } + a[0] = shr(a[0], q); + } + else + { + q_sug = 12; + q = 0; + } + /* a[NC] = 0.5*f1[NC]*(1.0 + isp[M-1]); */ + hi = f1[nc] >> 16; + lo = (f1[nc] & 0xffff)>>1; + t0 = Mpy_32_16(hi, lo, isp[m - 1]); + t0 = vo_L_add(f1[nc], t0); + a[nc] = (Word16)(L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ + /* a[m] = isp[m-1]; */ + + a[m] = vo_shr_r(isp[m - 1], (3 + q)); /* from Q15 to Q12 */ + return; +} + +/*-----------------------------------------------------------* +* procedure Get_isp_pol: * +* ~~~~~~~~~~~ * +* Find the polynomial F1(z) or F2(z) from the ISPs. * +* This is performed by expanding the product polynomials: * +* * +* F1(z) = product ( 1 - 2 isp_i z^-1 + z^-2 ) * +* i=0,2,4,6,8 * +* F2(z) = product ( 1 - 2 isp_i z^-1 + z^-2 ) * +* i=1,3,5,7 * +* * +* where isp_i are the ISPs in the cosine domain. * +*-----------------------------------------------------------* +* * +* Parameters: * +* isp[] : isp vector (cosine domaine) in Q15 * +* f[] : the coefficients of F1 or F2 in Q23 * +* n : == NC for F1(z); == NC-1 for F2(z) * +*-----------------------------------------------------------*/ + +static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n) +{ + Word16 hi, lo; + Word32 i, j, t0; + /* All computation in Q23 */ + + f[0] = vo_L_mult(4096, 1024); /* f[0] = 1.0; in Q23 */ + f[1] = vo_L_mult(isp[0], -256); /* f[1] = -2.0*isp[0] in Q23 */ + + f += 2; /* Advance f pointer */ + isp += 2; /* Advance isp pointer */ + for (i = 2; i <= n; i++) + { + *f = f[-2]; + for (j = 1; j < i; j++, f--) + { + hi = f[-1]>>16; + lo = (f[-1] & 0xffff)>>1; + + t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */ + t0 = t0 << 1; + *f = vo_L_sub(*f, t0); /* *f -= t0 */ + *f = vo_L_add(*f, f[-2]); /* *f += f[-2] */ + } + *f -= (*isp << 9); /* *f -= isp<<8 */ + f += i; /* Advance f pointer */ + isp += 2; /* Advance isp pointer */ + } + return; +} + +static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n) +{ + Word16 hi, lo; + Word32 i, j, t0; + + /* All computation in Q23 */ + f[0] = L_mult(4096, 256); /* f[0] = 1.0; in Q23 */ + f[1] = L_mult(isp[0], -64); /* f[1] = -2.0*isp[0] in Q23 */ + + f += 2; /* Advance f pointer */ + isp += 2; /* Advance isp pointer */ + + for (i = 2; i <= n; i++) + { + *f = f[-2]; + for (j = 1; j < i; j++, f--) + { + VO_L_Extract(f[-1], &hi, &lo); + t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */ + t0 = L_shl2(t0, 1); + *f = L_sub(*f, t0); /* *f -= t0 */ + *f = L_add(*f, f[-2]); /* *f += f[-2] */ + } + *f = L_msu(*f, *isp, 64); /* *f -= isp<<8 */ + f += i; /* Advance f pointer */ + isp += 2; /* Advance isp pointer */ + } + return; +} + + diff --git a/media/libstagefright/codecs/amrwbenc/src/isp_isf.c b/media/libstagefright/codecs/amrwbenc/src/isp_isf.c new file mode 100644 index 0000000000000000000000000000000000000000..6c6e389f808cd092a5322f5851e4d0948f2996eb --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/isp_isf.c @@ -0,0 +1,91 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: isp_isf.c * +* * +* Description: * +* Isp_isf Transformation isp to isf * +* Isf_isp Transformation isf to isp * +* * +* The transformation from isp[i] to isf[i] and isf[i] to isp[i] * +* are approximated by a look-up table and interpolation * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "isp_isf.tab" /* Look-up table for transformations */ + +void Isp_isf( + Word16 isp[], /* (i) Q15 : isp[m] (range: -1<=val<1) */ + Word16 isf[], /* (o) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */ + Word16 m /* (i) : LPC order */ + ) +{ + Word32 i, ind; + Word32 L_tmp; + ind = 127; /* beging at end of table -1 */ + for (i = (m - 1); i >= 0; i--) + { + if (i >= (m - 2)) + { /* m-2 is a constant */ + ind = 127; /* beging at end of table -1 */ + } + /* find value in table that is just greater than isp[i] */ + while (table[ind] < isp[i]) + ind--; + /* acos(isp[i])= ind*128 + ( ( isp[i]-table[ind] ) * slope[ind] )/2048 */ + L_tmp = vo_L_mult(vo_sub(isp[i], table[ind]), slope[ind]); + isf[i] = vo_round((L_tmp << 4)); /* (isp[i]-table[ind])*slope[ind])>>11 */ + isf[i] = add1(isf[i], (ind << 7)); + } + isf[m - 1] = (isf[m - 1] >> 1); + return; +} + + +void Isf_isp( + Word16 isf[], /* (i) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */ + Word16 isp[], /* (o) Q15 : isp[m] (range: -1<=val<1) */ + Word16 m /* (i) : LPC order */ + ) +{ + Word16 offset; + Word32 i, ind, L_tmp; + + for (i = 0; i < m - 1; i++) + { + isp[i] = isf[i]; + } + isp[m - 1] = (isf[m - 1] << 1); + + for (i = 0; i < m; i++) + { + ind = (isp[i] >> 7); /* ind = b7-b15 of isf[i] */ + offset = (Word16) (isp[i] & 0x007f); /* offset = b0-b6 of isf[i] */ + + /* isp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 128 */ + L_tmp = vo_L_mult(vo_sub(table[ind + 1], table[ind]), offset); + isp[i] = add1(table[ind], (Word16)((L_tmp >> 8))); + } + + return; +} + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/lag_wind.c b/media/libstagefright/codecs/amrwbenc/src/lag_wind.c new file mode 100644 index 0000000000000000000000000000000000000000..0397704b55c1cf92e56b352f8f3675fd8d635535 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/lag_wind.c @@ -0,0 +1,49 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: lag_wind.c * +* * +* Description: Lag_windows on autocorrelations * +* r[i] *= lag_wind[i] * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "lag_wind.tab" + + +void Lag_window( + Word16 r_h[], /* (i/o) : Autocorrelations (msb) */ + Word16 r_l[] /* (i/o) : Autocorrelations (lsb) */ + ) +{ + Word32 i; + Word32 x; + + for (i = 1; i <= M; i++) + { + x = Mpy_32(r_h[i], r_l[i], volag_h[i - 1], volag_l[i - 1]); + r_h[i] = x >> 16; + r_l[i] = (x & 0xffff)>>1; + } + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/levinson.c b/media/libstagefright/codecs/amrwbenc/src/levinson.c new file mode 100644 index 0000000000000000000000000000000000000000..8bc6f629b1a51e0c9a6dbbb9fb40a8a42d900058 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/levinson.c @@ -0,0 +1,250 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: levinson.c * +* * +* Description:LEVINSON-DURBIN algorithm in double precision * +* * +************************************************************************/ +/*---------------------------------------------------------------------------* + * LEVINSON.C * + *---------------------------------------------------------------------------* + * * + * LEVINSON-DURBIN algorithm in double precision * + * * + * * + * Algorithm * + * * + * R[i] autocorrelations. * + * A[i] filter coefficients. * + * K reflection coefficients. * + * Alpha prediction gain. * + * * + * Initialization: * + * A[0] = 1 * + * K = -R[1]/R[0] * + * A[1] = K * + * Alpha = R[0] * (1-K**2] * + * * + * Do for i = 2 to M * + * * + * S = SUM ( R[j]*A[i-j] ,j=1,i-1 ) + R[i] * + * * + * K = -S / Alpha * + * * + * An[j] = A[j] + K*A[i-j] for j=1 to i-1 * + * where An[i] = new A[i] * + * An[i]=K * + * * + * Alpha=Alpha * (1-K**2) * + * * + * END * + * * + * Remarks on the dynamics of the calculations. * + * * + * The numbers used are in double precision in the following format : * + * A = AH <<16 + AL<<1. AH and AL are 16 bit signed integers. * + * Since the LSB's also contain a sign bit, this format does not * + * correspond to standard 32 bit integers. We use this format since * + * it allows fast execution of multiplications and divisions. * + * * + * "DPF" will refer to this special format in the following text. * + * See oper_32b.c * + * * + * The R[i] were normalized in routine AUTO (hence, R[i] < 1.0). * + * The K[i] and Alpha are theoretically < 1.0. * + * The A[i], for a sampling frequency of 8 kHz, are in practice * + * always inferior to 16.0. * + * * + * These characteristics allow straigthforward fixed-point * + * implementation. We choose to represent the parameters as * + * follows : * + * * + * R[i] Q31 +- .99.. * + * K[i] Q31 +- .99.. * + * Alpha Normalized -> mantissa in Q31 plus exponent * + * A[i] Q27 +- 15.999.. * + * * + * The additions are performed in 32 bit. For the summation used * + * to calculate the K[i], we multiply numbers in Q31 by numbers * + * in Q27, with the result of the multiplications in Q27, * + * resulting in a dynamic of +- 16. This is sufficient to avoid * + * overflow, since the final result of the summation is * + * necessarily < 1.0 as both the K[i] and Alpha are * + * theoretically < 1.0. * + *___________________________________________________________________________*/ +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "acelp.h" + +#define M 16 +#define NC (M/2) + +void Init_Levinson( + Word16 * mem /* output :static memory (18 words) */ + ) +{ + Set_zero(mem, 18); /* old_A[0..M-1] = 0, old_rc[0..1] = 0 */ + return; +} + + +void Levinson( + Word16 Rh[], /* (i) : Rh[M+1] Vector of autocorrelations (msb) */ + Word16 Rl[], /* (i) : Rl[M+1] Vector of autocorrelations (lsb) */ + Word16 A[], /* (o) Q12 : A[M] LPC coefficients (m = 16) */ + Word16 rc[], /* (o) Q15 : rc[M] Reflection coefficients. */ + Word16 * mem /* (i/o) :static memory (18 words) */ + ) +{ + Word32 i, j; + Word16 hi, lo; + Word16 Kh, Kl; /* reflection coefficient; hi and lo */ + Word16 alp_h, alp_l, alp_exp; /* Prediction gain; hi lo and exponent */ + Word16 Ah[M + 1], Al[M + 1]; /* LPC coef. in double prec. */ + Word16 Anh[M + 1], Anl[M + 1]; /* LPC coef.for next iteration in double prec. */ + Word32 t0, t1, t2; /* temporary variable */ + Word16 *old_A, *old_rc; + + /* Last A(z) for case of unstable filter */ + old_A = mem; + old_rc = mem + M; + + /* K = A[1] = -R[1] / R[0] */ + + t1 = ((Rh[1] << 16) + (Rl[1] << 1)); /* R[1] in Q31 */ + t2 = L_abs(t1); /* abs R[1] */ + t0 = Div_32(t2, Rh[0], Rl[0]); /* R[1]/R[0] in Q31 */ + if (t1 > 0) + t0 = -t0; /* -R[1]/R[0] */ + + Kh = t0 >> 16; + Kl = (t0 & 0xffff)>>1; + rc[0] = Kh; + t0 = (t0 >> 4); /* A[1] in Q27 */ + + Ah[1] = t0 >> 16; + Al[1] = (t0 & 0xffff)>>1; + + /* Alpha = R[0] * (1-K**2) */ + t0 = Mpy_32(Kh, Kl, Kh, Kl); /* K*K in Q31 */ + t0 = L_abs(t0); /* Some case <0 !! */ + t0 = vo_L_sub((Word32) 0x7fffffffL, t0); /* 1 - K*K in Q31 */ + + hi = t0 >> 16; + lo = (t0 & 0xffff)>>1; + + t0 = Mpy_32(Rh[0], Rl[0], hi, lo); /* Alpha in Q31 */ + + /* Normalize Alpha */ + alp_exp = norm_l(t0); + t0 = (t0 << alp_exp); + + alp_h = t0 >> 16; + alp_l = (t0 & 0xffff)>>1; + /*--------------------------------------* + * ITERATIONS I=2 to M * + *--------------------------------------*/ + for (i = 2; i <= M; i++) + { + /* t0 = SUM ( R[j]*A[i-j] ,j=1,i-1 ) + R[i] */ + t0 = 0; + for (j = 1; j < i; j++) + t0 = vo_L_add(t0, Mpy_32(Rh[j], Rl[j], Ah[i - j], Al[i - j])); + + t0 = t0 << 4; /* result in Q27 -> convert to Q31 */ + /* No overflow possible */ + t1 = ((Rh[i] << 16) + (Rl[i] << 1)); + t0 = vo_L_add(t0, t1); /* add R[i] in Q31 */ + + /* K = -t0 / Alpha */ + t1 = L_abs(t0); + t2 = Div_32(t1, alp_h, alp_l); /* abs(t0)/Alpha */ + if (t0 > 0) + t2 = -t2; /* K =-t0/Alpha */ + t2 = (t2 << alp_exp); /* denormalize; compare to Alpha */ + + Kh = t2 >> 16; + Kl = (t2 & 0xffff)>>1; + + rc[i - 1] = Kh; + /* Test for unstable filter. If unstable keep old A(z) */ + if (abs_s(Kh) > 32750) + { + A[0] = 4096; /* Ai[0] not stored (always 1.0) */ + for (j = 0; j < M; j++) + { + A[j + 1] = old_A[j]; + } + rc[0] = old_rc[0]; /* only two rc coefficients are needed */ + rc[1] = old_rc[1]; + return; + } + /*------------------------------------------* + * Compute new LPC coeff. -> An[i] * + * An[j]= A[j] + K*A[i-j] , j=1 to i-1 * + * An[i]= K * + *------------------------------------------*/ + for (j = 1; j < i; j++) + { + t0 = Mpy_32(Kh, Kl, Ah[i - j], Al[i - j]); + t0 = vo_L_add(t0, ((Ah[j] << 16) + (Al[j] << 1))); + Anh[j] = t0 >> 16; + Anl[j] = (t0 & 0xffff)>>1; + } + t2 = (t2 >> 4); /* t2 = K in Q31 ->convert to Q27 */ + + VO_L_Extract(t2, &Anh[i], &Anl[i]); /* An[i] in Q27 */ + + /* Alpha = Alpha * (1-K**2) */ + t0 = Mpy_32(Kh, Kl, Kh, Kl); /* K*K in Q31 */ + t0 = L_abs(t0); /* Some case <0 !! */ + t0 = vo_L_sub((Word32) 0x7fffffffL, t0); /* 1 - K*K in Q31 */ + hi = t0 >> 16; + lo = (t0 & 0xffff)>>1; + t0 = Mpy_32(alp_h, alp_l, hi, lo); /* Alpha in Q31 */ + + /* Normalize Alpha */ + j = norm_l(t0); + t0 = (t0 << j); + alp_h = t0 >> 16; + alp_l = (t0 & 0xffff)>>1; + alp_exp += j; /* Add normalization to alp_exp */ + + /* A[j] = An[j] */ + for (j = 1; j <= i; j++) + { + Ah[j] = Anh[j]; + Al[j] = Anl[j]; + } + } + /* Truncate A[i] in Q27 to Q12 with rounding */ + A[0] = 4096; + for (i = 1; i <= M; i++) + { + t0 = (Ah[i] << 16) + (Al[i] << 1); + old_A[i - 1] = A[i] = vo_round((t0 << 1)); + } + old_rc[0] = rc[0]; + old_rc[1] = rc[1]; + + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/log2.c b/media/libstagefright/codecs/amrwbenc/src/log2.c new file mode 100644 index 0000000000000000000000000000000000000000..cd3d815daf6894004e825fdece09acb5306baf46 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/log2.c @@ -0,0 +1,111 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* * +* File : log2.c * +* Purpose : Computes log2(L_x) * +* * +************************************************************************/ + +#include "log2.h" +/******************************************************************************** +* INCLUDE FILES +*********************************************************************************/ +#include "typedef.h" +#include "basic_op.h" + +/********************************************************************************* +* LOCAL VARIABLES AND TABLES +**********************************************************************************/ +#include "log2_tab.h" /* Table for Log2() */ + +/************************************************************************* +* +* FUNCTION: Log2_norm() +* +* PURPOSE: Computes log2(L_x, exp), where L_x is positive and +* normalized, and exp is the normalisation exponent +* If L_x is negative or zero, the result is 0. +* +* DESCRIPTION: +* The function Log2(L_x) is approximated by a table and linear +* interpolation. The following steps are used to compute Log2(L_x) +* +* 1- exponent = 30-norm_exponent +* 2- i = bit25-b31 of L_x; 32<=i<=63 (because of normalization). +* 3- a = bit10-b24 +* 4- i -=32 +* 5- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2 +* +*************************************************************************/ + +void Log2_norm ( + Word32 L_x, /* (i) : input value (normalized) */ + Word16 exp, /* (i) : norm_l (L_x) */ + Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */ + Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */ + ) +{ + Word16 i, a, tmp; + Word32 L_y; + if (L_x <= (Word32) 0) + { + *exponent = 0; + *fraction = 0; + return; + } + *exponent = (30 - exp); + L_x = (L_x >> 9); + i = extract_h (L_x); /* Extract b25-b31 */ + L_x = (L_x >> 1); + a = (Word16)(L_x); /* Extract b10-b24 of fraction */ + a = (Word16)(a & (Word16)0x7fff); + i -= 32; + L_y = L_deposit_h (table[i]); /* table[i] << 16 */ + tmp = vo_sub(table[i], table[i + 1]); /* table[i] - table[i+1] */ + L_y = vo_L_msu (L_y, tmp, a); /* L_y -= tmp*a*2 */ + *fraction = extract_h (L_y); + + return; +} + +/************************************************************************* +* +* FUNCTION: Log2() +* +* PURPOSE: Computes log2(L_x), where L_x is positive. +* If L_x is negative or zero, the result is 0. +* +* DESCRIPTION: +* normalizes L_x and then calls Log2_norm(). +* +*************************************************************************/ + +void Log2 ( + Word32 L_x, /* (i) : input value */ + Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */ + Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */ + ) +{ + Word16 exp; + + exp = norm_l(L_x); + Log2_norm ((L_x << exp), exp, exponent, fraction); +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/lp_dec2.c b/media/libstagefright/codecs/amrwbenc/src/lp_dec2.c new file mode 100644 index 0000000000000000000000000000000000000000..63b746b2552364f6580b7ea836670cf87d712634 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/lp_dec2.c @@ -0,0 +1,70 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: lp_dec2.c * +* * +* Description:Decimate a vector by 2 with 2nd order fir filter * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "cnst.h" + +#define L_FIR 5 +#define L_MEM (L_FIR-2) + +/* static float h_fir[L_FIR] = {0.13, 0.23, 0.28, 0.23, 0.13}; */ +/* fixed-point: sum of coef = 32767 to avoid overflow on DC */ +static Word16 h_fir[L_FIR] = {4260, 7536, 9175, 7536, 4260}; + +void LP_Decim2( + Word16 x[], /* in/out: signal to process */ + Word16 l, /* input : size of filtering */ + Word16 mem[] /* in/out: memory (size=3) */ + ) +{ + Word16 *p_x, x_buf[L_FRAME + L_MEM]; + Word32 i, j; + Word32 L_tmp; + /* copy initial filter states into buffer */ + p_x = x_buf; + for (i = 0; i < L_MEM; i++) + { + *p_x++ = mem[i]; + mem[i] = x[l - L_MEM + i]; + } + for (i = 0; i < l; i++) + { + *p_x++ = x[i]; + } + for (i = 0, j = 0; i < l; i += 2, j++) + { + p_x = &x_buf[i]; + L_tmp = ((*p_x++) * h_fir[0]); + L_tmp += ((*p_x++) * h_fir[1]); + L_tmp += ((*p_x++) * h_fir[2]); + L_tmp += ((*p_x++) * h_fir[3]); + L_tmp += ((*p_x++) * h_fir[4]); + x[j] = (L_tmp + 0x4000)>>15; + } + return; +} + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/math_op.c b/media/libstagefright/codecs/amrwbenc/src/math_op.c new file mode 100644 index 0000000000000000000000000000000000000000..1c95ed02513312e2ee8614be35bd8ae1f1130910 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/math_op.c @@ -0,0 +1,219 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*___________________________________________________________________________ +| | +| This file contains mathematic operations in fixed point. | +| | +| Isqrt() : inverse square root (16 bits precision). | +| Pow2() : 2^x (16 bits precision). | +| Log2() : log2 (16 bits precision). | +| Dot_product() : scalar product of | +| | +| These operations are not standard double precision operations. | +| They are used where low complexity is important and the full 32 bits | +| precision is not necessary. For example, the function Div_32() has a | +| 24 bits precision which is enough for our purposes. | +| | +| In this file, the values use theses representations: | +| | +| Word32 L_32 : standard signed 32 bits format | +| Word16 hi, lo : L_32 = hi<<16 + lo<<1 (DPF - Double Precision Format) | +| Word32 frac, Word16 exp : L_32 = frac << exp-31 (normalised format) | +| Word16 int, frac : L_32 = int.frac (fractional format) | +|___________________________________________________________________________| +*/ +#include "typedef.h" +#include "basic_op.h" +#include "math_op.h" + +/*___________________________________________________________________________ +| | +| Function Name : Isqrt | +| | +| Compute 1/sqrt(L_x). | +| if L_x is negative or zero, result is 1 (7fffffff). | +|---------------------------------------------------------------------------| +| Algorithm: | +| | +| 1- Normalization of L_x. | +| 2- call Isqrt_n(L_x, exponant) | +| 3- L_y = L_x << exponant | +|___________________________________________________________________________| +*/ +Word32 Isqrt( /* (o) Q31 : output value (range: 0<=val<1) */ + Word32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */ + ) +{ + Word16 exp; + Word32 L_y; + exp = norm_l(L_x); + L_x = (L_x << exp); /* L_x is normalized */ + exp = (31 - exp); + Isqrt_n(&L_x, &exp); + L_y = (L_x << exp); /* denormalization */ + return (L_y); +} + +/*___________________________________________________________________________ +| | +| Function Name : Isqrt_n | +| | +| Compute 1/sqrt(value). | +| if value is negative or zero, result is 1 (frac=7fffffff, exp=0). | +|---------------------------------------------------------------------------| +| Algorithm: | +| | +| The function 1/sqrt(value) is approximated by a table and linear | +| interpolation. | +| | +| 1- If exponant is odd then shift fraction right once. | +| 2- exponant = -((exponant-1)>>1) | +| 3- i = bit25-b30 of fraction, 16 <= i <= 63 ->because of normalization. | +| 4- a = bit10-b24 | +| 5- i -=16 | +| 6- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2 | +|___________________________________________________________________________| +*/ +static Word16 table_isqrt[49] = +{ + 32767, 31790, 30894, 30070, 29309, 28602, 27945, 27330, 26755, 26214, + 25705, 25225, 24770, 24339, 23930, 23541, 23170, 22817, 22479, 22155, + 21845, 21548, 21263, 20988, 20724, 20470, 20225, 19988, 19760, 19539, + 19326, 19119, 18919, 18725, 18536, 18354, 18176, 18004, 17837, 17674, + 17515, 17361, 17211, 17064, 16921, 16782, 16646, 16514, 16384 +}; + +void Isqrt_n( + Word32 * frac, /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */ + Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */ + ) +{ + Word16 i, a, tmp; + + if (*frac <= (Word32) 0) + { + *exp = 0; + *frac = 0x7fffffffL; + return; + } + + if((*exp & 1) == 1) /*If exponant odd -> shift right */ + *frac = (*frac) >> 1; + + *exp = negate((*exp - 1) >> 1); + + *frac = (*frac >> 9); + i = extract_h(*frac); /* Extract b25-b31 */ + *frac = (*frac >> 1); + a = (Word16)(*frac); /* Extract b10-b24 */ + a = (Word16) (a & (Word16) 0x7fff); + i -= 16; + *frac = L_deposit_h(table_isqrt[i]); /* table[i] << 16 */ + tmp = vo_sub(table_isqrt[i], table_isqrt[i + 1]); /* table[i] - table[i+1]) */ + *frac = vo_L_msu(*frac, tmp, a); /* frac -= tmp*a*2 */ + + return; +} + +/*___________________________________________________________________________ +| | +| Function Name : Pow2() | +| | +| L_x = pow(2.0, exponant.fraction) (exponant = interger part) | +| = pow(2.0, 0.fraction) << exponant | +|---------------------------------------------------------------------------| +| Algorithm: | +| | +| The function Pow2(L_x) is approximated by a table and linear | +| interpolation. | +| | +| 1- i = bit10-b15 of fraction, 0 <= i <= 31 | +| 2- a = bit0-b9 of fraction | +| 3- L_x = table[i]<<16 - (table[i] - table[i+1]) * a * 2 | +| 4- L_x = L_x >> (30-exponant) (with rounding) | +|___________________________________________________________________________| +*/ +static Word16 table_pow2[33] = +{ + 16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911, + 20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726, + 25268, 25821, 26386, 26964, 27554, 28158, 28774, 29405, 30048, 30706, + 31379, 32066, 32767 +}; + +Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */ + Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */ + Word16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */ + ) +{ + Word16 exp, i, a, tmp; + Word32 L_x; + + L_x = vo_L_mult(fraction, 32); /* L_x = fraction<<6 */ + i = extract_h(L_x); /* Extract b10-b16 of fraction */ + L_x =L_x >> 1; + a = (Word16)(L_x); /* Extract b0-b9 of fraction */ + a = (Word16) (a & (Word16) 0x7fff); + + L_x = L_deposit_h(table_pow2[i]); /* table[i] << 16 */ + tmp = vo_sub(table_pow2[i], table_pow2[i + 1]); /* table[i] - table[i+1] */ + L_x -= (tmp * a)<<1; /* L_x -= tmp*a*2 */ + + exp = vo_sub(30, exponant); + L_x = vo_L_shr_r(L_x, exp); + + return (L_x); +} + +/*___________________________________________________________________________ +| | +| Function Name : Dot_product12() | +| | +| Compute scalar product of using accumulator. | +| | +| The result is normalized (in Q31) with exponent (0..30). | +|---------------------------------------------------------------------------| +| Algorithm: | +| | +| dot_product = sum(x[i]*y[i]) i=0..N-1 | +|___________________________________________________________________________| +*/ + +Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */ + Word16 x[], /* (i) 12bits: x vector */ + Word16 y[], /* (i) 12bits: y vector */ + Word16 lg, /* (i) : vector length */ + Word16 * exp /* (o) : exponent of result (0..+30) */ + ) +{ + Word16 sft; + Word32 i, L_sum; + L_sum = 0; + for (i = 0; i < lg; i++) + { + L_sum += x[i] * y[i]; + } + L_sum = (L_sum << 1) + 1; + /* Normalize acc in Q31 */ + sft = norm_l(L_sum); + L_sum = L_sum << sft; + *exp = 30 - sft; /* exponent = 0..30 */ + return (L_sum); + +} + + diff --git a/media/libstagefright/codecs/amrwbenc/src/mem_align.c b/media/libstagefright/codecs/amrwbenc/src/mem_align.c new file mode 100644 index 0000000000000000000000000000000000000000..e58915a0a0f8f97efde32e109a1cd3027709b503 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/mem_align.c @@ -0,0 +1,107 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/******************************************************************************* + File: mem_align.c + + Content: Memory alloc alignments functions + +*******************************************************************************/ + + +#include "mem_align.h" + +/***************************************************************************** +* +* function name: mem_malloc +* description: malloc the alignments memory +* returns: the point of the memory +* +**********************************************************************************/ +void * +mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID) +{ + int ret; + unsigned char *mem_ptr; + VO_MEM_INFO MemInfo; + + if (!alignment) { + + MemInfo.Flag = 0; + MemInfo.Size = size + 1; + ret = pMemop->Alloc(CodecID, &MemInfo); + if(ret != 0) + return 0; + mem_ptr = (unsigned char *)MemInfo.VBuffer; + + pMemop->Set(CodecID, mem_ptr, 0, size + 1); + + *mem_ptr = (unsigned char)1; + + return ((void *)(mem_ptr+1)); + } else { + unsigned char *tmp; + + MemInfo.Flag = 0; + MemInfo.Size = size + alignment; + ret = pMemop->Alloc(CodecID, &MemInfo); + if(ret != 0) + return 0; + + tmp = (unsigned char *)MemInfo.VBuffer; + + pMemop->Set(CodecID, tmp, 0, size + alignment); + + mem_ptr = + (unsigned char *) ((unsigned int) (tmp + alignment - 1) & + (~((unsigned int) (alignment - 1)))); + + if (mem_ptr == tmp) + mem_ptr += alignment; + + *(mem_ptr - 1) = (unsigned char) (mem_ptr - tmp); + + return ((void *)mem_ptr); + } + + return(0); +} + + +/***************************************************************************** +* +* function name: mem_free +* description: free the memory +* +*******************************************************************************/ +void +mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID) +{ + + unsigned char *ptr; + + if (mem_ptr == 0) + return; + + ptr = mem_ptr; + + ptr -= *(ptr - 1); + + pMemop->Free(CodecID, ptr); +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/oper_32b.c b/media/libstagefright/codecs/amrwbenc/src/oper_32b.c new file mode 100644 index 0000000000000000000000000000000000000000..5f1523eac6eb4732b3c120970cb3f12d21126e7d --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/oper_32b.c @@ -0,0 +1,223 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/***************************************************************************** + * This file contains operations in double precision. * + * These operations are not standard double precision operations. * + * They are used where single precision is not enough but the full 32 bits * + * precision is not necessary. For example, the function Div_32() has a * + * 24 bits precision which is enough for our purposes. * + * * + * The double precision numbers use a special representation: * + * * + * L_32 = hi<<16 + lo<<1 * + * * + * L_32 is a 32 bit integer. * + * hi and lo are 16 bit signed integers. * + * As the low part also contains the sign, this allows fast multiplication. * + * * + * 0x8000 0000 <= L_32 <= 0x7fff fffe. * + * * + * We will use DPF (Double Precision Format )in this file to specify * + * this special format. * + ***************************************************************************** +*/ +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" + +/***************************************************************************** + * * + * Function L_Extract() * + * * + * Extract from a 32 bit integer two 16 bit DPF. * + * * + * Arguments: * + * * + * L_32 : 32 bit integer. * + * 0x8000 0000 <= L_32 <= 0x7fff ffff. * + * hi : b16 to b31 of L_32 * + * lo : (L_32 - hi<<16)>>1 * + ***************************************************************************** +*/ + +__inline void VO_L_Extract (Word32 L_32, Word16 *hi, Word16 *lo) +{ + *hi = (Word16)(L_32 >> 16); + *lo = (Word16)((L_32 & 0xffff) >> 1); + return; +} + +/***************************************************************************** + * * + * Function L_Comp() * + * * + * Compose from two 16 bit DPF a 32 bit integer. * + * * + * L_32 = hi<<16 + lo<<1 * + * * + * Arguments: * + * * + * hi msb * + * lo lsf (with sign) * + * * + * Return Value : * + * * + * 32 bit long signed integer (Word32) whose value falls in the * + * range : 0x8000 0000 <= L_32 <= 0x7fff fff0. * + * * + ***************************************************************************** +*/ + +Word32 L_Comp (Word16 hi, Word16 lo) +{ + Word32 L_32; + + L_32 = L_deposit_h (hi); + + return (L_mac (L_32, lo, 1)); /* = hi<<16 + lo<<1 */ +} + +/***************************************************************************** + * Function Mpy_32() * + * * + * Multiply two 32 bit integers (DPF). The result is divided by 2**31 * + * * + * L_32 = (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1 * + * * + * This operation can also be viewed as the multiplication of two Q31 * + * number and the result is also in Q31. * + * * + * Arguments: * + * * + * hi1 hi part of first number * + * lo1 lo part of first number * + * hi2 hi part of second number * + * lo2 lo part of second number * + * * + ***************************************************************************** +*/ + +__inline Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2) +{ + Word32 L_32; + L_32 = (hi1 * hi2); + L_32 += (hi1 * lo2) >> 15; + L_32 += (lo1 * hi2) >> 15; + L_32 <<= 1; + + return (L_32); +} + +/***************************************************************************** + * Function Mpy_32_16() * + * * + * Multiply a 16 bit integer by a 32 bit (DPF). The result is divided * + * by 2**15 * + * * + * * + * L_32 = (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 * + * * + * Arguments: * + * * + * hi hi part of 32 bit number. * + * lo lo part of 32 bit number. * + * n 16 bit number. * + * * + ***************************************************************************** +*/ + +__inline Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n) +{ + Word32 L_32; + + L_32 = (hi * n)<<1; + L_32 += (((lo * n)>>15)<<1); + + return (L_32); +} + +/***************************************************************************** + * * + * Function Name : Div_32 * + * * + * Purpose : * + * Fractional integer division of two 32 bit numbers. * + * L_num / L_denom. * + * L_num and L_denom must be positive and L_num < L_denom. * + * L_denom = denom_hi<<16 + denom_lo<<1 * + * denom_hi is a normalize number. * + * * + * Inputs : * + * * + * L_num * + * 32 bit long signed integer (Word32) whose value falls in the * + * range : 0x0000 0000 < L_num < L_denom * + * * + * L_denom = denom_hi<<16 + denom_lo<<1 (DPF) * + * * + * denom_hi * + * 16 bit positive normalized integer whose value falls in the * + * range : 0x4000 < hi < 0x7fff * + * denom_lo * + * 16 bit positive integer whose value falls in the * + * range : 0 < lo < 0x7fff * + * * + * Return Value : * + * * + * L_div * + * 32 bit long signed integer (Word32) whose value falls in the * + * range : 0x0000 0000 <= L_div <= 0x7fff ffff. * + * * + * Algorithm: * + * * + * - find = 1/L_denom. * + * First approximation: approx = 1 / denom_hi * + * 1/L_denom = approx * (2.0 - L_denom * approx ) * + * * + * - result = L_num * (1/L_denom) * + ***************************************************************************** +*/ + +Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo) +{ + Word16 approx, hi, lo, n_hi, n_lo; + Word32 L_32; + + /* First approximation: 1 / L_denom = 1/denom_hi */ + + approx = div_s ((Word16) 0x3fff, denom_hi); + + /* 1/L_denom = approx * (2.0 - L_denom * approx) */ + + L_32 = Mpy_32_16 (denom_hi, denom_lo, approx); + + L_32 = L_sub ((Word32) 0x7fffffffL, L_32); + hi = L_32 >> 16; + lo = (L_32 & 0xffff) >> 1; + + L_32 = Mpy_32_16 (hi, lo, approx); + + /* L_num * (1/L_denom) */ + hi = L_32 >> 16; + lo = (L_32 & 0xffff) >> 1; + VO_L_Extract (L_num, &n_hi, &n_lo); + L_32 = Mpy_32 (n_hi, n_lo, hi, lo); + L_32 = L_shl2(L_32, 2); + + return (L_32); +} + diff --git a/media/libstagefright/codecs/amrwbenc/src/p_med_ol.c b/media/libstagefright/codecs/amrwbenc/src/p_med_ol.c new file mode 100644 index 0000000000000000000000000000000000000000..39ee96660c55404eaf08dcda69504a5a4524eff6 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/p_med_ol.c @@ -0,0 +1,256 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: p_med_ol.c * +* * +* Description: Compute the open loop pitch lag * +* output: open loop pitch lag * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "acelp.h" +#include "oper_32b.h" +#include "math_op.h" +#include "p_med_ol.tab" + +Word16 Pitch_med_ol( + Word16 wsp[], /* i: signal used to compute the open loop pitch*/ + /* wsp[-pit_max] to wsp[-1] should be known */ + Coder_State *st, /* i/o: codec global structure */ + Word16 L_frame /* i: length of frame to compute pitch */ + ) +{ + Word16 Tm; + Word16 hi, lo; + Word16 *ww, *we, *hp_wsp; + Word16 exp_R0, exp_R1, exp_R2; + Word32 i, j, max, R0, R1, R2; + Word16 *p1, *p2; + Word16 L_min = 17; /* minimum pitch lag: PIT_MIN / OPL_DECIM */ + Word16 L_max = 115; /* maximum pitch lag: PIT_MAX / OPL_DECIM */ + Word16 L_0 = st->old_T0_med; /* old open-loop pitch */ + Word16 *gain = &(st->ol_gain); /* normalize correlation of hp_wsp for the lag */ + Word16 *hp_wsp_mem = st->hp_wsp_mem; /* memory of the hypass filter for hp_wsp[] (lg = 9)*/ + Word16 *old_hp_wsp = st->old_hp_wsp; /* hypass wsp[] */ + Word16 wght_flg = st->ol_wght_flg; /* is weighting function used */ + + ww = &corrweight[198]; + we = &corrweight[98 + L_max - L_0]; + + max = MIN_32; + Tm = 0; + for (i = L_max; i > L_min; i--) + { + /* Compute the correlation */ + R0 = 0; + p1 = wsp; + p2 = &wsp[-i]; + for (j = 0; j < L_frame; j+=4) + { + R0 += vo_L_mult((*p1++), (*p2++)); + R0 += vo_L_mult((*p1++), (*p2++)); + R0 += vo_L_mult((*p1++), (*p2++)); + R0 += vo_L_mult((*p1++), (*p2++)); + } + /* Weighting of the correlation function. */ + hi = R0>>16; + lo = (R0 & 0xffff)>>1; + + R0 = Mpy_32_16(hi, lo, *ww); + ww--; + + if ((L_0 > 0) && (wght_flg > 0)) + { + /* Weight the neighbourhood of the old lag. */ + hi = R0>>16; + lo = (R0 & 0xffff)>>1; + R0 = Mpy_32_16(hi, lo, *we); + we--; + } + if(R0 >= max) + { + max = R0; + Tm = i; + } + } + + /* Hypass the wsp[] vector */ + hp_wsp = old_hp_wsp + L_max; + Hp_wsp(wsp, hp_wsp, L_frame, hp_wsp_mem); + + /* Compute normalize correlation at delay Tm */ + R0 = 0; + R1 = 0; + R2 = 0; + p1 = hp_wsp; + p2 = hp_wsp - Tm; + for (j = 0; j < L_frame; j+=4) + { + R2 += vo_mult32(*p1, *p1); + R1 += vo_mult32(*p2, *p2); + R0 += vo_mult32(*p1++, *p2++); + R2 += vo_mult32(*p1, *p1); + R1 += vo_mult32(*p2, *p2); + R0 += vo_mult32(*p1++, *p2++); + R2 += vo_mult32(*p1, *p1); + R1 += vo_mult32(*p2, *p2); + R0 += vo_mult32(*p1++, *p2++); + R2 += vo_mult32(*p1, *p1); + R1 += vo_mult32(*p2, *p2); + R0 += vo_mult32(*p1++, *p2++); + } + R0 = R0 <<1; + R1 = (R1 <<1) + 1L; + R2 = (R2 <<1) + 1L; + /* gain = R0/ sqrt(R1*R2) */ + + exp_R0 = norm_l(R0); + R0 = (R0 << exp_R0); + + exp_R1 = norm_l(R1); + R1 = (R1 << exp_R1); + + exp_R2 = norm_l(R2); + R2 = (R2 << exp_R2); + + + R1 = vo_L_mult(vo_round(R1), vo_round(R2)); + + i = norm_l(R1); + R1 = (R1 << i); + + exp_R1 += exp_R2; + exp_R1 += i; + exp_R1 = 62 - exp_R1; + + Isqrt_n(&R1, &exp_R1); + + R0 = vo_L_mult(voround(R0), voround(R1)); + exp_R0 = 31 - exp_R0; + exp_R0 += exp_R1; + + *gain = vo_round(L_shl(R0, exp_R0)); + + /* Shitf hp_wsp[] for next frame */ + + for (i = 0; i < L_max; i++) + { + old_hp_wsp[i] = old_hp_wsp[i + L_frame]; + } + + return (Tm); +} + +/************************************************************************ +* Function: median5 * +* * +* Returns the median of the set {X[-2], X[-1],..., X[2]}, * +* whose elements are 16-bit integers. * +* * +* Input: * +* X[-2:2] 16-bit integers. * +* * +* Return: * +* The median of {X[-2], X[-1],..., X[2]}. * +************************************************************************/ + +Word16 median5(Word16 x[]) +{ + Word16 x1, x2, x3, x4, x5; + Word16 tmp; + + x1 = x[-2]; + x2 = x[-1]; + x3 = x[0]; + x4 = x[1]; + x5 = x[2]; + + if (x2 < x1) + { + tmp = x1; + x1 = x2; + x2 = tmp; + } + if (x3 < x1) + { + tmp = x1; + x1 = x3; + x3 = tmp; + } + if (x4 < x1) + { + tmp = x1; + x1 = x4; + x4 = tmp; + } + if (x5 < x1) + { + x5 = x1; + } + if (x3 < x2) + { + tmp = x2; + x2 = x3; + x3 = tmp; + } + if (x4 < x2) + { + tmp = x2; + x2 = x4; + x4 = tmp; + } + if (x5 < x2) + { + x5 = x2; + } + if (x4 < x3) + { + x3 = x4; + } + if (x5 < x3) + { + x3 = x5; + } + return (x3); +} + + +Word16 Med_olag( /* output : median of 5 previous open-loop lags */ + Word16 prev_ol_lag, /* input : previous open-loop lag */ + Word16 old_ol_lag[5] + ) +{ + Word32 i; + + /* Use median of 5 previous open-loop lags as old lag */ + + for (i = 4; i > 0; i--) + { + old_ol_lag[i] = old_ol_lag[i - 1]; + } + + old_ol_lag[0] = prev_ol_lag; + + i = median5(&old_ol_lag[2]); + + return i; + +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/pit_shrp.c b/media/libstagefright/codecs/amrwbenc/src/pit_shrp.c new file mode 100644 index 0000000000000000000000000000000000000000..c8a227c2e1b7ea6777e0f02c6f06d49ac54ea23e --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/pit_shrp.c @@ -0,0 +1,49 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: pit_shrp.c * +* * +* Description: Performs Pitch sharpening routine * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + +void Pit_shrp( + Word16 * x, /* in/out: impulse response (or algebraic code) */ + Word16 pit_lag, /* input : pitch lag */ + Word16 sharp, /* input : pitch sharpening factor (Q15) */ + Word16 L_subfr /* input : subframe size */ + ) +{ + Word32 i; + Word32 L_tmp; + Word16 *x_ptr = x + pit_lag; + + for (i = pit_lag; i < L_subfr; i++) + { + L_tmp = (*x_ptr << 15); + L_tmp += *x++ * sharp; + *x_ptr++ = ((L_tmp + 0x4000)>>15); + } + + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c b/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c new file mode 100644 index 0000000000000000000000000000000000000000..c115b11bdb397ea21e84df4b52960eadb60e3e7c --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c @@ -0,0 +1,324 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: pitch_f4.c * +* * +* Description: Find the closed loop pitch period with * +* 1/4 subsample resolution. * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "math_op.h" +#include "acelp.h" +#include "cnst.h" + +#define UP_SAMP 4 +#define L_INTERPOL1 4 + +/* Local functions */ + +#ifdef ASM_OPT +void Norm_corr_asm( + Word16 exc[], /* (i) : excitation buffer */ + Word16 xn[], /* (i) : target vector */ + Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */ + Word16 L_subfr, + Word16 t_min, /* (i) : minimum value of pitch lag. */ + Word16 t_max, /* (i) : maximum value of pitch lag. */ + Word16 corr_norm[] /* (o) Q15 : normalized correlation */ + ); +#else +static void Norm_Corr( + Word16 exc[], /* (i) : excitation buffer */ + Word16 xn[], /* (i) : target vector */ + Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */ + Word16 L_subfr, + Word16 t_min, /* (i) : minimum value of pitch lag. */ + Word16 t_max, /* (i) : maximum value of pitch lag. */ + Word16 corr_norm[] /* (o) Q15 : normalized correlation */ + ); +#endif + +static Word16 Interpol_4( /* (o) : interpolated value */ + Word16 * x, /* (i) : input vector */ + Word32 frac /* (i) : fraction (-4..+3) */ + ); + + +Word16 Pitch_fr4( /* (o) : pitch period. */ + Word16 exc[], /* (i) : excitation buffer */ + Word16 xn[], /* (i) : target vector */ + Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */ + Word16 t0_min, /* (i) : minimum value in the searched range. */ + Word16 t0_max, /* (i) : maximum value in the searched range. */ + Word16 * pit_frac, /* (o) : chosen fraction (0, 1, 2 or 3). */ + Word16 i_subfr, /* (i) : indicator for first subframe. */ + Word16 t0_fr2, /* (i) : minimum value for resolution 1/2 */ + Word16 t0_fr1, /* (i) : minimum value for resolution 1 */ + Word16 L_subfr /* (i) : Length of subframe */ + ) +{ + Word32 fraction, i; + Word16 t_min, t_max; + Word16 max, t0, step, temp; + Word16 *corr; + Word16 corr_v[40]; /* Total length = t0_max-t0_min+1+2*L_inter */ + + /* Find interval to compute normalized correlation */ + + t_min = t0_min - L_INTERPOL1; + t_max = t0_max + L_INTERPOL1; + corr = &corr_v[-t_min]; + /* Compute normalized correlation between target and filtered excitation */ +#ifdef ASM_OPT /* asm optimization branch */ + Norm_corr_asm(exc, xn, h, L_subfr, t_min, t_max, corr); +#else + Norm_Corr(exc, xn, h, L_subfr, t_min, t_max, corr); +#endif + + /* Find integer pitch */ + + max = corr[t0_min]; + t0 = t0_min; + for (i = t0_min + 1; i <= t0_max; i++) + { + if (corr[i] >= max) + { + max = corr[i]; + t0 = i; + } + } + /* If first subframe and t0 >= t0_fr1, do not search fractionnal pitch */ + if ((i_subfr == 0) && (t0 >= t0_fr1)) + { + *pit_frac = 0; + return (t0); + } + /*------------------------------------------------------------------* + * Search fractionnal pitch with 1/4 subsample resolution. * + * Test the fractions around t0 and choose the one which maximizes * + * the interpolated normalized correlation. * + *------------------------------------------------------------------*/ + + step = 1; /* 1/4 subsample resolution */ + fraction = -3; + if ((t0_fr2 == PIT_MIN)||((i_subfr == 0) && (t0 >= t0_fr2))) + { + step = 2; /* 1/2 subsample resolution */ + fraction = -2; + } + if(t0 == t0_min) + { + fraction = 0; + } + max = Interpol_4(&corr[t0], fraction); + + for (i = fraction + step; i <= 3; i += step) + { + temp = Interpol_4(&corr[t0], i); + if(temp > max) + { + max = temp; + fraction = i; + } + } + /* limit the fraction value in the interval [0,1,2,3] */ + if (fraction < 0) + { + fraction += UP_SAMP; + t0 -= 1; + } + *pit_frac = fraction; + return (t0); +} + + +/*********************************************************************************** +* Function: Norm_Corr() * +* * +* Description: Find the normalized correlation between the target vector and the * +* filtered past excitation. * +* (correlation between target and filtered excitation divided by the * +* square root of energy of target and filtered excitation). * +************************************************************************************/ +#ifndef ASM_OPT +static void Norm_Corr( + Word16 exc[], /* (i) : excitation buffer */ + Word16 xn[], /* (i) : target vector */ + Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */ + Word16 L_subfr, + Word16 t_min, /* (i) : minimum value of pitch lag. */ + Word16 t_max, /* (i) : maximum value of pitch lag. */ + Word16 corr_norm[]) /* (o) Q15 : normalized correlation */ +{ + Word32 i, k, t; + Word32 corr, exp_corr, norm, exp, scale; + Word16 exp_norm, excf[L_SUBFR], tmp; + Word32 L_tmp, L_tmp1, L_tmp2; + + /* compute the filtered excitation for the first delay t_min */ + k = -t_min; + +#ifdef ASM_OPT /* asm optimization branch */ + Convolve_asm(&exc[k], h, excf, 64); +#else + Convolve(&exc[k], h, excf, 64); +#endif + + /* Compute rounded down 1/sqrt(energy of xn[]) */ + L_tmp = 0; + for (i = 0; i < 64; i+=4) + { + L_tmp += (xn[i] * xn[i]); + L_tmp += (xn[i+1] * xn[i+1]); + L_tmp += (xn[i+2] * xn[i+2]); + L_tmp += (xn[i+3] * xn[i+3]); + } + + L_tmp = (L_tmp << 1) + 1; + exp = norm_l(L_tmp); + exp = (32 - exp); + //exp = exp + 2; /* energy of xn[] x 2 + rounded up */ + scale = -(exp >> 1); /* (1<> L_tmp2; + } + else + { + L_tmp = L_tmp << L_tmp2; + } + + corr_norm[t] = vo_round(L_tmp); + /* modify the filtered excitation excf[] for the next iteration */ + + if(t != t_max) + { + k = -(t + 1); + tmp = exc[k]; + for (i = 63; i > 0; i--) + { + excf[i] = add1(vo_mult(tmp, h[i]), excf[i - 1]); + } + excf[0] = vo_mult(tmp, h[0]); + } + } + return; +} + +#endif +/************************************************************************************ +* Function: Interpol_4() * +* * +* Description: For interpolating the normalized correlation with 1/4 resolution. * +**************************************************************************************/ + +/* 1/4 resolution interpolation filter (-3 dB at 0.791*fs/2) in Q14 */ +static Word16 inter4_1[4][8] = +{ + {-12, 420, -1732, 5429, 13418, -1242, 73, 32}, + {-26, 455, -2142, 9910, 9910, -2142, 455, -26}, + {32, 73, -1242, 13418, 5429, -1732, 420, -12}, + {206, -766, 1376, 14746, 1376, -766, 206, 0} +}; + +/*** Coefficients in floating point +static float inter4_1[UP_SAMP*L_INTERPOL1+1] = { +0.900000, +0.818959, 0.604850, 0.331379, 0.083958, +-0.075795, -0.130717, -0.105685, -0.046774, +0.004467, 0.027789, 0.025642, 0.012571, +0.001927, -0.001571, -0.000753, 0.000000}; +***/ + +static Word16 Interpol_4( /* (o) : interpolated value */ + Word16 * x, /* (i) : input vector */ + Word32 frac /* (i) : fraction (-4..+3) */ + ) +{ + Word16 sum; + Word32 k, L_sum; + Word16 *ptr; + + if (frac < 0) + { + frac += UP_SAMP; + x--; + } + x = x - L_INTERPOL1 + 1; + k = UP_SAMP - 1 - frac; + ptr = &(inter4_1[k][0]); + + L_sum = vo_mult32(x[0], (*ptr++)); + L_sum += vo_mult32(x[1], (*ptr++)); + L_sum += vo_mult32(x[2], (*ptr++)); + L_sum += vo_mult32(x[3], (*ptr++)); + L_sum += vo_mult32(x[4], (*ptr++)); + L_sum += vo_mult32(x[5], (*ptr++)); + L_sum += vo_mult32(x[6], (*ptr++)); + L_sum += vo_mult32(x[7], (*ptr++)); + + sum = extract_h(L_add(L_shl2(L_sum, 2), 0x8000)); + return (sum); +} + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/pred_lt4.c b/media/libstagefright/codecs/amrwbenc/src/pred_lt4.c new file mode 100644 index 0000000000000000000000000000000000000000..ac1ff225440b9b04848a319e3e8ceb4567a654b2 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/pred_lt4.c @@ -0,0 +1,120 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: pred_lt4.c * +* * +* Description: Compute the result of long term prediction with * +* fractional interpolation of resolution 1/4 * +* on return exc[0..L_subr-1] contains the interpolated signal * +* (adaptive codebook excitation) * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + +#define UP_SAMP 4 +#define L_INTERPOL2 16 + +/* 1/4 resolution interpolation filter (-3 dB at 0.856*fs/2) in Q14 */ + +Word16 inter4_2[4][32] = +{ + {0,-2,4,-2,-10,38,-88,165,-275,424,-619,871,-1207,1699,-2598,5531,14031,-2147,780,-249, + -16,153,-213,226,-209,175,-133,91,-55,28,-10,2}, + + {1,-7,19,-33,47,-52,43,-9,-60,175,-355,626,-1044,1749,-3267,10359,10359,-3267,1749,-1044, + 626,-355,175,-60,-9,43,-52,47,-33,19, -7, 1}, + + {2,-10,28,-55,91,-133,175,-209,226,-213,153,-16,-249,780,-2147,14031,5531,-2598,1699,-1207, + 871,-619,424,-275,165,-88,38,-10,-2,4,-2,0}, + + {1,-7,22,-49,92,-153,231,-325,431,-544,656,-762,853,-923,968,15401,968,-923,853,-762, + 656,-544,431,-325,231,-153,92,-49,22,-7, 1, 0} + +}; + +void Pred_lt4( + Word16 exc[], /* in/out: excitation buffer */ + Word16 T0, /* input : integer pitch lag */ + Word16 frac, /* input : fraction of lag */ + Word16 L_subfr /* input : subframe size */ + ) +{ + Word16 j, k, *x; + Word32 L_sum; + Word16 *ptr, *ptr1; + Word16 *ptr2; + + x = exc - T0; + frac = -frac; + if (frac < 0) + { + frac += UP_SAMP; + x--; + } + x -= 15; /* x = L_INTERPOL2 - 1 */ + k = 3 - frac; /* k = UP_SAMP - 1 - frac */ + + ptr2 = &(inter4_2[k][0]); + for (j = 0; j < L_subfr; j++) + { + ptr = ptr2; + ptr1 = x; + L_sum = vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + L_sum += vo_mult32((*ptr1++), (*ptr++)); + + L_sum = L_shl2(L_sum, 2); + exc[j] = extract_h(L_add(L_sum, 0x8000)); + x++; + } + + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/preemph.c b/media/libstagefright/codecs/amrwbenc/src/preemph.c new file mode 100644 index 0000000000000000000000000000000000000000..f5bcd3376c15a174f1ffe99d85349cc78659f48d --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/preemph.c @@ -0,0 +1,88 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: preemph.c * +* * +* Description: Preemphasis: filtering through 1 - g z^-1 * +* Preemph2 --> signal is multiplied by 2 * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + +void Preemph( + Word16 x[], /* (i/o) : input signal overwritten by the output */ + Word16 mu, /* (i) Q15 : preemphasis coefficient */ + Word16 lg, /* (i) : lenght of filtering */ + Word16 * mem /* (i/o) : memory (x[-1]) */ + ) +{ + Word16 temp; + Word32 i, L_tmp; + + temp = x[lg - 1]; + + for (i = lg - 1; i > 0; i--) + { + L_tmp = L_deposit_h(x[i]); + L_tmp -= (x[i - 1] * mu)<<1; + x[i] = (L_tmp + 0x8000)>>16; + } + + L_tmp = L_deposit_h(x[0]); + L_tmp -= ((*mem) * mu)<<1; + x[0] = (L_tmp + 0x8000)>>16; + + *mem = temp; + + return; +} + + +void Preemph2( + Word16 x[], /* (i/o) : input signal overwritten by the output */ + Word16 mu, /* (i) Q15 : preemphasis coefficient */ + Word16 lg, /* (i) : lenght of filtering */ + Word16 * mem /* (i/o) : memory (x[-1]) */ + ) +{ + Word16 temp; + Word32 i, L_tmp; + + temp = x[lg - 1]; + + for (i = (Word16) (lg - 1); i > 0; i--) + { + L_tmp = L_deposit_h(x[i]); + L_tmp -= (x[i - 1] * mu)<<1; + L_tmp = (L_tmp << 1); + x[i] = (L_tmp + 0x8000)>>16; + } + + L_tmp = L_deposit_h(x[0]); + L_tmp -= ((*mem) * mu)<<1; + L_tmp = (L_tmp << 1); + x[0] = (L_tmp + 0x8000)>>16; + + *mem = temp; + + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/q_gain2.c b/media/libstagefright/codecs/amrwbenc/src/q_gain2.c new file mode 100644 index 0000000000000000000000000000000000000000..59eefe41142a8e136a08dd349a2c19397d406f5a --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/q_gain2.c @@ -0,0 +1,346 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/************************************************************************** +* File: q_gain2.c * +* * +* Description: * +* Quantization of pitch and codebook gains. * +* MA prediction is performed on the innovation energy (in dB with mean * +* removed). * +* An initial predicted gain, g_0, is first determined and the correction * +* factor alpha = gain / g_0 is quantized. * +* The pitch gain and the correction factor are vector quantized and the * +* mean-squared weighted error criterion is used in the quantizer search. * +****************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "math_op.h" +#include "log2.h" +#include "acelp.h" +#include "q_gain2.tab" + +#define MEAN_ENER 30 +#define RANGE 64 +#define PRED_ORDER 4 + + +/* MA prediction coeff ={0.5, 0.4, 0.3, 0.2} in Q13 */ +static Word16 pred[PRED_ORDER] = {4096, 3277, 2458, 1638}; + + +void Init_Q_gain2( + Word16 * mem /* output :static memory (2 words) */ + ) +{ + Word32 i; + + /* 4nd order quantizer energy predictor (init to -14.0 in Q10) */ + for (i = 0; i < PRED_ORDER; i++) + { + mem[i] = -14336; /* past_qua_en[i] */ + } + + return; +} + +Word16 Q_gain2( /* Return index of quantization. */ + Word16 xn[], /* (i) Q_xn: Target vector. */ + Word16 y1[], /* (i) Q_xn: Adaptive codebook. */ + Word16 Q_xn, /* (i) : xn and y1 format */ + Word16 y2[], /* (i) Q9 : Filtered innovative vector. */ + Word16 code[], /* (i) Q9 : Innovative vector. */ + Word16 g_coeff[], /* (i) : Correlations */ + /* Compute in G_pitch(). */ + Word16 L_subfr, /* (i) : Subframe lenght. */ + Word16 nbits, /* (i) : number of bits (6 or 7) */ + Word16 * gain_pit, /* (i/o)Q14: Pitch gain. */ + Word32 * gain_cod, /* (o) Q16 : Code gain. */ + Word16 gp_clip, /* (i) : Gp Clipping flag */ + Word16 * mem /* (i/o) : static memory (2 words) */ + ) +{ + Word16 index, *p, min_ind, size; + Word16 exp, frac, gcode0, exp_gcode0, e_max, exp_code, qua_ener; + Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo; + Word16 coeff[5], coeff_lo[5], exp_coeff[5]; + Word16 exp_max[5]; + Word32 i, j, L_tmp, dist_min; + Word16 *past_qua_en, *t_qua_gain; + + past_qua_en = mem; + + /*-----------------------------------------------------------------* + * - Find the initial quantization pitch index * + * - Set gains search range * + *-----------------------------------------------------------------*/ + if (nbits == 6) + { + t_qua_gain = t_qua_gain6b; + min_ind = 0; + size = RANGE; + + if(gp_clip == 1) + { + size = size - 16; /* limit gain pitch to 1.0 */ + } + } else + { + t_qua_gain = t_qua_gain7b; + + p = t_qua_gain7b + RANGE; /* pt at 1/4th of table */ + + j = nb_qua_gain7b - RANGE; + + if (gp_clip == 1) + { + j = j - 27; /* limit gain pitch to 1.0 */ + } + min_ind = 0; + g_pitch = *gain_pit; + + for (i = 0; i < j; i++, p += 2) + { + if (g_pitch > *p) + { + min_ind = min_ind + 1; + } + } + size = RANGE; + } + + /*------------------------------------------------------------------* + * Compute coefficient need for the quantization. * + * * + * coeff[0] = y1 y1 * + * coeff[1] = -2 xn y1 * + * coeff[2] = y2 y2 * + * coeff[3] = -2 xn y2 * + * coeff[4] = 2 y1 y2 * + * * + * Product and have been compute in G_pitch() and * + * are in vector g_coeff[]. * + *------------------------------------------------------------------*/ + + coeff[0] = g_coeff[0]; + exp_coeff[0] = g_coeff[1]; + coeff[1] = negate(g_coeff[2]); /* coeff[1] = -2 xn y1 */ + exp_coeff[1] = g_coeff[3] + 1; + + /* Compute scalar product */ +#ifdef ASM_OPT /* asm optimization branch */ + coeff[2] = extract_h(Dot_product12_asm(y2, y2, L_subfr, &exp)); +#else + coeff[2] = extract_h(Dot_product12(y2, y2, L_subfr, &exp)); +#endif + exp_coeff[2] = (exp - 18) + (Q_xn << 1); /* -18 (y2 Q9) */ + + /* Compute scalar product -2* */ +#ifdef ASM_OPT /* asm optimization branch */ + coeff[3] = extract_h(L_negate(Dot_product12_asm(xn, y2, L_subfr, &exp))); +#else + coeff[3] = extract_h(L_negate(Dot_product12(xn, y2, L_subfr, &exp))); +#endif + + exp_coeff[3] = (exp - 8) + Q_xn; /* -9 (y2 Q9), +1 (2 xn y2) */ + + /* Compute scalar product 2* */ +#ifdef ASM_OPT /* asm optimization branch */ + coeff[4] = extract_h(Dot_product12_asm(y1, y2, L_subfr, &exp)); +#else + coeff[4] = extract_h(Dot_product12(y1, y2, L_subfr, &exp)); +#endif + exp_coeff[4] = (exp - 8) + Q_xn; /* -9 (y2 Q9), +1 (2 y1 y2) */ + + /*-----------------------------------------------------------------* + * Find energy of code and compute: * + * * + * L_tmp = MEAN_ENER - 10log10(energy of code/ L_subfr) * + * = MEAN_ENER - 3.0103*log2(energy of code/ L_subfr) * + *-----------------------------------------------------------------*/ +#ifdef ASM_OPT /* asm optimization branch */ + L_tmp = Dot_product12_asm(code, code, L_subfr, &exp_code); +#else + L_tmp = Dot_product12(code, code, L_subfr, &exp_code); +#endif + /* exp_code: -18 (code in Q9), -6 (/L_subfr), -31 (L_tmp Q31->Q0) */ + exp_code = (exp_code - (18 + 6 + 31)); + + Log2(L_tmp, &exp, &frac); + exp += exp_code; + L_tmp = Mpy_32_16(exp, frac, -24660); /* x -3.0103(Q13) -> Q14 */ + + L_tmp += (MEAN_ENER * 8192)<<1; /* + MEAN_ENER in Q14 */ + + /*-----------------------------------------------------------------* + * Compute gcode0. * + * = Sum(i=0,1) pred[i]*past_qua_en[i] + mean_ener - ener_code * + *-----------------------------------------------------------------*/ + L_tmp = (L_tmp << 10); /* From Q14 to Q24 */ + L_tmp += (pred[0] * past_qua_en[0])<<1; /* Q13*Q10 -> Q24 */ + L_tmp += (pred[1] * past_qua_en[1])<<1; /* Q13*Q10 -> Q24 */ + L_tmp += (pred[2] * past_qua_en[2])<<1; /* Q13*Q10 -> Q24 */ + L_tmp += (pred[3] * past_qua_en[3])<<1; /* Q13*Q10 -> Q24 */ + + gcode0 = extract_h(L_tmp); /* From Q24 to Q8 */ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) * + * = pow(2, 3.321928*gcode0/20) * + * = pow(2, 0.166096*gcode0) * + *-----------------------------------------------------------------*/ + + L_tmp = vo_L_mult(gcode0, 5443); /* *0.166096 in Q15 -> Q24 */ + L_tmp = L_tmp >> 8; /* From Q24 to Q16 */ + VO_L_Extract(L_tmp, &exp_gcode0, &frac); /* Extract exponent of gcode0 */ + + gcode0 = (Word16)(Pow2(14, frac)); /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 -= 14; + + /*-------------------------------------------------------------------------* + * Find the best quantizer * + * ~~~~~~~~~~~~~~~~~~~~~~~ * + * Before doing the computation we need to aling exponents of coeff[] * + * to be sure to have the maximum precision. * + * * + * In the table the pitch gains are in Q14, the code gains are in Q11 and * + * are multiply by gcode0 which have been multiply by 2^exp_gcode0. * + * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code * + * we divide by 2^15. * + * Considering all the scaling above we have: * + * * + * exp_code = exp_gcode0-11+15 = exp_gcode0+4 * + * * + * g_pitch*g_pitch = -14-14+15 * + * g_pitch = -14 * + * g_code*g_code = (2*exp_code)+15 * + * g_code = exp_code * + * g_pitch*g_code = -14 + exp_code +15 * + * * + * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] - 13 * + * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] - 14 * + * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] +15+(2*exp_code) * + * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code * + * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code * + *-------------------------------------------------------------------------*/ + + exp_code = (exp_gcode0 + 4); + exp_max[0] = (exp_coeff[0] - 13); + exp_max[1] = (exp_coeff[1] - 14); + exp_max[2] = (exp_coeff[2] + (15 + (exp_code << 1))); + exp_max[3] = (exp_coeff[3] + exp_code); + exp_max[4] = (exp_coeff[4] + (1 + exp_code)); + + /* Find maximum exponant */ + + e_max = exp_max[0]; + for (i = 1; i < 5; i++) + { + if(exp_max[i] > e_max) + { + e_max = exp_max[i]; + } + } + + /* align coeff[] and save in special 32 bit double precision */ + + for (i = 0; i < 5; i++) + { + j = add1(vo_sub(e_max, exp_max[i]), 2);/* /4 to avoid overflow */ + L_tmp = L_deposit_h(coeff[i]); + L_tmp = L_shr(L_tmp, j); + VO_L_Extract(L_tmp, &coeff[i], &coeff_lo[i]); + coeff_lo[i] = (coeff_lo[i] >> 3); /* lo >> 3 */ + } + + /* Codebook search */ + dist_min = MAX_32; + p = &t_qua_gain[min_ind << 1]; + + index = 0; + for (i = 0; i < size; i++) + { + g_pitch = *p++; + g_code = *p++; + + g_code = ((g_code * gcode0) + 0x4000)>>15; + g2_pitch = ((g_pitch * g_pitch) + 0x4000)>>15; + g_pit_cod = ((g_code * g_pitch) + 0x4000)>>15; + L_tmp = (g_code * g_code)<<1; + VO_L_Extract(L_tmp, &g2_code, &g2_code_lo); + + L_tmp = (coeff[2] * g2_code_lo)<<1; + L_tmp = (L_tmp >> 3); + L_tmp += (coeff_lo[0] * g2_pitch)<<1; + L_tmp += (coeff_lo[1] * g_pitch)<<1; + L_tmp += (coeff_lo[2] * g2_code)<<1; + L_tmp += (coeff_lo[3] * g_code)<<1; + L_tmp += (coeff_lo[4] * g_pit_cod)<<1; + L_tmp = (L_tmp >> 12); + L_tmp += (coeff[0] * g2_pitch)<<1; + L_tmp += (coeff[1] * g_pitch)<<1; + L_tmp += (coeff[2] * g2_code)<<1; + L_tmp += (coeff[3] * g_code)<<1; + L_tmp += (coeff[4] * g_pit_cod)<<1; + + if(L_tmp < dist_min) + { + dist_min = L_tmp; + index = i; + } + } + + /* Read the quantized gains */ + index = index + min_ind; + p = &t_qua_gain[(index + index)]; + *gain_pit = *p++; /* selected pitch gain in Q14 */ + g_code = *p++; /* selected code gain in Q11 */ + + L_tmp = vo_L_mult(g_code, gcode0); /* Q11*Q0 -> Q12 */ + L_tmp = L_shl(L_tmp, (exp_gcode0 + 4)); /* Q12 -> Q16 */ + + *gain_cod = L_tmp; /* gain of code in Q16 */ + + /*---------------------------------------------------* + * qua_ener = 20*log10(g_code) * + * = 6.0206*log2(g_code) * + * = 6.0206*(log2(g_codeQ11) - 11) * + *---------------------------------------------------*/ + + L_tmp = L_deposit_l(g_code); + Log2(L_tmp, &exp, &frac); + exp -= 11; + L_tmp = Mpy_32_16(exp, frac, 24660); /* x 6.0206 in Q12 */ + + qua_ener = (Word16)(L_tmp >> 3); /* result in Q10 */ + + /* update table of past quantized energies */ + + past_qua_en[3] = past_qua_en[2]; + past_qua_en[2] = past_qua_en[1]; + past_qua_en[1] = past_qua_en[0]; + past_qua_en[0] = qua_ener; + + return (index); +} + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/q_pulse.c b/media/libstagefright/codecs/amrwbenc/src/q_pulse.c new file mode 100644 index 0000000000000000000000000000000000000000..a28ba40cc0a1494abb9fa47c53cd0b194017d5b5 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/q_pulse.c @@ -0,0 +1,400 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: q_pulse.c * +* * +* Description: Coding and decoding of algebraic codebook * +* * +************************************************************************/ + +#include +#include "typedef.h" +#include "basic_op.h" +#include "q_pulse.h" + +#define NB_POS 16 /* pos in track, mask for sign bit */ + +Word32 quant_1p_N1( /* (o) return N+1 bits */ + Word16 pos, /* (i) position of the pulse */ + Word16 N) /* (i) number of bits for position */ +{ + Word16 mask; + Word32 index; + + mask = (1 << N) - 1; /* mask = ((1<> 1)), 1); + index = L_shl(quant_1p_N1(posA[0], n_1), tmp); + /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1); */ + index = vo_L_add(index, quant_3p_3N1(posB[0], posB[1], posB[2], n_1)); + break; + case 2: + tmp = ((n_1 << 1) + 1); /* index = quant_2p_2N1(posA[0], posA[1], n_1) << ((2*n_1)+1); */ + index = L_shl(quant_2p_2N1(posA[0], posA[1], n_1), tmp); + /* index += quant_2p_2N1(posB[0], posB[1], n_1); */ + index = vo_L_add(index, quant_2p_2N1(posB[0], posB[1], n_1)); + break; + case 3: + /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << N; */ + index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), N); + index = vo_L_add(index, quant_1p_N1(posB[0], n_1)); /* index += quant_1p_N1(posB[0], n_1); */ + break; + case 4: + index = quant_4p_4N1(posA[0], posA[1], posA[2], posA[3], n_1); + break; + default: + index = 0; + fprintf(stderr, "Error in function quant_4p_4N\n"); + } + tmp = ((N << 2) - 2); /* index += (i & 3) << ((4*N)-2); */ + index = vo_L_add(index, L_shl((L_deposit_l(i) & (3L)), tmp)); + + return (index); +} + + + +Word32 quant_5p_5N( /* (o) return 5*N bits */ + Word16 pos[], /* (i) position of the pulse 1..5 */ + Word16 N) /* (i) number of bits for position */ +{ + Word16 nb_pos, n_1, tmp; + Word16 posA[5], posB[5]; + Word32 i, j, k, index, tmp2; + + n_1 = (Word16) (N - 1); + nb_pos = (1 << n_1); /* nb_pos = (1<> 1)), 1); /* ((5*N)-1)) */ + index = L_shl(1L, tmp); /* index = 1 << ((5*N)-1); */ + tmp = add1((N << 1), 1); /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) << ((2*N)+1);*/ + tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp); + index = vo_L_add(index, tmp2); + index = vo_L_add(index, quant_2p_2N1(posB[3], posB[4], N)); /* index += quant_2p_2N1(posB[3], posB[4], N); */ + break; + case 1: + tmp = vo_sub((Word16)((vo_L_mult(5, N) >> 1)), 1); /* index = 1 << ((5*N)-1); */ + index = L_shl(1L, tmp); + tmp = add1((N << 1), 1); /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) <<((2*N)+1); */ + tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp); + index = vo_L_add(index, tmp2); + index = vo_L_add(index, quant_2p_2N1(posB[3], posA[0], N)); /* index += quant_2p_2N1(posB[3], posA[0], N); */ + break; + case 2: + tmp = vo_sub((Word16)((vo_L_mult(5, N) >> 1)), 1); /* ((5*N)-1)) */ + index = L_shl(1L, tmp); /* index = 1 << ((5*N)-1); */ + tmp = add1((N << 1), 1); /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) << ((2*N)+1); */ + tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp); + index = vo_L_add(index, tmp2); + index = vo_L_add(index, quant_2p_2N1(posA[0], posA[1], N)); /* index += quant_2p_2N1(posA[0], posA[1], N); */ + break; + case 3: + tmp = add1((N << 1), 1); /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1); */ + index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp); + index = vo_L_add(index, quant_2p_2N1(posB[0], posB[1], N)); /* index += quant_2p_2N1(posB[0], posB[1], N); */ + break; + case 4: + tmp = add1((N << 1), 1); /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1); */ + index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp); + index = vo_L_add(index, quant_2p_2N1(posA[3], posB[0], N)); /* index += quant_2p_2N1(posA[3], posB[0], N); */ + break; + case 5: + tmp = add1((N << 1), 1); /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1); */ + index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp); + index = vo_L_add(index, quant_2p_2N1(posA[3], posA[4], N)); /* index += quant_2p_2N1(posA[3], posA[4], N); */ + break; + default: + index = 0; + fprintf(stderr, "Error in function quant_5p_5N\n"); + } + + return (index); +} + + +Word32 quant_6p_6N_2( /* (o) return (6*N)-2 bits */ + Word16 pos[], /* (i) position of the pulse 1..6 */ + Word16 N) /* (i) number of bits for position */ +{ + Word16 nb_pos, n_1; + Word16 posA[6], posB[6]; + Word32 i, j, k, index; + + /* !! N and n_1 are constants -> it doesn't need to be operated by Basic Operators */ + n_1 = (Word16) (N - 1); + nb_pos = (1 << n_1); /* nb_pos = (1< 0; j--) + { + isf_buf[j * M + i] = isf_buf[(j - 1) * M + i]; + } + isf_buf[i] = isf_q[i]; + } + } + } else + { /* bad frame */ + for (i = 0; i < M; i++) + { + L_tmp = mean_isf[i] << 14; + for (j = 0; j < L_MEANBUF; j++) + { + L_tmp += (isf_buf[j * M + i] << 14); + } + ref_isf[i] = vo_round(L_tmp); + } + + /* use the past ISFs slightly shifted towards their mean */ + for (i = 0; i < ORDER; i++) + { + isf_q[i] = add1(vo_mult(ALPHA, isfold[i]), vo_mult(ONE_ALPHA, ref_isf[i])); + } + + /* estimate past quantized residual to be used in next frame */ + for (i = 0; i < ORDER; i++) + { + tmp = add1(ref_isf[i], vo_mult(past_isfq[i], MU)); /* predicted ISF */ + past_isfq[i] = vo_sub(isf_q[i], tmp); + past_isfq[i] = (past_isfq[i] >> 1); /* past_isfq[i] *= 0.5 */ + } + } + + Reorder_isf(isf_q, ISF_GAP, ORDER); + return; +} + +/********************************************************************* +* Function: Disf_2s_36b() * +* * +* Description: Decoding of ISF parameters * +*********************************************************************/ + +void Dpisf_2s_36b( + Word16 * indice, /* input: quantization indices */ + Word16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */ + Word16 * past_isfq, /* i/0 : past ISF quantizer */ + Word16 * isfold, /* input : past quantized ISF */ + Word16 * isf_buf, /* input : isf buffer */ + Word16 bfi, /* input : Bad frame indicator */ + Word16 enc_dec + ) +{ + Word16 ref_isf[M], tmp; + Word32 i, j, L_tmp; + + if (bfi == 0) /* Good frame */ + { + for (i = 0; i < 9; i++) + { + isf_q[i] = dico1_isf[indice[0] * 9 + i]; + } + for (i = 0; i < 7; i++) + { + isf_q[i + 9] = dico2_isf[indice[1] * 7 + i]; + } + + for (i = 0; i < 5; i++) + { + isf_q[i] = add1(isf_q[i], dico21_isf_36b[indice[2] * 5 + i]); + } + for (i = 0; i < 4; i++) + { + isf_q[i + 5] = add1(isf_q[i + 5], dico22_isf_36b[indice[3] * 4 + i]); + } + for (i = 0; i < 7; i++) + { + isf_q[i + 9] = add1(isf_q[i + 9], dico23_isf_36b[indice[4] * 7 + i]); + } + + for (i = 0; i < ORDER; i++) + { + tmp = isf_q[i]; + isf_q[i] = add1(tmp, mean_isf[i]); + isf_q[i] = add1(isf_q[i], vo_mult(MU, past_isfq[i])); + past_isfq[i] = tmp; + } + + + if (enc_dec) + { + for (i = 0; i < M; i++) + { + for (j = (L_MEANBUF - 1); j > 0; j--) + { + isf_buf[j * M + i] = isf_buf[(j - 1) * M + i]; + } + isf_buf[i] = isf_q[i]; + } + } + } else + { /* bad frame */ + for (i = 0; i < M; i++) + { + L_tmp = (mean_isf[i] << 14); + for (j = 0; j < L_MEANBUF; j++) + { + L_tmp += (isf_buf[j * M + i] << 14); + } + ref_isf[i] = vo_round(L_tmp); + } + + /* use the past ISFs slightly shifted towards their mean */ + for (i = 0; i < ORDER; i++) + { + isf_q[i] = add1(vo_mult(ALPHA, isfold[i]), vo_mult(ONE_ALPHA, ref_isf[i])); + } + + /* estimate past quantized residual to be used in next frame */ + for (i = 0; i < ORDER; i++) + { + tmp = add1(ref_isf[i], vo_mult(past_isfq[i], MU)); /* predicted ISF */ + past_isfq[i] = vo_sub(isf_q[i], tmp); + past_isfq[i] = past_isfq[i] >> 1; /* past_isfq[i] *= 0.5 */ + } + } + + Reorder_isf(isf_q, ISF_GAP, ORDER); + + return; +} + + +/*************************************************************************** +* Function: Reorder_isf() * +* * +* Description: To make sure that the isfs are properly order and to * +* keep a certain minimum distance between consecutive isfs. * +*--------------------------------------------------------------------------* +* Argument description in/out * +* * +* isf[] vector of isfs i/o * +* min_dist minimum required distance i * +* n LPC order i * +****************************************************************************/ + +void Reorder_isf( + Word16 * isf, /* (i/o) Q15: ISF in the frequency domain (0..0.5) */ + Word16 min_dist, /* (i) Q15 : minimum distance to keep */ + Word16 n /* (i) : number of ISF */ + ) +{ + Word32 i; + Word16 isf_min; + + isf_min = min_dist; + for (i = 0; i < n - 1; i++) + { + if(isf[i] < isf_min) + { + isf[i] = isf_min; + } + isf_min = (isf[i] + min_dist); + } + return; +} + + +Word16 Sub_VQ( /* output: return quantization index */ + Word16 * x, /* input : ISF residual vector */ + Word16 * dico, /* input : quantization codebook */ + Word16 dim, /* input : dimention of vector */ + Word16 dico_size, /* input : size of quantization codebook */ + Word32 * distance /* output: error of quantization */ + ) +{ + Word16 temp, *p_dico; + Word32 i, j, index; + Word32 dist_min, dist; + + dist_min = MAX_32; + p_dico = dico; + + index = 0; + for (i = 0; i < dico_size; i++) + { + dist = 0; + + for (j = 0; j < dim; j++) + { + temp = x[j] - (*p_dico++); + dist += (temp * temp)<<1; + } + + if(dist < dist_min) + { + dist_min = dist; + index = i; + } + } + + *distance = dist_min; + + /* Reading the selected vector */ + p_dico = &dico[index * dim]; + for (j = 0; j < dim; j++) + { + x[j] = *p_dico++; + } + + return index; +} + + +static void VQ_stage1( + Word16 * x, /* input : ISF residual vector */ + Word16 * dico, /* input : quantization codebook */ + Word16 dim, /* input : dimention of vector */ + Word16 dico_size, /* input : size of quantization codebook */ + Word16 * index, /* output: indices of survivors */ + Word16 surv /* input : number of survivor */ + ) +{ + Word16 temp, *p_dico; + Word32 i, j, k, l; + Word32 dist_min[N_SURV_MAX], dist; + + dist_min[0] = MAX_32; + dist_min[1] = MAX_32; + dist_min[2] = MAX_32; + dist_min[3] = MAX_32; + index[0] = 0; + index[1] = 1; + index[2] = 2; + index[3] = 3; + + p_dico = dico; + + for (i = 0; i < dico_size; i++) + { + dist = 0; + for (j = 0; j < dim; j++) + { + temp = x[j] - (*p_dico++); + dist += (temp * temp)<<1; + } + + for (k = 0; k < surv; k++) + { + if(dist < dist_min[k]) + { + for (l = surv - 1; l > k; l--) + { + dist_min[l] = dist_min[l - 1]; + index[l] = index[l - 1]; + } + dist_min[k] = dist; + index[k] = i; + break; + } + } + } + return; +} + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/random.c b/media/libstagefright/codecs/amrwbenc/src/random.c new file mode 100644 index 0000000000000000000000000000000000000000..8baa8bf27e7db7caa60829cd81ecdaa3078f37ba --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/random.c @@ -0,0 +1,33 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: random.c * +* * +* Description: Signed 16 bits random generator * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + +Word16 Random(Word16 * seed) +{ + /* static Word16 seed = 21845; */ + *seed = (Word16)(L_add((L_mult(*seed, 31821) >> 1), 13849L)); + return (*seed); +} + diff --git a/media/libstagefright/codecs/amrwbenc/src/residu.c b/media/libstagefright/codecs/amrwbenc/src/residu.c new file mode 100644 index 0000000000000000000000000000000000000000..68298829bbb3157ce56330736a5cd9b4a444ded8 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/residu.c @@ -0,0 +1,67 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: residu.c * +* * +* Description: Compute the LPC residual by filtering * +* the input speech through A(z) * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + +void Residu( + Word16 a[], /* (i) Q12 : prediction coefficients */ + Word16 x[], /* (i) : speech (values x[-m..-1] are needed */ + Word16 y[], /* (o) x2 : residual signal */ + Word16 lg /* (i) : size of filtering */ + ) +{ + Word16 i,*p1, *p2; + Word32 s; + for (i = 0; i < lg; i++) + { + p1 = a; + p2 = &x[i]; + s = vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1++), (*p2--)); + s += vo_mult32((*p1), (*p2)); + + s = L_shl2(s, 5); + y[i] = extract_h(L_add(s, 0x8000)); + } + + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/scale.c b/media/libstagefright/codecs/amrwbenc/src/scale.c new file mode 100644 index 0000000000000000000000000000000000000000..af40121b8fb2a1c495c5966c2214086eaff05215 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/scale.c @@ -0,0 +1,57 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: scale.c * +* * +* Description: Scale signal to get maximum of dynamic * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + +void Scale_sig( + Word16 x[], /* (i/o) : signal to scale */ + Word16 lg, /* (i) : size of x[] */ + Word16 exp /* (i) : exponent: x = round(x << exp) */ + ) +{ + Word32 i; + Word32 L_tmp; + if(exp > 0) + { + for (i = lg - 1 ; i >= 0; i--) + { + L_tmp = L_shl2(x[i], 16 + exp); + x[i] = extract_h(L_add(L_tmp, 0x8000)); + } + } + else + { + exp = -exp; + for (i = lg - 1; i >= 0; i--) + { + L_tmp = x[i] << 16; + L_tmp >>= exp; + x[i] = (L_tmp + 0x8000)>>16; + } + } + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/stream.c b/media/libstagefright/codecs/amrwbenc/src/stream.c new file mode 100644 index 0000000000000000000000000000000000000000..a7082358166f261be0406d7c42b9ae0452cff75e --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/stream.c @@ -0,0 +1,58 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: stream.c * +* * +* Description: VOME API Buffer Operator Implement Code * +* * +************************************************************************/ + +#include "stream.h" + +void voAWB_InitFrameBuffer(FrameStream *stream) +{ + stream->set_ptr = NULL; + stream->frame_ptr_bk = stream->frame_ptr; + stream->set_len = 0; + stream->framebuffer_len = 0; + stream->frame_storelen = 0; +} + +void voAWB_UpdateFrameBuffer( + FrameStream *stream, + VO_MEM_OPERATOR *pMemOP + ) +{ + int len; + len = MIN(Frame_Maxsize - stream->frame_storelen, stream->set_len); + pMemOP->Copy(VO_INDEX_ENC_AMRWB, stream->frame_ptr_bk + stream->frame_storelen , stream->set_ptr, len); + stream->set_len -= len; + stream->set_ptr += len; + stream->framebuffer_len = stream->frame_storelen + len; + stream->frame_ptr = stream->frame_ptr_bk; + stream->used_len += len; +} + +void voAWB_FlushFrameBuffer(FrameStream *stream) +{ + stream->set_ptr = NULL; + stream->frame_ptr_bk = stream->frame_ptr; + stream->set_len = 0; + stream->framebuffer_len = 0; + stream->frame_storelen = 0; +} + diff --git a/media/libstagefright/codecs/amrwbenc/src/syn_filt.c b/media/libstagefright/codecs/amrwbenc/src/syn_filt.c new file mode 100644 index 0000000000000000000000000000000000000000..6c1fb8e5fa7ade36add558deb5a2fa1dcdcd8ad2 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/syn_filt.c @@ -0,0 +1,160 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: syn_filt.c * +* * +* Description: Do the synthesis filtering 1/A(z) * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "math_op.h" +#include "cnst.h" + +void Syn_filt( + Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */ + Word16 x[], /* (i) : input signal */ + Word16 y[], /* (o) : output signal */ + Word16 lg, /* (i) : size of filtering */ + Word16 mem[], /* (i/o) : memory associated with this filtering. */ + Word16 update /* (i) : 0=no update, 1=update of memory. */ + ) +{ + Word32 i, a0; + Word16 y_buf[L_SUBFR16k + M16k]; + Word32 L_tmp; + Word16 *yy, *p1, *p2; + yy = &y_buf[0]; + /* copy initial filter states into synthesis buffer */ + for (i = 0; i < 16; i++) + { + *yy++ = mem[i]; + } + a0 = (a[0] >> 1); /* input / 2 */ + /* Do the filtering. */ + for (i = 0; i < lg; i++) + { + p1 = &a[1]; + p2 = &yy[i-1]; + L_tmp = vo_mult32(a0, x[i]); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1++), (*p2--)); + L_tmp -= vo_mult32((*p1), (*p2)); + + L_tmp = L_shl2(L_tmp, 4); + y[i] = yy[i] = extract_h(L_add(L_tmp, 0x8000)); + } + /* Update memory if required */ + if (update) + for (i = 0; i < 16; i++) + { + mem[i] = yy[lg - 16 + i]; + } + return; +} + + +void Syn_filt_32( + Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */ + Word16 m, /* (i) : order of LP filter */ + Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */ + Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */ + Word16 sig_hi[], /* (o) /16 : synthesis high */ + Word16 sig_lo[], /* (o) /16 : synthesis low */ + Word16 lg /* (i) : size of filtering */ + ) +{ + Word32 i,a0; + Word32 L_tmp, L_tmp1; + Word16 *p1, *p2, *p3; + a0 = a[0] >> (4 + Qnew); /* input / 16 and >>Qnew */ + /* Do the filtering. */ + for (i = 0; i < lg; i++) + { + L_tmp = 0; + L_tmp1 = 0; + p1 = a; + p2 = &sig_lo[i - 1]; + p3 = &sig_hi[i - 1]; + + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + L_tmp -= vo_mult32((*p2--), (*p1)); + L_tmp1 -= vo_mult32((*p3--), (*p1++)); + + L_tmp = L_tmp >> 11; + L_tmp += vo_L_mult(exc[i], a0); + + /* sig_hi = bit16 to bit31 of synthesis */ + L_tmp = L_tmp - (L_tmp1<<1); + + L_tmp = L_tmp >> 3; /* ai in Q12 */ + sig_hi[i] = extract_h(L_tmp); + + /* sig_lo = bit4 to bit15 of synthesis */ + L_tmp >>= 4; /* 4 : sig_lo[i] >> 4 */ + sig_lo[i] = (Word16)((L_tmp - (sig_hi[i] << 13))); + } + + return; +} + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/updt_tar.c b/media/libstagefright/codecs/amrwbenc/src/updt_tar.c new file mode 100644 index 0000000000000000000000000000000000000000..f3e56502cd44a186289d0004876f42487fb6f443 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/updt_tar.c @@ -0,0 +1,49 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: updt_tar.c * +* * +* Description: Update the target vector for codebook search * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + +void Updt_tar( + Word16 * x, /* (i) Q0 : old target (for pitch search) */ + Word16 * x2, /* (o) Q0 : new target (for codebook search) */ + Word16 * y, /* (i) Q0 : filtered adaptive codebook vector */ + Word16 gain, /* (i) Q14 : adaptive codebook gain */ + Word16 L /* (i) : subframe size */ + ) +{ + Word32 i; + Word32 L_tmp; + + for (i = 0; i < L; i++) + { + L_tmp = x[i] << 15; + L_tmp -= (y[i] * gain)<<1; + x2[i] = extract_h(L_shl2(L_tmp, 1)); + } + + return; +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/util.c b/media/libstagefright/codecs/amrwbenc/src/util.c new file mode 100644 index 0000000000000000000000000000000000000000..78141dd79c1946c0c391c93b82ba9239d9f59935 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/util.c @@ -0,0 +1,74 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: util.c * +* * +* Description: Reset and Copy buffer * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + +/*********************************************************************** +* Function: Set_zero() * +* Description: Set vector x[] to zero * +************************************************************************/ + +void Set_zero( + Word16 x[], /* (o) : vector to clear */ + Word16 L /* (i) : length of vector */ + ) +{ + Word32 num = (Word32)L; + do{ + *x++ = 0; + }while(--num !=0); +} + + +/********************************************************************* +* Function: Copy() * +* * +* Description: Copy vector x[] to y[] * +*********************************************************************/ + +void Copy( + Word16 x[], /* (i) : input vector */ + Word16 y[], /* (o) : output vector */ + Word16 L /* (i) : vector length */ + ) +{ + Word32 temp1,temp2,num; + if(L&1) + { + temp1 = *x++; + *y++ = temp1; + } + num = (Word32)(L>>1); + temp1 = *x++; + temp2 = *x++; + do{ + *y++ = temp1; + *y++ = temp2; + temp1 = *x++; + temp2 = *x++; + }while(--num!=0); +} + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c new file mode 100644 index 0000000000000000000000000000000000000000..d0d99a729bef48804cb0d31c35f1aa6162a4bfea --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c @@ -0,0 +1,1941 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: voAMRWBEnc.c * +* * +* Description: Performs the main encoder routine * +* Fixed-point C simulation of AMR WB ACELP coding * +* algorithm with 20 msspeech frames for * +* wideband speech signals. * +* * +************************************************************************/ + +#include +#include +#include "typedef.h" +#include "basic_op.h" +#include "oper_32b.h" +#include "math_op.h" +#include "cnst.h" +#include "acelp.h" +#include "cod_main.h" +#include "bits.h" +#include "main.h" +#include "voAMRWB.h" +#include "mem_align.h" +#include "cmnMemory.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */ +static Word16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767}; + +/* isp tables for initialization */ +static Word16 isp_init[M] = +{ + 32138, 30274, 27246, 23170, 18205, 12540, 6393, 0, + -6393, -12540, -18205, -23170, -27246, -30274, -32138, 1475 +}; + +static Word16 isf_init[M] = +{ + 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, + 9216, 10240, 11264, 12288, 13312, 14336, 15360, 3840 +}; + +/* High Band encoding */ +static const Word16 HP_gain[16] = +{ + 3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264, + 11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728 +}; + +/* Private function declaration */ +static Word16 synthesis( + Word16 Aq[], /* A(z) : quantized Az */ + Word16 exc[], /* (i) : excitation at 12kHz */ + Word16 Q_new, /* (i) : scaling performed on exc */ + Word16 synth16k[], /* (o) : 16kHz synthesis signal */ + Coder_State * st /* (i/o) : State structure */ + ); + +/* Codec some parameters initialization */ +void Reset_encoder(void *st, Word16 reset_all) +{ + Word16 i; + Coder_State *cod_state; + cod_state = (Coder_State *) st; + Set_zero(cod_state->old_exc, PIT_MAX + L_INTERPOL); + Set_zero(cod_state->mem_syn, M); + Set_zero(cod_state->past_isfq, M); + cod_state->mem_w0 = 0; + cod_state->tilt_code = 0; + cod_state->first_frame = 1; + Init_gp_clip(cod_state->gp_clip); + cod_state->L_gc_thres = 0; + if (reset_all != 0) + { + /* Static vectors to zero */ + Set_zero(cod_state->old_speech, L_TOTAL - L_FRAME); + Set_zero(cod_state->old_wsp, (PIT_MAX / OPL_DECIM)); + Set_zero(cod_state->mem_decim2, 3); + /* routines initialization */ + Init_Decim_12k8(cod_state->mem_decim); + Init_HP50_12k8(cod_state->mem_sig_in); + Init_Levinson(cod_state->mem_levinson); + Init_Q_gain2(cod_state->qua_gain); + Init_Hp_wsp(cod_state->hp_wsp_mem); + /* isp initialization */ + Copy(isp_init, cod_state->ispold, M); + Copy(isp_init, cod_state->ispold_q, M); + /* variable initialization */ + cod_state->mem_preemph = 0; + cod_state->mem_wsp = 0; + cod_state->Q_old = 15; + cod_state->Q_max[0] = 15; + cod_state->Q_max[1] = 15; + cod_state->old_wsp_max = 0; + cod_state->old_wsp_shift = 0; + /* pitch ol initialization */ + cod_state->old_T0_med = 40; + cod_state->ol_gain = 0; + cod_state->ada_w = 0; + cod_state->ol_wght_flg = 0; + for (i = 0; i < 5; i++) + { + cod_state->old_ol_lag[i] = 40; + } + Set_zero(cod_state->old_hp_wsp, (L_FRAME / 2) / OPL_DECIM + (PIT_MAX / OPL_DECIM)); + Set_zero(cod_state->mem_syn_hf, M); + Set_zero(cod_state->mem_syn_hi, M); + Set_zero(cod_state->mem_syn_lo, M); + Init_HP50_12k8(cod_state->mem_sig_out); + Init_Filt_6k_7k(cod_state->mem_hf); + Init_HP400_12k8(cod_state->mem_hp400); + Copy(isf_init, cod_state->isfold, M); + cod_state->mem_deemph = 0; + cod_state->seed2 = 21845; + Init_Filt_6k_7k(cod_state->mem_hf2); + cod_state->gain_alpha = 32767; + cod_state->vad_hist = 0; + wb_vad_reset(cod_state->vadSt); + dtx_enc_reset(cod_state->dtx_encSt, isf_init); + } + return; +} + +/*-----------------------------------------------------------------* +* Funtion coder * +* ~~~~~ * +* ->Main coder routine. * +* * +*-----------------------------------------------------------------*/ +void coder( + Word16 * mode, /* input : used mode */ + Word16 speech16k[], /* input : 320 new speech samples (at 16 kHz) */ + Word16 prms[], /* output: output parameters */ + Word16 * ser_size, /* output: bit rate of the used mode */ + void *spe_state, /* i/o : State structure */ + Word16 allow_dtx /* input : DTX ON/OFF */ + ) +{ + /* Coder states */ + Coder_State *st; + /* Speech vector */ + Word16 old_speech[L_TOTAL]; + Word16 *new_speech, *speech, *p_window; + + /* Weighted speech vector */ + Word16 old_wsp[L_FRAME + (PIT_MAX / OPL_DECIM)]; + Word16 *wsp; + + /* Excitation vector */ + Word16 old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL]; + Word16 *exc; + + /* LPC coefficients */ + Word16 r_h[M + 1], r_l[M + 1]; /* Autocorrelations of windowed speech */ + Word16 rc[M]; /* Reflection coefficients. */ + Word16 Ap[M + 1]; /* A(z) with spectral expansion */ + Word16 ispnew[M]; /* immittance spectral pairs at 4nd sfr */ + Word16 ispnew_q[M]; /* quantized ISPs at 4nd subframe */ + Word16 isf[M]; /* ISF (frequency domain) at 4nd sfr */ + Word16 *p_A, *p_Aq; /* ptr to A(z) for the 4 subframes */ + Word16 A[NB_SUBFR * (M + 1)]; /* A(z) unquantized for the 4 subframes */ + Word16 Aq[NB_SUBFR * (M + 1)]; /* A(z) quantized for the 4 subframes */ + + /* Other vectors */ + Word16 xn[L_SUBFR]; /* Target vector for pitch search */ + Word16 xn2[L_SUBFR]; /* Target vector for codebook search */ + Word16 dn[L_SUBFR]; /* Correlation between xn2 and h1 */ + Word16 cn[L_SUBFR]; /* Target vector in residual domain */ + Word16 h1[L_SUBFR]; /* Impulse response vector */ + Word16 h2[L_SUBFR]; /* Impulse response vector */ + Word16 code[L_SUBFR]; /* Fixed codebook excitation */ + Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 y2[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 error[M + L_SUBFR]; /* error of quantization */ + Word16 synth[L_SUBFR]; /* 12.8kHz synthesis vector */ + Word16 exc2[L_FRAME]; /* excitation vector */ + Word16 buf[L_FRAME]; /* VAD buffer */ + + /* Scalars */ + Word32 i, j, i_subfr, select, pit_flag, clip_gain, vad_flag; + Word16 codec_mode; + Word16 T_op, T_op2, T0, T0_min, T0_max, T0_frac, index; + Word16 gain_pit, gain_code, g_coeff[4], g_coeff2[4]; + Word16 tmp, gain1, gain2, exp, Q_new, mu, shift, max; + Word16 voice_fac; + Word16 indice[8]; + Word32 L_tmp, L_gain_code, L_max, L_tmp1; + Word16 code2[L_SUBFR]; /* Fixed codebook excitation */ + Word16 stab_fac, fac, gain_code_lo; + + Word16 corr_gain; + Word16 *vo_p0, *vo_p1, *vo_p2, *vo_p3; + + st = (Coder_State *) spe_state; + + *ser_size = nb_of_bits[*mode]; + codec_mode = *mode; + + /*--------------------------------------------------------------------------* + * Initialize pointers to speech vector. * + * * + * * + * |-------|-------|-------|-------|-------|-------| * + * past sp sf1 sf2 sf3 sf4 L_NEXT * + * <------- Total speech buffer (L_TOTAL) ------> * + * old_speech * + * <------- LPC analysis window (L_WINDOW) ------> * + * | <-- present frame (L_FRAME) ----> * + * p_window | <----- new speech (L_FRAME) ----> * + * | | * + * speech | * + * new_speech * + *--------------------------------------------------------------------------*/ + + new_speech = old_speech + L_TOTAL - L_FRAME - L_FILT; /* New speech */ + speech = old_speech + L_TOTAL - L_FRAME - L_NEXT; /* Present frame */ + p_window = old_speech + L_TOTAL - L_WINDOW; + + exc = old_exc + PIT_MAX + L_INTERPOL; + wsp = old_wsp + (PIT_MAX / OPL_DECIM); + + /* copy coder memory state into working space */ + Copy(st->old_speech, old_speech, L_TOTAL - L_FRAME); + Copy(st->old_wsp, old_wsp, PIT_MAX / OPL_DECIM); + Copy(st->old_exc, old_exc, PIT_MAX + L_INTERPOL); + + /*---------------------------------------------------------------* + * Down sampling signal from 16kHz to 12.8kHz * + * -> The signal is extended by L_FILT samples (padded to zero) * + * to avoid additional delay (L_FILT samples) in the coder. * + * The last L_FILT samples are approximated after decimation and * + * are used (and windowed) only in autocorrelations. * + *---------------------------------------------------------------*/ + + Decim_12k8(speech16k, L_FRAME16k, new_speech, st->mem_decim); + + /* last L_FILT samples for autocorrelation window */ + Copy(st->mem_decim, code, 2 * L_FILT16k); + Set_zero(error, L_FILT16k); /* set next sample to zero */ + Decim_12k8(error, L_FILT16k, new_speech + L_FRAME, code); + + /*---------------------------------------------------------------* + * Perform 50Hz HP filtering of input signal. * + *---------------------------------------------------------------*/ + + HP50_12k8(new_speech, L_FRAME, st->mem_sig_in); + + /* last L_FILT samples for autocorrelation window */ + Copy(st->mem_sig_in, code, 6); + HP50_12k8(new_speech + L_FRAME, L_FILT, code); + + /*---------------------------------------------------------------* + * Perform fixed preemphasis through 1 - g z^-1 * + * Scale signal to get maximum of precision in filtering * + *---------------------------------------------------------------*/ + + mu = PREEMPH_FAC >> 1; /* Q15 --> Q14 */ + + /* get max of new preemphased samples (L_FRAME+L_FILT) */ + L_tmp = new_speech[0] << 15; + L_tmp -= (st->mem_preemph * mu)<<1; + L_max = L_abs(L_tmp); + + for (i = 1; i < L_FRAME + L_FILT; i++) + { + L_tmp = new_speech[i] << 15; + L_tmp -= (new_speech[i - 1] * mu)<<1; + L_tmp = L_abs(L_tmp); + if(L_tmp > L_max) + { + L_max = L_tmp; + } + } + + /* get scaling factor for new and previous samples */ + /* limit scaling to Q_MAX to keep dynamic for ringing in low signal */ + /* limit scaling to Q_MAX also to avoid a[0]<1 in syn_filt_32 */ + tmp = extract_h(L_max); + if (tmp == 0) + { + shift = Q_MAX; + } else + { + shift = norm_s(tmp) - 1; + if (shift < 0) + { + shift = 0; + } + if (shift > Q_MAX) + { + shift = Q_MAX; + } + } + Q_new = shift; + if (Q_new > st->Q_max[0]) + { + Q_new = st->Q_max[0]; + } + if (Q_new > st->Q_max[1]) + { + Q_new = st->Q_max[1]; + } + exp = (Q_new - st->Q_old); + st->Q_old = Q_new; + st->Q_max[1] = st->Q_max[0]; + st->Q_max[0] = shift; + + /* preemphasis with scaling (L_FRAME+L_FILT) */ + tmp = new_speech[L_FRAME - 1]; + + for (i = L_FRAME + L_FILT - 1; i > 0; i--) + { + L_tmp = new_speech[i] << 15; + L_tmp -= (new_speech[i - 1] * mu)<<1; + L_tmp = (L_tmp << Q_new); + new_speech[i] = vo_round(L_tmp); + } + + L_tmp = new_speech[0] << 15; + L_tmp -= (st->mem_preemph * mu)<<1; + L_tmp = (L_tmp << Q_new); + new_speech[0] = vo_round(L_tmp); + + st->mem_preemph = tmp; + + /* scale previous samples and memory */ + + Scale_sig(old_speech, L_TOTAL - L_FRAME - L_FILT, exp); + Scale_sig(old_exc, PIT_MAX + L_INTERPOL, exp); + Scale_sig(st->mem_syn, M, exp); + Scale_sig(st->mem_decim2, 3, exp); + Scale_sig(&(st->mem_wsp), 1, exp); + Scale_sig(&(st->mem_w0), 1, exp); + + /*------------------------------------------------------------------------* + * Call VAD * + * Preemphesis scale down signal in low frequency and keep dynamic in HF.* + * Vad work slightly in futur (new_speech = speech + L_NEXT - L_FILT). * + *------------------------------------------------------------------------*/ + Copy(new_speech, buf, L_FRAME); + +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(buf, L_FRAME, 1 - Q_new); +#else + Scale_sig(buf, L_FRAME, 1 - Q_new); +#endif + + vad_flag = wb_vad(st->vadSt, buf); /* Voice Activity Detection */ + if (vad_flag == 0) + { + st->vad_hist = (st->vad_hist + 1); + } else + { + st->vad_hist = 0; + } + + /* DTX processing */ + if (allow_dtx != 0) + { + /* Note that mode may change here */ + tx_dtx_handler(st->dtx_encSt, vad_flag, mode); + *ser_size = nb_of_bits[*mode]; + } + + if(*mode != MRDTX) + { + Parm_serial(vad_flag, 1, &prms); + } + /*------------------------------------------------------------------------* + * Perform LPC analysis * + * ~~~~~~~~~~~~~~~~~~~~ * + * - autocorrelation + lag windowing * + * - Levinson-durbin algorithm to find a[] * + * - convert a[] to isp[] * + * - convert isp[] to isf[] for quantization * + * - quantize and code the isf[] * + * - convert isf[] to isp[] for interpolation * + * - find the interpolated ISPs and convert to a[] for the 4 subframes * + *------------------------------------------------------------------------*/ + + /* LP analysis centered at 4nd subframe */ + Autocorr(p_window, M, r_h, r_l); /* Autocorrelations */ + Lag_window(r_h, r_l); /* Lag windowing */ + Levinson(r_h, r_l, A, rc, st->mem_levinson); /* Levinson Durbin */ + Az_isp(A, ispnew, st->ispold); /* From A(z) to ISP */ + + /* Find the interpolated ISPs and convert to a[] for all subframes */ + Int_isp(st->ispold, ispnew, interpol_frac, A); + + /* update ispold[] for the next frame */ + Copy(ispnew, st->ispold, M); + + /* Convert ISPs to frequency domain 0..6400 */ + Isp_isf(ispnew, isf, M); + + /* check resonance for pitch clipping algorithm */ + Gp_clip_test_isf(isf, st->gp_clip); + + /*----------------------------------------------------------------------* + * Perform PITCH_OL analysis * + * ~~~~~~~~~~~~~~~~~~~~~~~~~ * + * - Find the residual res[] for the whole speech frame * + * - Find the weighted input speech wsp[] for the whole speech frame * + * - scale wsp[] to avoid overflow in pitch estimation * + * - Find open loop pitch lag for whole speech frame * + *----------------------------------------------------------------------*/ + p_A = A; + for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) + { + /* Weighting of LPC coefficients */ + Weight_a(p_A, Ap, GAMMA1, M); + +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR); +#else + Residu(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR); +#endif + + p_A += (M + 1); + } + + Deemph2(wsp, TILT_FAC, L_FRAME, &(st->mem_wsp)); + + /* find maximum value on wsp[] for 12 bits scaling */ + max = 0; + for (i = 0; i < L_FRAME; i++) + { + tmp = abs_s(wsp[i]); + if(tmp > max) + { + max = tmp; + } + } + tmp = st->old_wsp_max; + if(max > tmp) + { + tmp = max; /* tmp = max(wsp_max, old_wsp_max) */ + } + st->old_wsp_max = max; + + shift = norm_s(tmp) - 3; + if (shift > 0) + { + shift = 0; /* shift = 0..-3 */ + } + /* decimation of wsp[] to search pitch in LF and to reduce complexity */ + LP_Decim2(wsp, L_FRAME, st->mem_decim2); + + /* scale wsp[] in 12 bits to avoid overflow */ +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(wsp, L_FRAME / OPL_DECIM, shift); +#else + Scale_sig(wsp, L_FRAME / OPL_DECIM, shift); +#endif + /* scale old_wsp (warning: exp must be Q_new-Q_old) */ + exp = exp + (shift - st->old_wsp_shift); + st->old_wsp_shift = shift; + + Scale_sig(old_wsp, PIT_MAX / OPL_DECIM, exp); + Scale_sig(st->old_hp_wsp, PIT_MAX / OPL_DECIM, exp); + + scale_mem_Hp_wsp(st->hp_wsp_mem, exp); + + /* Find open loop pitch lag for whole speech frame */ + + if(*ser_size == NBBITS_7k) + { + /* Find open loop pitch lag for whole speech frame */ + T_op = Pitch_med_ol(wsp, st, L_FRAME / OPL_DECIM); + } else + { + /* Find open loop pitch lag for first 1/2 frame */ + T_op = Pitch_med_ol(wsp, st, (L_FRAME/2) / OPL_DECIM); + } + + if(st->ol_gain > 19661) /* 0.6 in Q15 */ + { + st->old_T0_med = Med_olag(T_op, st->old_ol_lag); + st->ada_w = 32767; + } else + { + st->ada_w = vo_mult(st->ada_w, 29491); + } + + if(st->ada_w < 26214) + st->ol_wght_flg = 0; + else + st->ol_wght_flg = 1; + + wb_vad_tone_detection(st->vadSt, st->ol_gain); + T_op *= OPL_DECIM; + + if(*ser_size != NBBITS_7k) + { + /* Find open loop pitch lag for second 1/2 frame */ + T_op2 = Pitch_med_ol(wsp + ((L_FRAME / 2) / OPL_DECIM), st, (L_FRAME/2) / OPL_DECIM); + + if(st->ol_gain > 19661) /* 0.6 in Q15 */ + { + st->old_T0_med = Med_olag(T_op2, st->old_ol_lag); + st->ada_w = 32767; + } else + { + st->ada_w = mult(st->ada_w, 29491); + } + + if(st->ada_w < 26214) + st->ol_wght_flg = 0; + else + st->ol_wght_flg = 1; + + wb_vad_tone_detection(st->vadSt, st->ol_gain); + + T_op2 *= OPL_DECIM; + + } else + { + T_op2 = T_op; + } + /*----------------------------------------------------------------------* + * DTX-CNG * + *----------------------------------------------------------------------*/ + if(*mode == MRDTX) /* CNG mode */ + { + /* Buffer isf's and energy */ +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(&A[3 * (M + 1)], speech, exc, L_FRAME); +#else + Residu(&A[3 * (M + 1)], speech, exc, L_FRAME); +#endif + + for (i = 0; i < L_FRAME; i++) + { + exc2[i] = shr(exc[i], Q_new); + } + + L_tmp = 0; + for (i = 0; i < L_FRAME; i++) + L_tmp += (exc2[i] * exc2[i])<<1; + + L_tmp >>= 1; + + dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode); + + /* Quantize and code the ISFs */ + dtx_enc(st->dtx_encSt, isf, exc2, &prms); + + /* Convert ISFs to the cosine domain */ + Isf_isp(isf, ispnew_q, M); + Isp_Az(ispnew_q, Aq, M, 0); + + for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) + { + corr_gain = synthesis(Aq, &exc2[i_subfr], 0, &speech16k[i_subfr * 5 / 4], st); + } + Copy(isf, st->isfold, M); + + /* reset speech coder memories */ + Reset_encoder(st, 0); + + /*--------------------------------------------------* + * Update signal for next frame. * + * -> save past of speech[] and wsp[]. * + *--------------------------------------------------*/ + + Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME); + Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM); + + return; + } + /*----------------------------------------------------------------------* + * ACELP * + *----------------------------------------------------------------------*/ + + /* Quantize and code the ISFs */ + + if (*ser_size <= NBBITS_7k) + { + Qpisf_2s_36b(isf, isf, st->past_isfq, indice, 4); + + Parm_serial(indice[0], 8, &prms); + Parm_serial(indice[1], 8, &prms); + Parm_serial(indice[2], 7, &prms); + Parm_serial(indice[3], 7, &prms); + Parm_serial(indice[4], 6, &prms); + } else + { + Qpisf_2s_46b(isf, isf, st->past_isfq, indice, 4); + + Parm_serial(indice[0], 8, &prms); + Parm_serial(indice[1], 8, &prms); + Parm_serial(indice[2], 6, &prms); + Parm_serial(indice[3], 7, &prms); + Parm_serial(indice[4], 7, &prms); + Parm_serial(indice[5], 5, &prms); + Parm_serial(indice[6], 5, &prms); + } + + /* Check stability on isf : distance between old isf and current isf */ + + L_tmp = 0; + for (i = 0; i < M - 1; i++) + { + tmp = vo_sub(isf[i], st->isfold[i]); + L_tmp += (tmp * tmp)<<1; + } + + tmp = extract_h(L_shl2(L_tmp, 8)); + + tmp = vo_mult(tmp, 26214); /* tmp = L_tmp*0.8/256 */ + tmp = vo_sub(20480, tmp); /* 1.25 - tmp (in Q14) */ + + stab_fac = shl(tmp, 1); + + if (stab_fac < 0) + { + stab_fac = 0; + } + Copy(isf, st->isfold, M); + + /* Convert ISFs to the cosine domain */ + Isf_isp(isf, ispnew_q, M); + + if (st->first_frame != 0) + { + st->first_frame = 0; + Copy(ispnew_q, st->ispold_q, M); + } + /* Find the interpolated ISPs and convert to a[] for all subframes */ + + Int_isp(st->ispold_q, ispnew_q, interpol_frac, Aq); + + /* update ispold[] for the next frame */ + Copy(ispnew_q, st->ispold_q, M); + + p_Aq = Aq; + for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) + { +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); +#else + Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); +#endif + p_Aq += (M + 1); + } + + /* Buffer isf's and energy for dtx on non-speech frame */ + if (vad_flag == 0) + { + for (i = 0; i < L_FRAME; i++) + { + exc2[i] = exc[i] >> Q_new; + } + L_tmp = 0; + for (i = 0; i < L_FRAME; i++) + L_tmp += (exc2[i] * exc2[i])<<1; + L_tmp >>= 1; + + dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode); + } + /* range for closed loop pitch search in 1st subframe */ + + T0_min = T_op - 8; + if (T0_min < PIT_MIN) + { + T0_min = PIT_MIN; + } + T0_max = (T0_min + 15); + + if(T0_max > PIT_MAX) + { + T0_max = PIT_MAX; + T0_min = T0_max - 15; + } + /*------------------------------------------------------------------------* + * Loop for every subframe in the analysis frame * + *------------------------------------------------------------------------* + * To find the pitch and innovation parameters. The subframe size is * + * L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times. * + * - compute the target signal for pitch search * + * - compute impulse response of weighted synthesis filter (h1[]) * + * - find the closed-loop pitch parameters * + * - encode the pitch dealy * + * - find 2 lt prediction (with / without LP filter for lt pred) * + * - find 2 pitch gains and choose the best lt prediction. * + * - find target vector for codebook search * + * - update the impulse response h1[] for codebook search * + * - correlation between target vector and impulse response * + * - codebook search and encoding * + * - VQ of pitch and codebook gains * + * - find voicing factor and tilt of code for next subframe. * + * - update states of weighting filter * + * - find excitation and synthesis speech * + *------------------------------------------------------------------------*/ + p_A = A; + p_Aq = Aq; + for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) + { + pit_flag = i_subfr; + if ((i_subfr == 2 * L_SUBFR) && (*ser_size > NBBITS_7k)) + { + pit_flag = 0; + /* range for closed loop pitch search in 3rd subframe */ + T0_min = (T_op2 - 8); + + if (T0_min < PIT_MIN) + { + T0_min = PIT_MIN; + } + T0_max = (T0_min + 15); + if (T0_max > PIT_MAX) + { + T0_max = PIT_MAX; + T0_min = (T0_max - 15); + } + } + /*-----------------------------------------------------------------------* + * * + * Find the target vector for pitch search: * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + * * + * |------| res[n] * + * speech[n]---| A(z) |-------- * + * |------| | |--------| error[n] |------| * + * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target * + * exc |--------| |------| * + * * + * Instead of subtracting the zero-input response of filters from * + * the weighted input speech, the above configuration is used to * + * compute the target vector. * + * * + *-----------------------------------------------------------------------*/ + + for (i = 0; i < M; i++) + { + error[i] = vo_sub(speech[i + i_subfr - M], st->mem_syn[i]); + } + +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); +#else + Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); +#endif + Syn_filt(p_Aq, &exc[i_subfr], error + M, L_SUBFR, error, 0); + Weight_a(p_A, Ap, GAMMA1, M); + +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(Ap, error + M, xn, L_SUBFR); +#else + Residu(Ap, error + M, xn, L_SUBFR); +#endif + Deemph2(xn, TILT_FAC, L_SUBFR, &(st->mem_w0)); + + /*----------------------------------------------------------------------* + * Find approx. target in residual domain "cn[]" for inovation search. * + *----------------------------------------------------------------------*/ + /* first half: xn[] --> cn[] */ + Set_zero(code, M); + Copy(xn, code + M, L_SUBFR / 2); + tmp = 0; + Preemph2(code + M, TILT_FAC, L_SUBFR / 2, &tmp); + Weight_a(p_A, Ap, GAMMA1, M); + Syn_filt(Ap,code + M, code + M, L_SUBFR / 2, code, 0); + +#ifdef ASM_OPT /* asm optimization branch */ + Residu_opt(p_Aq,code + M, cn, L_SUBFR / 2); +#else + Residu(p_Aq,code + M, cn, L_SUBFR / 2); +#endif + + /* second half: res[] --> cn[] (approximated and faster) */ + Copy(&exc[i_subfr + (L_SUBFR / 2)], cn + (L_SUBFR / 2), L_SUBFR / 2); + + /*---------------------------------------------------------------* + * Compute impulse response, h1[], of weighted synthesis filter * + *---------------------------------------------------------------*/ + + Set_zero(error, M + L_SUBFR); + Weight_a(p_A, error + M, GAMMA1, M); + + vo_p0 = error+M; + vo_p3 = h1; + for (i = 0; i < L_SUBFR; i++) + { + L_tmp = *vo_p0 << 14; /* x4 (Q12 to Q14) */ + vo_p1 = p_Aq + 1; + vo_p2 = vo_p0-1; + for (j = 1; j <= M/4; j++) + { + L_tmp -= *vo_p1++ * *vo_p2--; + L_tmp -= *vo_p1++ * *vo_p2--; + L_tmp -= *vo_p1++ * *vo_p2--; + L_tmp -= *vo_p1++ * *vo_p2--; + } + *vo_p3++ = *vo_p0++ = vo_round((L_tmp <<4)); + } + /* deemph without division by 2 -> Q14 to Q15 */ + tmp = 0; + Deemph2(h1, TILT_FAC, L_SUBFR, &tmp); /* h1 in Q14 */ + + /* h2 in Q12 for codebook search */ + Copy(h1, h2, L_SUBFR); + + /*---------------------------------------------------------------* + * scale xn[] and h1[] to avoid overflow in dot_product12() * + *---------------------------------------------------------------*/ +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(h2, L_SUBFR, -2); + Scale_sig_opt(xn, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig_opt(h1, L_SUBFR, 1 + shift); /* set h1[] in Q15 with scaling for convolution */ +#else + Scale_sig(h2, L_SUBFR, -2); + Scale_sig(xn, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig(h1, L_SUBFR, 1 + shift); /* set h1[] in Q15 with scaling for convolution */ +#endif + /*----------------------------------------------------------------------* + * Closed-loop fractional pitch search * + *----------------------------------------------------------------------*/ + /* find closed loop fractional pitch lag */ + if(*ser_size <= NBBITS_9k) + { + T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac, + pit_flag, PIT_MIN, PIT_FR1_8b, L_SUBFR); + + /* encode pitch lag */ + if (pit_flag == 0) /* if 1st/3rd subframe */ + { + /*--------------------------------------------------------------* + * The pitch range for the 1st/3rd subframe is encoded with * + * 8 bits and is divided as follows: * + * PIT_MIN to PIT_FR1-1 resolution 1/2 (frac = 0 or 2) * + * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) * + *--------------------------------------------------------------*/ + if (T0 < PIT_FR1_8b) + { + index = ((T0 << 1) + (T0_frac >> 1) - (PIT_MIN<<1)); + } else + { + index = ((T0 - PIT_FR1_8b) + ((PIT_FR1_8b - PIT_MIN)*2)); + } + + Parm_serial(index, 8, &prms); + + /* find T0_min and T0_max for subframe 2 and 4 */ + T0_min = (T0 - 8); + if (T0_min < PIT_MIN) + { + T0_min = PIT_MIN; + } + T0_max = T0_min + 15; + if (T0_max > PIT_MAX) + { + T0_max = PIT_MAX; + T0_min = (T0_max - 15); + } + } else + { /* if subframe 2 or 4 */ + /*--------------------------------------------------------------* + * The pitch range for subframe 2 or 4 is encoded with 5 bits: * + * T0_min to T0_max resolution 1/2 (frac = 0 or 2) * + *--------------------------------------------------------------*/ + i = (T0 - T0_min); + index = (i << 1) + (T0_frac >> 1); + + Parm_serial(index, 5, &prms); + } + } else + { + T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac, + pit_flag, PIT_FR2, PIT_FR1_9b, L_SUBFR); + + /* encode pitch lag */ + if (pit_flag == 0) /* if 1st/3rd subframe */ + { + /*--------------------------------------------------------------* + * The pitch range for the 1st/3rd subframe is encoded with * + * 9 bits and is divided as follows: * + * PIT_MIN to PIT_FR2-1 resolution 1/4 (frac = 0,1,2 or 3) * + * PIT_FR2 to PIT_FR1-1 resolution 1/2 (frac = 0 or 1) * + * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) * + *--------------------------------------------------------------*/ + + if (T0 < PIT_FR2) + { + index = ((T0 << 2) + T0_frac) - (PIT_MIN << 2); + } else if(T0 < PIT_FR1_9b) + { + index = ((((T0 << 1) + (T0_frac >> 1)) - (PIT_FR2<<1)) + ((PIT_FR2 - PIT_MIN)<<2)); + } else + { + index = (((T0 - PIT_FR1_9b) + ((PIT_FR2 - PIT_MIN)<<2)) + ((PIT_FR1_9b - PIT_FR2)<<1)); + } + + Parm_serial(index, 9, &prms); + + /* find T0_min and T0_max for subframe 2 and 4 */ + + T0_min = (T0 - 8); + if (T0_min < PIT_MIN) + { + T0_min = PIT_MIN; + } + T0_max = T0_min + 15; + + if (T0_max > PIT_MAX) + { + T0_max = PIT_MAX; + T0_min = (T0_max - 15); + } + } else + { /* if subframe 2 or 4 */ + /*--------------------------------------------------------------* + * The pitch range for subframe 2 or 4 is encoded with 6 bits: * + * T0_min to T0_max resolution 1/4 (frac = 0,1,2 or 3) * + *--------------------------------------------------------------*/ + i = (T0 - T0_min); + index = (i << 2) + T0_frac; + Parm_serial(index, 6, &prms); + } + } + + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure * + *-----------------------------------------------------------------*/ + + clip_gain = 0; + if((st->gp_clip[0] < 154) && (st->gp_clip[1] > 14746)) + clip_gain = 1; + + /*-----------------------------------------------------------------* + * - find unity gain pitch excitation (adaptive codebook entry) * + * with fractional interpolation. * + * - find filtered pitch exc. y1[]=exc[] convolved with h1[]) * + * - compute pitch gain1 * + *-----------------------------------------------------------------*/ + /* find pitch exitation */ +#ifdef ASM_OPT /* asm optimization branch */ + pred_lt4_asm(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1); +#else + Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1); +#endif + if (*ser_size > NBBITS_9k) + { +#ifdef ASM_OPT /* asm optimization branch */ + Convolve_asm(&exc[i_subfr], h1, y1, L_SUBFR); +#else + Convolve(&exc[i_subfr], h1, y1, L_SUBFR); +#endif + gain1 = G_pitch(xn, y1, g_coeff, L_SUBFR); + /* clip gain if necessary to avoid problem at decoder */ + if ((clip_gain != 0) && (gain1 > GP_CLIP)) + { + gain1 = GP_CLIP; + } + /* find energy of new target xn2[] */ + Updt_tar(xn, dn, y1, gain1, L_SUBFR); /* dn used temporary */ + } else + { + gain1 = 0; + } + /*-----------------------------------------------------------------* + * - find pitch excitation filtered by 1st order LP filter. * + * - find filtered pitch exc. y2[]=exc[] convolved with h1[]) * + * - compute pitch gain2 * + *-----------------------------------------------------------------*/ + /* find pitch excitation with lp filter */ + vo_p0 = exc + i_subfr-1; + vo_p1 = code; + /* find pitch excitation with lp filter */ + for (i = 0; i < L_SUBFR/2; i++) + { + L_tmp = 5898 * *vo_p0++; + L_tmp1 = 5898 * *vo_p0; + L_tmp += 20972 * *vo_p0++; + L_tmp1 += 20972 * *vo_p0++; + L_tmp1 += 5898 * *vo_p0--; + L_tmp += 5898 * *vo_p0; + *vo_p1++ = (L_tmp + 0x4000)>>15; + *vo_p1++ = (L_tmp1 + 0x4000)>>15; + } + +#ifdef ASM_OPT /* asm optimization branch */ + Convolve_asm(code, h1, y2, L_SUBFR); +#else + Convolve(code, h1, y2, L_SUBFR); +#endif + + gain2 = G_pitch(xn, y2, g_coeff2, L_SUBFR); + + /* clip gain if necessary to avoid problem at decoder */ + if ((clip_gain != 0) && (gain2 > GP_CLIP)) + { + gain2 = GP_CLIP; + } + /* find energy of new target xn2[] */ + Updt_tar(xn, xn2, y2, gain2, L_SUBFR); + /*-----------------------------------------------------------------* + * use the best prediction (minimise quadratic error). * + *-----------------------------------------------------------------*/ + select = 0; + if(*ser_size > NBBITS_9k) + { + L_tmp = 0L; + vo_p0 = dn; + vo_p1 = xn2; + for (i = 0; i < L_SUBFR/2; i++) + { + L_tmp += *vo_p0 * *vo_p0; + vo_p0++; + L_tmp -= *vo_p1 * *vo_p1; + vo_p1++; + L_tmp += *vo_p0 * *vo_p0; + vo_p0++; + L_tmp -= *vo_p1 * *vo_p1; + vo_p1++; + } + + if (L_tmp <= 0) + { + select = 1; + } + Parm_serial(select, 1, &prms); + } + if (select == 0) + { + /* use the lp filter for pitch excitation prediction */ + gain_pit = gain2; + Copy(code, &exc[i_subfr], L_SUBFR); + Copy(y2, y1, L_SUBFR); + Copy(g_coeff2, g_coeff, 4); + } else + { + /* no filter used for pitch excitation prediction */ + gain_pit = gain1; + Copy(dn, xn2, L_SUBFR); /* target vector for codebook search */ + } + /*-----------------------------------------------------------------* + * - update cn[] for codebook search * + *-----------------------------------------------------------------*/ + Updt_tar(cn, cn, &exc[i_subfr], gain_pit, L_SUBFR); + +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(cn, L_SUBFR, shift); /* scaling of cn[] to limit dynamic at 12 bits */ +#else + Scale_sig(cn, L_SUBFR, shift); /* scaling of cn[] to limit dynamic at 12 bits */ +#endif + /*-----------------------------------------------------------------* + * - include fixed-gain pitch contribution into impulse resp. h1[] * + *-----------------------------------------------------------------*/ + tmp = 0; + Preemph(h2, st->tilt_code, L_SUBFR, &tmp); + + if (T0_frac > 2) + T0 = (T0 + 1); + Pit_shrp(h2, T0, PIT_SHARP, L_SUBFR); + /*-----------------------------------------------------------------* + * - Correlation between target xn2[] and impulse response h1[] * + * - Innovative codebook search * + *-----------------------------------------------------------------*/ + cor_h_x(h2, xn2, dn); + if (*ser_size <= NBBITS_7k) + { + ACELP_2t64_fx(dn, cn, h2, code, y2, indice); + + Parm_serial(indice[0], 12, &prms); + } else if(*ser_size <= NBBITS_9k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 20, *ser_size, indice); + + Parm_serial(indice[0], 5, &prms); + Parm_serial(indice[1], 5, &prms); + Parm_serial(indice[2], 5, &prms); + Parm_serial(indice[3], 5, &prms); + } else if(*ser_size <= NBBITS_12k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 36, *ser_size, indice); + + Parm_serial(indice[0], 9, &prms); + Parm_serial(indice[1], 9, &prms); + Parm_serial(indice[2], 9, &prms); + Parm_serial(indice[3], 9, &prms); + } else if(*ser_size <= NBBITS_14k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 44, *ser_size, indice); + + Parm_serial(indice[0], 13, &prms); + Parm_serial(indice[1], 13, &prms); + Parm_serial(indice[2], 9, &prms); + Parm_serial(indice[3], 9, &prms); + } else if(*ser_size <= NBBITS_16k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 52, *ser_size, indice); + + Parm_serial(indice[0], 13, &prms); + Parm_serial(indice[1], 13, &prms); + Parm_serial(indice[2], 13, &prms); + Parm_serial(indice[3], 13, &prms); + } else if(*ser_size <= NBBITS_18k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 64, *ser_size, indice); + + Parm_serial(indice[0], 2, &prms); + Parm_serial(indice[1], 2, &prms); + Parm_serial(indice[2], 2, &prms); + Parm_serial(indice[3], 2, &prms); + Parm_serial(indice[4], 14, &prms); + Parm_serial(indice[5], 14, &prms); + Parm_serial(indice[6], 14, &prms); + Parm_serial(indice[7], 14, &prms); + } else if(*ser_size <= NBBITS_20k) + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 72, *ser_size, indice); + + Parm_serial(indice[0], 10, &prms); + Parm_serial(indice[1], 10, &prms); + Parm_serial(indice[2], 2, &prms); + Parm_serial(indice[3], 2, &prms); + Parm_serial(indice[4], 10, &prms); + Parm_serial(indice[5], 10, &prms); + Parm_serial(indice[6], 14, &prms); + Parm_serial(indice[7], 14, &prms); + } else + { + ACELP_4t64_fx(dn, cn, h2, code, y2, 88, *ser_size, indice); + + Parm_serial(indice[0], 11, &prms); + Parm_serial(indice[1], 11, &prms); + Parm_serial(indice[2], 11, &prms); + Parm_serial(indice[3], 11, &prms); + Parm_serial(indice[4], 11, &prms); + Parm_serial(indice[5], 11, &prms); + Parm_serial(indice[6], 11, &prms); + Parm_serial(indice[7], 11, &prms); + } + /*-------------------------------------------------------* + * - Add the fixed-gain pitch contribution to code[]. * + *-------------------------------------------------------*/ + tmp = 0; + Preemph(code, st->tilt_code, L_SUBFR, &tmp); + Pit_shrp(code, T0, PIT_SHARP, L_SUBFR); + /*----------------------------------------------------------* + * - Compute the fixed codebook gain * + * - quantize fixed codebook gain * + *----------------------------------------------------------*/ + if(*ser_size <= NBBITS_9k) + { + index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 6, + &gain_pit, &L_gain_code, clip_gain, st->qua_gain); + Parm_serial(index, 6, &prms); + } else + { + index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 7, + &gain_pit, &L_gain_code, clip_gain, st->qua_gain); + Parm_serial(index, 7, &prms); + } + /* test quantized gain of pitch for pitch clipping algorithm */ + Gp_clip_test_gain_pit(gain_pit, st->gp_clip); + + L_tmp = L_shl(L_gain_code, Q_new); + gain_code = extract_h(L_add(L_tmp, 0x8000)); + + /*----------------------------------------------------------* + * Update parameters for the next subframe. * + * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced) * + *----------------------------------------------------------*/ + /* find voice factor in Q15 (1=voiced, -1=unvoiced) */ + Copy(&exc[i_subfr], exc2, L_SUBFR); + +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(exc2, L_SUBFR, shift); +#else + Scale_sig(exc2, L_SUBFR, shift); +#endif + voice_fac = voice_factor(exc2, shift, gain_pit, code, gain_code, L_SUBFR); + /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */ + st->tilt_code = ((voice_fac >> 2) + 8192); + /*------------------------------------------------------* + * - Update filter's memory "mem_w0" for finding the * + * target vector in the next subframe. * + * - Find the total excitation * + * - Find synthesis speech to update mem_syn[]. * + *------------------------------------------------------*/ + + /* y2 in Q9, gain_pit in Q14 */ + L_tmp = (gain_code * y2[L_SUBFR - 1])<<1; + L_tmp = L_shl(L_tmp, (5 + shift)); + L_tmp = L_negate(L_tmp); + L_tmp += (xn[L_SUBFR - 1] * 16384)<<1; + L_tmp -= (y1[L_SUBFR - 1] * gain_pit)<<1; + L_tmp = L_shl(L_tmp, (1 - shift)); + st->mem_w0 = extract_h(L_add(L_tmp, 0x8000)); + + if (*ser_size >= NBBITS_24k) + Copy(&exc[i_subfr], exc2, L_SUBFR); + + for (i = 0; i < L_SUBFR; i++) + { + /* code in Q9, gain_pit in Q14 */ + L_tmp = (gain_code * code[i])<<1; + L_tmp = (L_tmp << 5); + L_tmp += (exc[i + i_subfr] * gain_pit)<<1; + L_tmp = L_shl2(L_tmp, 1); + exc[i + i_subfr] = extract_h(L_add(L_tmp, 0x8000)); + } + + Syn_filt(p_Aq,&exc[i_subfr], synth, L_SUBFR, st->mem_syn, 1); + + if(*ser_size >= NBBITS_24k) + { + /*------------------------------------------------------------* + * phase dispersion to enhance noise in low bit rate * + *------------------------------------------------------------*/ + /* L_gain_code in Q16 */ + VO_L_Extract(L_gain_code, &gain_code, &gain_code_lo); + + /*------------------------------------------------------------* + * noise enhancer * + * ~~~~~~~~~~~~~~ * + * - Enhance excitation on noise. (modify gain of code) * + * If signal is noisy and LPC filter is stable, move gain * + * of code 1.5 dB toward gain of code threshold. * + * This decrease by 3 dB noise energy variation. * + *------------------------------------------------------------*/ + tmp = (16384 - (voice_fac >> 1)); /* 1=unvoiced, 0=voiced */ + fac = vo_mult(stab_fac, tmp); + L_tmp = L_gain_code; + if(L_tmp < st->L_gc_thres) + { + L_tmp = vo_L_add(L_tmp, Mpy_32_16(gain_code, gain_code_lo, 6226)); + if(L_tmp > st->L_gc_thres) + { + L_tmp = st->L_gc_thres; + } + } else + { + L_tmp = Mpy_32_16(gain_code, gain_code_lo, 27536); + if(L_tmp < st->L_gc_thres) + { + L_tmp = st->L_gc_thres; + } + } + st->L_gc_thres = L_tmp; + + L_gain_code = Mpy_32_16(gain_code, gain_code_lo, (32767 - fac)); + VO_L_Extract(L_tmp, &gain_code, &gain_code_lo); + L_gain_code = vo_L_add(L_gain_code, Mpy_32_16(gain_code, gain_code_lo, fac)); + + /*------------------------------------------------------------* + * pitch enhancer * + * ~~~~~~~~~~~~~~ * + * - Enhance excitation on voice. (HP filtering of code) * + * On voiced signal, filtering of code by a smooth fir HP * + * filter to decrease energy of code in low frequency. * + *------------------------------------------------------------*/ + + tmp = ((voice_fac >> 3) + 4096); /* 0.25=voiced, 0=unvoiced */ + + L_tmp = L_deposit_h(code[0]); + L_tmp -= (code[1] * tmp)<<1; + code2[0] = vo_round(L_tmp); + + for (i = 1; i < L_SUBFR - 1; i++) + { + L_tmp = L_deposit_h(code[i]); + L_tmp -= (code[i + 1] * tmp)<<1; + L_tmp -= (code[i - 1] * tmp)<<1; + code2[i] = vo_round(L_tmp); + } + + L_tmp = L_deposit_h(code[L_SUBFR - 1]); + L_tmp -= (code[L_SUBFR - 2] * tmp)<<1; + code2[L_SUBFR - 1] = vo_round(L_tmp); + + /* build excitation */ + gain_code = vo_round(L_shl(L_gain_code, Q_new)); + + for (i = 0; i < L_SUBFR; i++) + { + L_tmp = (code2[i] * gain_code)<<1; + L_tmp = (L_tmp << 5); + L_tmp += (exc2[i] * gain_pit)<<1; + L_tmp = (L_tmp << 1); + exc2[i] = vo_round(L_tmp); + } + + corr_gain = synthesis(p_Aq, exc2, Q_new, &speech16k[i_subfr * 5 / 4], st); + Parm_serial(corr_gain, 4, &prms); + } + p_A += (M + 1); + p_Aq += (M + 1); + } /* end of subframe loop */ + + /*--------------------------------------------------* + * Update signal for next frame. * + * -> save past of speech[], wsp[] and exc[]. * + *--------------------------------------------------*/ + Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME); + Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM); + Copy(&old_exc[L_FRAME], st->old_exc, PIT_MAX + L_INTERPOL); + return; +} + +/*-----------------------------------------------------* +* Function synthesis() * +* * +* Synthesis of signal at 16kHz with HF extension. * +* * +*-----------------------------------------------------*/ + +static Word16 synthesis( + Word16 Aq[], /* A(z) : quantized Az */ + Word16 exc[], /* (i) : excitation at 12kHz */ + Word16 Q_new, /* (i) : scaling performed on exc */ + Word16 synth16k[], /* (o) : 16kHz synthesis signal */ + Coder_State * st /* (i/o) : State structure */ + ) +{ + Word16 fac, tmp, exp; + Word16 ener, exp_ener; + Word32 L_tmp, i; + + Word16 synth_hi[M + L_SUBFR], synth_lo[M + L_SUBFR]; + Word16 synth[L_SUBFR]; + Word16 HF[L_SUBFR16k]; /* High Frequency vector */ + Word16 Ap[M + 1]; + + Word16 HF_SP[L_SUBFR16k]; /* High Frequency vector (from original signal) */ + + Word16 HP_est_gain, HP_calc_gain, HP_corr_gain; + Word16 dist_min, dist; + Word16 HP_gain_ind = 0; + Word16 gain1, gain2; + Word16 weight1, weight2; + + /*------------------------------------------------------------* + * speech synthesis * + * ~~~~~~~~~~~~~~~~ * + * - Find synthesis speech corresponding to exc2[]. * + * - Perform fixed deemphasis and hp 50hz filtering. * + * - Oversampling from 12.8kHz to 16kHz. * + *------------------------------------------------------------*/ + Copy(st->mem_syn_hi, synth_hi, M); + Copy(st->mem_syn_lo, synth_lo, M); + +#ifdef ASM_OPT /* asm optimization branch */ + Syn_filt_32_asm(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR); +#else + Syn_filt_32(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR); +#endif + + Copy(synth_hi + L_SUBFR, st->mem_syn_hi, M); + Copy(synth_lo + L_SUBFR, st->mem_syn_lo, M); + +#ifdef ASM_OPT /* asm optimization branch */ + Deemph_32_asm(synth_hi + M, synth_lo + M, synth, &(st->mem_deemph)); +#else + Deemph_32(synth_hi + M, synth_lo + M, synth, PREEMPH_FAC, L_SUBFR, &(st->mem_deemph)); +#endif + + HP50_12k8(synth, L_SUBFR, st->mem_sig_out); + + /* Original speech signal as reference for high band gain quantisation */ + for (i = 0; i < L_SUBFR16k; i++) + { + HF_SP[i] = synth16k[i]; + } + + /*------------------------------------------------------* + * HF noise synthesis * + * ~~~~~~~~~~~~~~~~~~ * + * - Generate HF noise between 5.5 and 7.5 kHz. * + * - Set energy of noise according to synthesis tilt. * + * tilt > 0.8 ==> - 14 dB (voiced) * + * tilt 0.5 ==> - 6 dB (voiced or noise) * + * tilt < 0.0 ==> 0 dB (noise) * + *------------------------------------------------------*/ + /* generate white noise vector */ + for (i = 0; i < L_SUBFR16k; i++) + { + HF[i] = Random(&(st->seed2))>>3; + } + /* energy of excitation */ +#ifdef ASM_OPT /* asm optimization branch */ + Scale_sig_opt(exc, L_SUBFR, -3); + Q_new = Q_new - 3; + ener = extract_h(Dot_product12_asm(exc, exc, L_SUBFR, &exp_ener)); +#else + Scale_sig(exc, L_SUBFR, -3); + Q_new = Q_new - 3; + ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp_ener)); +#endif + + exp_ener = exp_ener - (Q_new + Q_new); + /* set energy of white noise to energy of excitation */ +#ifdef ASM_OPT /* asm optimization branch */ + tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp)); +#else + tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp)); +#endif + + if(tmp > ener) + { + tmp = (tmp >> 1); /* Be sure tmp < ener */ + exp = (exp + 1); + } + L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */ + exp = (exp - exp_ener); + Isqrt_n(&L_tmp, &exp); + L_tmp = L_shl(L_tmp, (exp + 1)); /* L_tmp x 2, L_tmp in Q31 */ + tmp = extract_h(L_tmp); /* tmp = 2 x sqrt(ener_exc/ener_hf) */ + + for (i = 0; i < L_SUBFR16k; i++) + { + HF[i] = vo_mult(HF[i], tmp); + } + + /* find tilt of synthesis speech (tilt: 1=voiced, -1=unvoiced) */ + HP400_12k8(synth, L_SUBFR, st->mem_hp400); + + L_tmp = 1L; + for (i = 0; i < L_SUBFR; i++) + L_tmp += (synth[i] * synth[i])<<1; + + exp = norm_l(L_tmp); + ener = extract_h(L_tmp << exp); /* ener = r[0] */ + + L_tmp = 1L; + for (i = 1; i < L_SUBFR; i++) + L_tmp +=(synth[i] * synth[i - 1])<<1; + + tmp = extract_h(L_tmp << exp); /* tmp = r[1] */ + + if (tmp > 0) + { + fac = div_s(tmp, ener); + } else + { + fac = 0; + } + + /* modify energy of white noise according to synthesis tilt */ + gain1 = 32767 - fac; + gain2 = vo_mult(gain1, 20480); + gain2 = shl(gain2, 1); + + if (st->vad_hist > 0) + { + weight1 = 0; + weight2 = 32767; + } else + { + weight1 = 32767; + weight2 = 0; + } + tmp = vo_mult(weight1, gain1); + tmp = add1(tmp, vo_mult(weight2, gain2)); + + if (tmp != 0) + { + tmp = (tmp + 1); + } + HP_est_gain = tmp; + + if(HP_est_gain < 3277) + { + HP_est_gain = 3277; /* 0.1 in Q15 */ + } + /* synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz */ + Weight_a(Aq, Ap, 19661, M); /* fac=0.6 */ + +#ifdef ASM_OPT /* asm optimization branch */ + Syn_filt_asm(Ap, HF, HF, st->mem_syn_hf); + /* noise High Pass filtering (1ms of delay) */ + Filt_6k_7k_asm(HF, L_SUBFR16k, st->mem_hf); + /* filtering of the original signal */ + Filt_6k_7k_asm(HF_SP, L_SUBFR16k, st->mem_hf2); + + /* check the gain difference */ + Scale_sig_opt(HF_SP, L_SUBFR16k, -1); + ener = extract_h(Dot_product12_asm(HF_SP, HF_SP, L_SUBFR16k, &exp_ener)); + /* set energy of white noise to energy of excitation */ + tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp)); +#else + Syn_filt(Ap, HF, HF, L_SUBFR16k, st->mem_syn_hf, 1); + /* noise High Pass filtering (1ms of delay) */ + Filt_6k_7k(HF, L_SUBFR16k, st->mem_hf); + /* filtering of the original signal */ + Filt_6k_7k(HF_SP, L_SUBFR16k, st->mem_hf2); + /* check the gain difference */ + Scale_sig(HF_SP, L_SUBFR16k, -1); + ener = extract_h(Dot_product12(HF_SP, HF_SP, L_SUBFR16k, &exp_ener)); + /* set energy of white noise to energy of excitation */ + tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp)); +#endif + + if (tmp > ener) + { + tmp = (tmp >> 1); /* Be sure tmp < ener */ + exp = (exp + 1); + } + L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */ + exp = vo_sub(exp, exp_ener); + Isqrt_n(&L_tmp, &exp); + L_tmp = L_shl(L_tmp, exp); /* L_tmp, L_tmp in Q31 */ + HP_calc_gain = extract_h(L_tmp); /* tmp = sqrt(ener_input/ener_hf) */ + + /* st->gain_alpha *= st->dtx_encSt->dtxHangoverCount/7 */ + L_tmp = (vo_L_mult(st->dtx_encSt->dtxHangoverCount, 4681) << 15); + st->gain_alpha = vo_mult(st->gain_alpha, extract_h(L_tmp)); + + if(st->dtx_encSt->dtxHangoverCount > 6) + st->gain_alpha = 32767; + HP_est_gain = HP_est_gain >> 1; /* From Q15 to Q14 */ + HP_corr_gain = add1(vo_mult(HP_calc_gain, st->gain_alpha), vo_mult((32767 - st->gain_alpha), HP_est_gain)); + + /* Quantise the correction gain */ + dist_min = 32767; + for (i = 0; i < 16; i++) + { + dist = vo_mult((HP_corr_gain - HP_gain[i]), (HP_corr_gain - HP_gain[i])); + if (dist_min > dist) + { + dist_min = dist; + HP_gain_ind = i; + } + } + HP_corr_gain = HP_gain[HP_gain_ind]; + /* return the quantised gain index when using the highest mode, otherwise zero */ + return (HP_gain_ind); +} + +/************************************************* +* +* Breif: Codec main function +* +**************************************************/ + +int AMR_Enc_Encode(HAMRENC hCodec) +{ + Word32 i; + Coder_State *gData = (Coder_State*)hCodec; + Word16 *signal; + Word16 packed_size = 0; + Word16 prms[NB_BITS_MAX]; + Word16 coding_mode = 0, nb_bits, allow_dtx, mode, reset_flag; + mode = gData->mode; + coding_mode = gData->mode; + nb_bits = nb_of_bits[mode]; + signal = (Word16 *)gData->inputStream; + allow_dtx = gData->allow_dtx; + + /* check for homing frame */ + reset_flag = encoder_homing_frame_test(signal); + + for (i = 0; i < L_FRAME16k; i++) /* Delete the 2 LSBs (14-bit input) */ + { + *(signal + i) = (Word16) (*(signal + i) & 0xfffC); + } + + coder(&coding_mode, signal, prms, &nb_bits, gData, allow_dtx); + packed_size = PackBits(prms, coding_mode, mode, gData); + if (reset_flag != 0) + { + Reset_encoder(gData, 1); + } + return packed_size; +} + +/*************************************************************************** +* +*Brief: Codec API function --- Initialize the codec and return a codec handle +* +***************************************************************************/ + +VO_U32 VO_API voAMRWB_Init(VO_HANDLE * phCodec, /* o: the audio codec handle */ + VO_AUDIO_CODINGTYPE vType, /* i: Codec Type ID */ + VO_CODEC_INIT_USERDATA * pUserData /* i: init Parameters */ + ) +{ + Coder_State *st; + FrameStream *stream; +#ifdef USE_DEAULT_MEM + VO_MEM_OPERATOR voMemoprator; +#endif + VO_MEM_OPERATOR *pMemOP; + int interMem = 0; + + if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL ) + { +#ifdef USE_DEAULT_MEM + voMemoprator.Alloc = cmnMemAlloc; + voMemoprator.Copy = cmnMemCopy; + voMemoprator.Free = cmnMemFree; + voMemoprator.Set = cmnMemSet; + voMemoprator.Check = cmnMemCheck; + interMem = 1; + pMemOP = &voMemoprator; +#else + *phCodec = NULL; + return VO_ERR_INVALID_ARG; +#endif + } + else + { + pMemOP = (VO_MEM_OPERATOR *)pUserData->memData; + } + /*-------------------------------------------------------------------------* + * Memory allocation for coder state. * + *-------------------------------------------------------------------------*/ + if ((st = (Coder_State *)mem_malloc(pMemOP, sizeof(Coder_State), 32, VO_INDEX_ENC_AMRWB)) == NULL) + { + return VO_ERR_OUTOF_MEMORY; + } + + st->vadSt = NULL; + st->dtx_encSt = NULL; + st->sid_update_counter = 3; + st->sid_handover_debt = 0; + st->prev_ft = TX_SPEECH; + st->inputStream = NULL; + st->inputSize = 0; + + /* Default setting */ + st->mode = VOAMRWB_MD2385; /* bit rate 23.85kbps */ + st->frameType = VOAMRWB_RFC3267; /* frame type: RFC3267 */ + st->allow_dtx = 0; /* disable DTX mode */ + + st->outputStream = NULL; + st->outputSize = 0; + + st->stream = (FrameStream *)mem_malloc(pMemOP, sizeof(FrameStream), 32, VO_INDEX_ENC_AMRWB); + if(st->stream == NULL) + return VO_ERR_OUTOF_MEMORY; + + st->stream->frame_ptr = (unsigned char *)mem_malloc(pMemOP, Frame_Maxsize, 32, VO_INDEX_ENC_AMRWB); + if(st->stream->frame_ptr == NULL) + return VO_ERR_OUTOF_MEMORY; + + stream = st->stream; + voAWB_InitFrameBuffer(stream); + + wb_vad_init(&(st->vadSt), pMemOP); + dtx_enc_init(&(st->dtx_encSt), isf_init, pMemOP); + + Reset_encoder((void *) st, 1); + + if(interMem) + { + st->voMemoprator.Alloc = cmnMemAlloc; + st->voMemoprator.Copy = cmnMemCopy; + st->voMemoprator.Free = cmnMemFree; + st->voMemoprator.Set = cmnMemSet; + st->voMemoprator.Check = cmnMemCheck; + pMemOP = &st->voMemoprator; + } + + st->pvoMemop = pMemOP; + + *phCodec = (void *) st; + + return VO_ERR_NONE; +} + +/********************************************************************************** +* +* Brief: Codec API function: Input PCM data +* +***********************************************************************************/ + +VO_U32 VO_API voAMRWB_SetInputData( + VO_HANDLE hCodec, /* i/o: The codec handle which was created by Init function */ + VO_CODECBUFFER * pInput /* i: The input buffer parameter */ + ) +{ + Coder_State *gData; + FrameStream *stream; + + if(NULL == hCodec) + { + return VO_ERR_INVALID_ARG; + } + + gData = (Coder_State *)hCodec; + stream = gData->stream; + + if(NULL == pInput || NULL == pInput->Buffer || 0 > pInput->Length) + { + return VO_ERR_INVALID_ARG; + } + + stream->set_ptr = pInput->Buffer; + stream->set_len = pInput->Length; + stream->frame_ptr = stream->frame_ptr_bk; + stream->used_len = 0; + + return VO_ERR_NONE; +} + +/************************************************************************************** +* +* Brief: Codec API function: Get the compression audio data frame by frame +* +***************************************************************************************/ + +VO_U32 VO_API voAMRWB_GetOutputData( + VO_HANDLE hCodec, /* i: The Codec Handle which was created by Init function*/ + VO_CODECBUFFER * pOutput, /* o: The output audio data */ + VO_AUDIO_OUTPUTINFO * pAudioFormat /* o: The encoder module filled audio format and used the input size*/ + ) +{ + Coder_State* gData = (Coder_State*)hCodec; + VO_MEM_OPERATOR *pMemOP; + FrameStream *stream = (FrameStream *)gData->stream; + pMemOP = (VO_MEM_OPERATOR *)gData->pvoMemop; + + if(stream->framebuffer_len < Frame_MaxByte) /* check the work buffer len */ + { + stream->frame_storelen = stream->framebuffer_len; + if(stream->frame_storelen) + { + pMemOP->Copy(VO_INDEX_ENC_AMRWB, stream->frame_ptr_bk , stream->frame_ptr , stream->frame_storelen); + } + if(stream->set_len > 0) + { + voAWB_UpdateFrameBuffer(stream, pMemOP); + } + if(stream->framebuffer_len < Frame_MaxByte) + { + if(pAudioFormat) + pAudioFormat->InputUsed = stream->used_len; + return VO_ERR_INPUT_BUFFER_SMALL; + } + } + + gData->inputStream = stream->frame_ptr; + gData->outputStream = (unsigned short*)pOutput->Buffer; + + gData->outputSize = AMR_Enc_Encode(gData); /* encoder main function */ + + pOutput->Length = gData->outputSize; /* get the output buffer length */ + stream->frame_ptr += 640; /* update the work buffer ptr */ + stream->framebuffer_len -= 640; + + if(pAudioFormat) /* return output audio information */ + { + pAudioFormat->Format.Channels = 1; + pAudioFormat->Format.SampleRate = 8000; + pAudioFormat->Format.SampleBits = 16; + pAudioFormat->InputUsed = stream->used_len; + } + return VO_ERR_NONE; +} + +/************************************************************************* +* +* Brief: Codec API function---set the data by specified parameter ID +* +*************************************************************************/ + + +VO_U32 VO_API voAMRWB_SetParam( + VO_HANDLE hCodec, /* i/o: The Codec Handle which was created by Init function */ + VO_S32 uParamID, /* i: The param ID */ + VO_PTR pData /* i: The param value depend on the ID */ + ) +{ + Coder_State* gData = (Coder_State*)hCodec; + FrameStream *stream = (FrameStream *)(gData->stream); + int *lValue = (int*)pData; + + switch(uParamID) + { + /* setting AMR-WB frame type*/ + case VO_PID_AMRWB_FRAMETYPE: + if(*lValue < VOAMRWB_DEFAULT || *lValue > VOAMRWB_RFC3267) + return VO_ERR_WRONG_PARAM_ID; + gData->frameType = *lValue; + break; + /* setting AMR-WB bit rate */ + case VO_PID_AMRWB_MODE: + { + if(*lValue < VOAMRWB_MD66 || *lValue > VOAMRWB_MD2385) + return VO_ERR_WRONG_PARAM_ID; + gData->mode = *lValue; + } + break; + /* enable or disable DTX mode */ + case VO_PID_AMRWB_DTX: + gData->allow_dtx = (Word16)(*lValue); + break; + + case VO_PID_COMMON_HEADDATA: + break; + /* flush the work buffer */ + case VO_PID_COMMON_FLUSH: + stream->set_ptr = NULL; + stream->frame_storelen = 0; + stream->framebuffer_len = 0; + stream->set_len = 0; + break; + + default: + return VO_ERR_WRONG_PARAM_ID; + } + return VO_ERR_NONE; +} + +/************************************************************************** +* +*Brief: Codec API function---Get the data by specified parameter ID +* +***************************************************************************/ + +VO_U32 VO_API voAMRWB_GetParam( + VO_HANDLE hCodec, /* i: The Codec Handle which was created by Init function */ + VO_S32 uParamID, /* i: The param ID */ + VO_PTR pData /* o: The param value depend on the ID */ + ) +{ + int temp; + Coder_State* gData = (Coder_State*)hCodec; + + if (gData==NULL) + return VO_ERR_INVALID_ARG; + switch(uParamID) + { + /* output audio format */ + case VO_PID_AMRWB_FORMAT: + { + VO_AUDIO_FORMAT* fmt = (VO_AUDIO_FORMAT*)pData; + fmt->Channels = 1; + fmt->SampleRate = 16000; + fmt->SampleBits = 16; + break; + } + /* output audio channel number */ + case VO_PID_AMRWB_CHANNELS: + temp = 1; + pData = (void *)(&temp); + break; + /* output audio sample rate */ + case VO_PID_AMRWB_SAMPLERATE: + temp = 16000; + pData = (void *)(&temp); + break; + /* output audio frame type */ + case VO_PID_AMRWB_FRAMETYPE: + temp = gData->frameType; + pData = (void *)(&temp); + break; + /* output audio bit rate */ + case VO_PID_AMRWB_MODE: + temp = gData->mode; + pData = (void *)(&temp); + break; + default: + return VO_ERR_WRONG_PARAM_ID; + } + + return VO_ERR_NONE; +} + +/*********************************************************************************** +* +* Brief: Codec API function---Release the codec after all encoder operations are done +* +*************************************************************************************/ + +VO_U32 VO_API voAMRWB_Uninit(VO_HANDLE hCodec /* i/o: Codec handle pointer */ + ) +{ + Coder_State* gData = (Coder_State*)hCodec; + VO_MEM_OPERATOR *pMemOP; + pMemOP = gData->pvoMemop; + + if(hCodec) + { + if(gData->stream) + { + if(gData->stream->frame_ptr_bk) + { + mem_free(pMemOP, gData->stream->frame_ptr_bk, VO_INDEX_ENC_AMRWB); + gData->stream->frame_ptr_bk = NULL; + } + mem_free(pMemOP, gData->stream, VO_INDEX_ENC_AMRWB); + gData->stream = NULL; + } + wb_vad_exit(&(((Coder_State *) gData)->vadSt), pMemOP); + dtx_enc_exit(&(((Coder_State *) gData)->dtx_encSt), pMemOP); + + mem_free(pMemOP, hCodec, VO_INDEX_ENC_AMRWB); + hCodec = NULL; + } + + return VO_ERR_NONE; +} + +/******************************************************************************** +* +* Brief: voGetAMRWBEncAPI gets the API handle of the codec +* +********************************************************************************/ + +VO_S32 VO_API voGetAMRWBEncAPI( + VO_AUDIO_CODECAPI * pEncHandle /* i/o: Codec handle pointer */ + ) +{ + if(NULL == pEncHandle) + return VO_ERR_INVALID_ARG; + pEncHandle->Init = voAMRWB_Init; + pEncHandle->SetInputData = voAMRWB_SetInputData; + pEncHandle->GetOutputData = voAMRWB_GetOutputData; + pEncHandle->SetParam = voAMRWB_SetParam; + pEncHandle->GetParam = voAMRWB_GetParam; + pEncHandle->Uninit = voAMRWB_Uninit; + + return VO_ERR_NONE; +} + +#ifdef __cplusplus +} +#endif diff --git a/media/libstagefright/codecs/amrwbenc/src/voicefac.c b/media/libstagefright/codecs/amrwbenc/src/voicefac.c new file mode 100644 index 0000000000000000000000000000000000000000..187d77454660ee80fd3daeddc24d3907f91f9544 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/voicefac.c @@ -0,0 +1,92 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: voicefac.c * +* * +* Description: Find the voicing factors (1 = voice to -1 = unvoiced) * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "math_op.h" + +Word16 voice_factor( /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */ + Word16 exc[], /* (i) Q_exc : pitch excitation */ + Word16 Q_exc, /* (i) : exc format */ + Word16 gain_pit, /* (i) Q14 : gain of pitch */ + Word16 code[], /* (i) Q9 : Fixed codebook excitation */ + Word16 gain_code, /* (i) Q0 : gain of code */ + Word16 L_subfr /* (i) : subframe length */ + ) +{ + Word16 tmp, exp, ener1, exp1, ener2, exp2; + Word32 i, L_tmp; + +#ifdef ASM_OPT /* asm optimization branch */ + ener1 = extract_h(Dot_product12_asm(exc, exc, L_subfr, &exp1)); +#else + ener1 = extract_h(Dot_product12(exc, exc, L_subfr, &exp1)); +#endif + exp1 = exp1 - (Q_exc + Q_exc); + L_tmp = vo_L_mult(gain_pit, gain_pit); + exp = norm_l(L_tmp); + tmp = extract_h(L_tmp << exp); + ener1 = vo_mult(ener1, tmp); + exp1 = exp1 - exp - 10; /* 10 -> gain_pit Q14 to Q9 */ + +#ifdef ASM_OPT /* asm optimization branch */ + ener2 = extract_h(Dot_product12_asm(code, code, L_subfr, &exp2)); +#else + ener2 = extract_h(Dot_product12(code, code, L_subfr, &exp2)); +#endif + + exp = norm_s(gain_code); + tmp = gain_code << exp; + tmp = vo_mult(tmp, tmp); + ener2 = vo_mult(ener2, tmp); + exp2 = exp2 - (exp + exp); + + i = exp1 - exp2; + + if (i >= 0) + { + ener1 = ener1 >> 1; + ener2 = ener2 >> (i + 1); + } else + { + ener1 = ener1 >> (1 - i); + ener2 = ener2 >> 1; + } + + tmp = vo_sub(ener1, ener2); + ener1 = add1(add1(ener1, ener2), 1); + + if (tmp >= 0) + { + tmp = div_s(tmp, ener1); + } else + { + tmp = vo_negate(div_s(vo_negate(tmp), ener1)); + } + + return (tmp); +} + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/wb_vad.c b/media/libstagefright/codecs/amrwbenc/src/wb_vad.c new file mode 100644 index 0000000000000000000000000000000000000000..01268533b2b358ef7bb7e4150882feeb01199939 --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/wb_vad.c @@ -0,0 +1,808 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: wb_vad.c * +* * +* Description: Voice Activity Detection * +* * +************************************************************************/ + +#include +#include +#include "cnst.h" +#include "wb_vad.h" +#include "typedef.h" +#include "basic_op.h" +#include "math_op.h" +#include "wb_vad_c.h" +#include "mem_align.h" + +/****************************************************************************** +* Calculate Log2 and scale the signal: +* +* ilog2(Word32 in) = -1024*log10(in * 2^-31)/log10(2), where in = [1, 2^31-1] +* +* input output +* 32768 16384 +* 1 31744 +* +* When input is in the range of [1,2^16], max error is 0.0380%. +*********************************************************************************/ + +static Word16 ilog2( /* return: output value of the log2 */ + Word16 mant /* i: value to be converted */ + ) +{ + Word16 ex, ex2, res; + Word32 i, l_temp; + + if (mant <= 0) + { + mant = 1; + } + ex = norm_s(mant); + mant = mant << ex; + + for (i = 0; i < 3; i++) + mant = vo_mult(mant, mant); + l_temp = vo_L_mult(mant, mant); + + ex2 = norm_l(l_temp); + mant = extract_h(l_temp << ex2); + + res = (ex + 16) << 10; + res = add1(res, (ex2 << 6)); + res = vo_sub(add1(res, 127), (mant >> 8)); + return (res); +} + +/****************************************************************************** +* +* Function : filter5 +* Purpose : Fifth-order half-band lowpass/highpass filter pair with +* decimation. +* +*******************************************************************************/ + +static void filter5( + Word16 * in0, /* i/o : input values; output low-pass part */ + Word16 * in1, /* i/o : input values; output high-pass part */ + Word16 data[] /* i/o : filter memory */ + ) +{ + Word16 temp0, temp1, temp2; + + temp0 = vo_sub(*in0, vo_mult(COEFF5_1, data[0])); + temp1 = add1(data[0], vo_mult(COEFF5_1, temp0)); + data[0] = temp0; + + temp0 = vo_sub(*in1, vo_mult(COEFF5_2, data[1])); + temp2 = add1(data[1], vo_mult(COEFF5_2, temp0)); + data[1] = temp0; + + *in0 = extract_h((vo_L_add(temp1, temp2) << 15)); + *in1 = extract_h((vo_L_sub(temp1, temp2) << 15)); +} + +/****************************************************************************** +* +* Function : filter3 +* Purpose : Third-order half-band lowpass/highpass filter pair with +* decimation. +* +*******************************************************************************/ + +static void filter3( + Word16 * in0, /* i/o : input values; output low-pass part */ + Word16 * in1, /* i/o : input values; output high-pass part */ + Word16 * data /* i/o : filter memory */ + ) +{ + Word16 temp1, temp2; + + temp1 = vo_sub(*in1, vo_mult(COEFF3, *data)); + temp2 = add1(*data, vo_mult(COEFF3, temp1)); + *data = temp1; + + *in1 = extract_h((vo_L_sub(*in0, temp2) << 15)); + *in0 = extract_h((vo_L_add(*in0, temp2) << 15)); +} + +/****************************************************************************** +* +* Function : level_calculation +* Purpose : Calculate signal level in a sub-band. Level is calculated +* by summing absolute values of the input data. +* +* Signal level calculated from of the end of the frame +* (data[count1 - count2]) is stored to (*sub_level) +* and added to the level of the next frame. +* +******************************************************************************/ + +static Word16 level_calculation( /* return: signal level */ + Word16 data[], /* i : signal buffer */ + Word16 * sub_level, /* i : level calculated at the end of the previous frame*/ + /* o : level of signal calculated from the last */ + /* (count2 - count1) samples */ + Word16 count1, /* i : number of samples to be counted */ + Word16 count2, /* i : number of samples to be counted */ + Word16 ind_m, /* i : step size for the index of the data buffer */ + Word16 ind_a, /* i : starting index of the data buffer */ + Word16 scale /* i : scaling for the level calculation */ + ) +{ + Word32 i, l_temp1, l_temp2; + Word16 level; + + l_temp1 = 0L; + for (i = count1; i < count2; i++) + { + l_temp1 += (abs_s(data[ind_m * i + ind_a])<<1); + } + + l_temp2 = vo_L_add(l_temp1, L_shl(*sub_level, 16 - scale)); + *sub_level = extract_h(L_shl(l_temp1, scale)); + + for (i = 0; i < count1; i++) + { + l_temp2 += (abs_s(data[ind_m * i + ind_a])<<1); + } + level = extract_h(L_shl2(l_temp2, scale)); + + return level; +} + +/****************************************************************************** +* +* Function : filter_bank +* Purpose : Divide input signal into bands and calculate level of +* the signal in each band +* +*******************************************************************************/ + +static void filter_bank( + VadVars * st, /* i/o : State struct */ + Word16 in[], /* i : input frame */ + Word16 level[] /* o : signal levels at each band */ + ) +{ + Word32 i; + Word16 tmp_buf[FRAME_LEN]; + + /* shift input 1 bit down for safe scaling */ + for (i = 0; i < FRAME_LEN; i++) + { + tmp_buf[i] = in[i] >> 1; + } + + /* run the filter bank */ + for (i = 0; i < 128; i++) + { + filter5(&tmp_buf[2 * i], &tmp_buf[2 * i + 1], st->a_data5[0]); + } + for (i = 0; i < 64; i++) + { + filter5(&tmp_buf[4 * i], &tmp_buf[4 * i + 2], st->a_data5[1]); + filter5(&tmp_buf[4 * i + 1], &tmp_buf[4 * i + 3], st->a_data5[2]); + } + for (i = 0; i < 32; i++) + { + filter5(&tmp_buf[8 * i], &tmp_buf[8 * i + 4], st->a_data5[3]); + filter5(&tmp_buf[8 * i + 2], &tmp_buf[8 * i + 6], st->a_data5[4]); + filter3(&tmp_buf[8 * i + 3], &tmp_buf[8 * i + 7], &st->a_data3[0]); + } + for (i = 0; i < 16; i++) + { + filter3(&tmp_buf[16 * i + 0], &tmp_buf[16 * i + 8], &st->a_data3[1]); + filter3(&tmp_buf[16 * i + 4], &tmp_buf[16 * i + 12], &st->a_data3[2]); + filter3(&tmp_buf[16 * i + 6], &tmp_buf[16 * i + 14], &st->a_data3[3]); + } + + for (i = 0; i < 8; i++) + { + filter3(&tmp_buf[32 * i + 0], &tmp_buf[32 * i + 16], &st->a_data3[4]); + filter3(&tmp_buf[32 * i + 8], &tmp_buf[32 * i + 24], &st->a_data3[5]); + } + + /* calculate levels in each frequency band */ + + /* 4800 - 6400 Hz */ + level[11] = level_calculation(tmp_buf, &st->sub_level[11], 16, 64, 4, 1, 14); + /* 4000 - 4800 Hz */ + level[10] = level_calculation(tmp_buf, &st->sub_level[10], 8, 32, 8, 7, 15); + /* 3200 - 4000 Hz */ + level[9] = level_calculation(tmp_buf, &st->sub_level[9],8, 32, 8, 3, 15); + /* 2400 - 3200 Hz */ + level[8] = level_calculation(tmp_buf, &st->sub_level[8],8, 32, 8, 2, 15); + /* 2000 - 2400 Hz */ + level[7] = level_calculation(tmp_buf, &st->sub_level[7],4, 16, 16, 14, 16); + /* 1600 - 2000 Hz */ + level[6] = level_calculation(tmp_buf, &st->sub_level[6],4, 16, 16, 6, 16); + /* 1200 - 1600 Hz */ + level[5] = level_calculation(tmp_buf, &st->sub_level[5],4, 16, 16, 4, 16); + /* 800 - 1200 Hz */ + level[4] = level_calculation(tmp_buf, &st->sub_level[4],4, 16, 16, 12, 16); + /* 600 - 800 Hz */ + level[3] = level_calculation(tmp_buf, &st->sub_level[3],2, 8, 32, 8, 17); + /* 400 - 600 Hz */ + level[2] = level_calculation(tmp_buf, &st->sub_level[2],2, 8, 32, 24, 17); + /* 200 - 400 Hz */ + level[1] = level_calculation(tmp_buf, &st->sub_level[1],2, 8, 32, 16, 17); + /* 0 - 200 Hz */ + level[0] = level_calculation(tmp_buf, &st->sub_level[0],2, 8, 32, 0, 17); +} + +/****************************************************************************** +* +* Function : update_cntrl +* Purpose : Control update of the background noise estimate. +* +*******************************************************************************/ + +static void update_cntrl( + VadVars * st, /* i/o : State structure */ + Word16 level[] /* i : sub-band levels of the input frame */ + ) +{ + Word32 i; + Word16 num, temp, stat_rat, exp, denom; + Word16 alpha; + + /* if a tone has been detected for a while, initialize stat_count */ + if (sub((Word16) (st->tone_flag & 0x7c00), 0x7c00) == 0) + { + st->stat_count = STAT_COUNT; + } else + { + /* if 8 last vad-decisions have been "0", reinitialize stat_count */ + if ((st->vadreg & 0x7f80) == 0) + { + st->stat_count = STAT_COUNT; + } else + { + stat_rat = 0; + for (i = 0; i < COMPLEN; i++) + { + if(level[i] > st->ave_level[i]) + { + num = level[i]; + denom = st->ave_level[i]; + } else + { + num = st->ave_level[i]; + denom = level[i]; + } + /* Limit nimimum value of num and denom to STAT_THR_LEVEL */ + if(num < STAT_THR_LEVEL) + { + num = STAT_THR_LEVEL; + } + if(denom < STAT_THR_LEVEL) + { + denom = STAT_THR_LEVEL; + } + exp = norm_s(denom); + denom = denom << exp; + + /* stat_rat = num/denom * 64 */ + temp = div_s(num >> 1, denom); + stat_rat = add1(stat_rat, shr(temp, (8 - exp))); + } + + /* compare stat_rat with a threshold and update stat_count */ + if(stat_rat > STAT_THR) + { + st->stat_count = STAT_COUNT; + } else + { + if ((st->vadreg & 0x4000) != 0) + { + + if (st->stat_count != 0) + { + st->stat_count = st->stat_count - 1; + } + } + } + } + } + + /* Update average amplitude estimate for stationarity estimation */ + alpha = ALPHA4; + if(st->stat_count == STAT_COUNT) + { + alpha = 32767; + } else if ((st->vadreg & 0x4000) == 0) + { + alpha = ALPHA5; + } + for (i = 0; i < COMPLEN; i++) + { + st->ave_level[i] = add1(st->ave_level[i], vo_mult_r(alpha, vo_sub(level[i], st->ave_level[i]))); + } +} + +/****************************************************************************** +* +* Function : hangover_addition +* Purpose : Add hangover after speech bursts +* +*******************************************************************************/ + +static Word16 hangover_addition( /* return: VAD_flag indicating final VAD decision */ + VadVars * st, /* i/o : State structure */ + Word16 low_power, /* i : flag power of the input frame */ + Word16 hang_len, /* i : hangover length */ + Word16 burst_len /* i : minimum burst length for hangover addition */ + ) +{ + /* if the input power (pow_sum) is lower than a threshold, clear counters and set VAD_flag to "0" */ + if (low_power != 0) + { + st->burst_count = 0; + st->hang_count = 0; + return 0; + } + /* update the counters (hang_count, burst_count) */ + if ((st->vadreg & 0x4000) != 0) + { + st->burst_count = st->burst_count + 1; + if(st->burst_count >= burst_len) + { + st->hang_count = hang_len; + } + return 1; + } else + { + st->burst_count = 0; + if (st->hang_count > 0) + { + st->hang_count = st->hang_count - 1; + return 1; + } + } + return 0; +} + +/****************************************************************************** +* +* Function : noise_estimate_update +* Purpose : Update of background noise estimate +* +*******************************************************************************/ + +static void noise_estimate_update( + VadVars * st, /* i/o : State structure */ + Word16 level[] /* i : sub-band levels of the input frame */ + ) +{ + Word32 i; + Word16 alpha_up, alpha_down, bckr_add = 2; + + /* Control update of bckr_est[] */ + update_cntrl(st, level); + + /* Choose update speed */ + if ((0x7800 & st->vadreg) == 0) + { + alpha_up = ALPHA_UP1; + alpha_down = ALPHA_DOWN1; + } else + { + if ((st->stat_count == 0)) + { + alpha_up = ALPHA_UP2; + alpha_down = ALPHA_DOWN2; + } else + { + alpha_up = 0; + alpha_down = ALPHA3; + bckr_add = 0; + } + } + + /* Update noise estimate (bckr_est) */ + for (i = 0; i < COMPLEN; i++) + { + Word16 temp; + temp = (st->old_level[i] - st->bckr_est[i]); + + if (temp < 0) + { /* update downwards */ + st->bckr_est[i] = add1(-2, add(st->bckr_est[i],vo_mult_r(alpha_down, temp))); + /* limit minimum value of the noise estimate to NOISE_MIN */ + if(st->bckr_est[i] < NOISE_MIN) + { + st->bckr_est[i] = NOISE_MIN; + } + } else + { /* update upwards */ + st->bckr_est[i] = add1(bckr_add, add1(st->bckr_est[i],vo_mult_r(alpha_up, temp))); + + /* limit maximum value of the noise estimate to NOISE_MAX */ + if(st->bckr_est[i] > NOISE_MAX) + { + st->bckr_est[i] = NOISE_MAX; + } + } + } + + /* Update signal levels of the previous frame (old_level) */ + for (i = 0; i < COMPLEN; i++) + { + st->old_level[i] = level[i]; + } +} + +/****************************************************************************** +* +* Function : vad_decision +* Purpose : Calculates VAD_flag +* +*******************************************************************************/ + +static Word16 vad_decision( /* return value : VAD_flag */ + VadVars * st, /* i/o : State structure */ + Word16 level[COMPLEN], /* i : sub-band levels of the input frame */ + Word32 pow_sum /* i : power of the input frame */ + ) +{ + Word32 i; + Word32 L_snr_sum; + Word32 L_temp; + Word16 vad_thr, temp, noise_level; + Word16 low_power_flag; + Word16 hang_len, burst_len; + Word16 ilog2_speech_level, ilog2_noise_level; + Word16 temp2; + + /* Calculate squared sum of the input levels (level) divided by the background noise components + * (bckr_est). */ + L_snr_sum = 0; + for (i = 0; i < COMPLEN; i++) + { + Word16 exp; + + exp = norm_s(st->bckr_est[i]); + temp = (st->bckr_est[i] << exp); + temp = div_s((level[i] >> 1), temp); + temp = shl(temp, (exp - (UNIRSHFT - 1))); + L_snr_sum = L_mac(L_snr_sum, temp, temp); + } + + /* Calculate average level of estimated background noise */ + L_temp = 0; + for (i = 1; i < COMPLEN; i++) /* ignore lowest band */ + { + L_temp = vo_L_add(L_temp, st->bckr_est[i]); + } + + noise_level = extract_h((L_temp << 12)); + /* if SNR is lower than a threshold (MIN_SPEECH_SNR), and increase speech_level */ + temp = vo_mult(noise_level, MIN_SPEECH_SNR) << 3; + + if(st->speech_level < temp) + { + st->speech_level = temp; + } + ilog2_noise_level = ilog2(noise_level); + + /* If SNR is very poor, speech_level is probably corrupted by noise level. This is correctred by + * subtracting MIN_SPEECH_SNR*noise_level from speech level */ + ilog2_speech_level = ilog2(st->speech_level - temp); + + temp = add1(vo_mult(NO_SLOPE, (ilog2_noise_level - NO_P1)), THR_HIGH); + + temp2 = add1(SP_CH_MIN, vo_mult(SP_SLOPE, (ilog2_speech_level - SP_P1))); + if (temp2 < SP_CH_MIN) + { + temp2 = SP_CH_MIN; + } + if (temp2 > SP_CH_MAX) + { + temp2 = SP_CH_MAX; + } + vad_thr = temp + temp2; + + if(vad_thr < THR_MIN) + { + vad_thr = THR_MIN; + } + /* Shift VAD decision register */ + st->vadreg = (st->vadreg >> 1); + + /* Make intermediate VAD decision */ + if(L_snr_sum > vo_L_mult(vad_thr, (512 * COMPLEN))) + { + st->vadreg = (Word16) (st->vadreg | 0x4000); + } + /* check if the input power (pow_sum) is lower than a threshold" */ + if(pow_sum < VAD_POW_LOW) + { + low_power_flag = 1; + } else + { + low_power_flag = 0; + } + /* Update background noise estimates */ + noise_estimate_update(st, level); + + /* Calculate values for hang_len and burst_len based on vad_thr */ + hang_len = add1(vo_mult(HANG_SLOPE, (vad_thr - HANG_P1)), HANG_HIGH); + if(hang_len < HANG_LOW) + { + hang_len = HANG_LOW; + } + burst_len = add1(vo_mult(BURST_SLOPE, (vad_thr - BURST_P1)), BURST_HIGH); + + return (hangover_addition(st, low_power_flag, hang_len, burst_len)); +} + +/****************************************************************************** +* +* Function : Estimate_Speech() +* Purpose : Estimate speech level +* +* Maximum signal level is searched and stored to the variable sp_max. +* The speech frames must locate within SP_EST_COUNT number of frames. +* Thus, noisy frames having occasional VAD = "1" decisions will not +* affect to the estimated speech_level. +* +*******************************************************************************/ + +static void Estimate_Speech( + VadVars * st, /* i/o : State structure */ + Word16 in_level /* level of the input frame */ + ) +{ + Word16 alpha; + + /* if the required activity count cannot be achieved, reset counters */ + if((st->sp_est_cnt - st->sp_max_cnt) > (SP_EST_COUNT - SP_ACTIVITY_COUNT)) + { + st->sp_est_cnt = 0; + st->sp_max = 0; + st->sp_max_cnt = 0; + } + st->sp_est_cnt += 1; + + if (((st->vadreg & 0x4000)||(in_level > st->speech_level)) && (in_level > MIN_SPEECH_LEVEL1)) + { + /* update sp_max */ + if(in_level > st->sp_max) + { + st->sp_max = in_level; + } + st->sp_max_cnt += 1; + + if(st->sp_max_cnt >= SP_ACTIVITY_COUNT) + { + Word16 tmp; + /* update speech estimate */ + tmp = (st->sp_max >> 1); /* scale to get "average" speech level */ + + /* select update speed */ + if(tmp > st->speech_level) + { + alpha = ALPHA_SP_UP; + } else + { + alpha = ALPHA_SP_DOWN; + } + if(tmp > MIN_SPEECH_LEVEL2) + { + st->speech_level = add1(st->speech_level, vo_mult_r(alpha, vo_sub(tmp, st->speech_level))); + } + /* clear all counters used for speech estimation */ + st->sp_max = 0; + st->sp_max_cnt = 0; + st->sp_est_cnt = 0; + } + } +} + +/****************************************************************************** +* +* Function: wb_vad_init +* Purpose: Allocates state memory and initializes state memory +* +*******************************************************************************/ + +Word16 wb_vad_init( /* return: non-zero with error, zero for ok. */ + VadVars ** state, /* i/o : State structure */ + VO_MEM_OPERATOR *pMemOP + ) +{ + VadVars *s; + + if (state == (VadVars **) NULL) + { + fprintf(stderr, "vad_init: invalid parameter\n"); + return -1; + } + *state = NULL; + + /* allocate memory */ + if ((s = (VadVars *) mem_malloc(pMemOP, sizeof(VadVars), 32, VO_INDEX_ENC_AMRWB)) == NULL) + { + fprintf(stderr, "vad_init: can not malloc state structure\n"); + return -1; + } + wb_vad_reset(s); + + *state = s; + + return 0; +} + +/****************************************************************************** +* +* Function: wb_vad_reset +* Purpose: Initializes state memory +* +*******************************************************************************/ + +Word16 wb_vad_reset( /* return: non-zero with error, zero for ok. */ + VadVars * state /* i/o : State structure */ + ) +{ + Word32 i, j; + + if (state == (VadVars *) NULL) + { + fprintf(stderr, "vad_reset: invalid parameter\n"); + return -1; + } + state->tone_flag = 0; + state->vadreg = 0; + state->hang_count = 0; + state->burst_count = 0; + state->hang_count = 0; + + /* initialize memory used by the filter bank */ + for (i = 0; i < F_5TH_CNT; i++) + { + for (j = 0; j < 2; j++) + { + state->a_data5[i][j] = 0; + } + } + + for (i = 0; i < F_3TH_CNT; i++) + { + state->a_data3[i] = 0; + } + + /* initialize the rest of the memory */ + for (i = 0; i < COMPLEN; i++) + { + state->bckr_est[i] = NOISE_INIT; + state->old_level[i] = NOISE_INIT; + state->ave_level[i] = NOISE_INIT; + state->sub_level[i] = 0; + } + + state->sp_est_cnt = 0; + state->sp_max = 0; + state->sp_max_cnt = 0; + state->speech_level = SPEECH_LEVEL_INIT; + state->prev_pow_sum = 0; + return 0; +} + +/****************************************************************************** +* +* Function: wb_vad_exit +* Purpose: The memory used for state memory is freed +* +*******************************************************************************/ + +void wb_vad_exit( + VadVars ** state, /* i/o : State structure */ + VO_MEM_OPERATOR *pMemOP + ) +{ + if (state == NULL || *state == NULL) + return; + /* deallocate memory */ + mem_free(pMemOP, *state, VO_INDEX_ENC_AMRWB); + *state = NULL; + return; +} + +/****************************************************************************** +* +* Function : wb_vad_tone_detection +* Purpose : Search maximum pitch gain from a frame. Set tone flag if +* pitch gain is high. This is used to detect +* signaling tones and other signals with high pitch gain. +* +*******************************************************************************/ + +void wb_vad_tone_detection( + VadVars * st, /* i/o : State struct */ + Word16 p_gain /* pitch gain */ + ) +{ + /* update tone flag */ + st->tone_flag = (st->tone_flag >> 1); + + /* if (pitch_gain > TONE_THR) set tone flag */ + if (p_gain > TONE_THR) + { + st->tone_flag = (Word16) (st->tone_flag | 0x4000); + } +} + +/****************************************************************************** +* +* Function : wb_vad +* Purpose : Main program for Voice Activity Detection (VAD) for AMR +* +*******************************************************************************/ + +Word16 wb_vad( /* Return value : VAD Decision, 1 = speech, 0 = noise */ + VadVars * st, /* i/o : State structure */ + Word16 in_buf[] /* i : samples of the input frame */ + ) +{ + Word16 level[COMPLEN]; + Word32 i; + Word16 VAD_flag, temp; + Word32 L_temp, pow_sum; + + /* Calculate power of the input frame. */ + L_temp = 0L; + for (i = 0; i < FRAME_LEN; i++) + { + L_temp = L_mac(L_temp, in_buf[i], in_buf[i]); + } + + /* pow_sum = power of current frame and previous frame */ + pow_sum = L_add(L_temp, st->prev_pow_sum); + + /* save power of current frame for next call */ + st->prev_pow_sum = L_temp; + + /* If input power is very low, clear tone flag */ + if (pow_sum < POW_TONE_THR) + { + st->tone_flag = (Word16) (st->tone_flag & 0x1fff); + } + /* Run the filter bank and calculate signal levels at each band */ + filter_bank(st, in_buf, level); + + /* compute VAD decision */ + VAD_flag = vad_decision(st, level, pow_sum); + + /* Calculate input level */ + L_temp = 0; + for (i = 1; i < COMPLEN; i++) /* ignore lowest band */ + { + L_temp = vo_L_add(L_temp, level[i]); + } + + temp = extract_h(L_temp << 12); + + Estimate_Speech(st, temp); /* Estimate speech level */ + return (VAD_flag); +} + + + + diff --git a/media/libstagefright/codecs/amrwbenc/src/weight_a.c b/media/libstagefright/codecs/amrwbenc/src/weight_a.c new file mode 100644 index 0000000000000000000000000000000000000000..d47be979d782bfa7c44b296dc0552f0042fb7a3a --- /dev/null +++ b/media/libstagefright/codecs/amrwbenc/src/weight_a.c @@ -0,0 +1,48 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ + +/*********************************************************************** +* File: weight_a.c * +* * +* Description:Weighting of LPC coefficients * +* ap[i] = a[i] * (gamma ** i) * +* * +************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" + +void Weight_a( + Word16 a[], /* (i) Q12 : a[m+1] LPC coefficients */ + Word16 ap[], /* (o) Q12 : Spectral expanded LPC coefficients */ + Word16 gamma, /* (i) Q15 : Spectral expansion factor. */ + Word16 m /* (i) : LPC order. */ + ) +{ + Word32 num = m - 1, fac; + *ap++ = *a++; + fac = gamma; + do{ + *ap++ =(Word16)(((vo_L_mult((*a++), fac)) + 0x8000) >> 16); + fac = (vo_L_mult(fac, gamma) + 0x8000) >> 16; + }while(--num != 0); + + *ap++ = (Word16)(((vo_L_mult((*a++), fac)) + 0x8000) >> 16); + return; +} + + + diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp index aa2a3d146f277ca4f635bea471575e472a965ea1..24c361ed345de1bc274b9b974c2c1994d3ec996f 100644 --- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp +++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp @@ -34,6 +34,8 @@ namespace android { +static const char kStartCode[4] = { 0x00, 0x00, 0x00, 0x01 }; + static int32_t Malloc(void *userData, int32_t size, int32_t attrs) { return reinterpret_cast(malloc(size)); } @@ -154,9 +156,7 @@ status_t AVCDecoder::start(MetaData *) { } } - sp params = new MetaData; - params->setInt32(kKeyWantsNALFragments, true); - mSource->start(params.get()); + mSource->start(); mAnchorTimeUs = 0; mNumSamplesOutput = 0; @@ -167,9 +167,10 @@ status_t AVCDecoder::start(MetaData *) { } void AVCDecoder::addCodecSpecificData(const uint8_t *data, size_t size) { - MediaBuffer *buffer = new MediaBuffer(size); - memcpy(buffer->data(), data, size); - buffer->set_range(0, size); + MediaBuffer *buffer = new MediaBuffer(size + 4); + memcpy(buffer->data(), kStartCode, 4); + memcpy((uint8_t *)buffer->data() + 4, data, size); + buffer->set_range(0, size + 4); mCodecSpecificData.push(buffer); } @@ -200,6 +201,29 @@ sp AVCDecoder::getFormat() { return mFormat; } +static void findNALFragment( + const MediaBuffer *buffer, const uint8_t **fragPtr, size_t *fragSize) { + const uint8_t *data = + (const uint8_t *)buffer->data() + buffer->range_offset(); + + size_t size = buffer->range_length(); + + CHECK(size >= 4); + CHECK(!memcmp(kStartCode, data, 4)); + + size_t offset = 4; + while (offset + 3 < size && memcmp(kStartCode, &data[offset], 4)) { + ++offset; + } + + *fragPtr = &data[4]; + if (offset + 3 >= size) { + *fragSize = size - 4; + } else { + *fragSize = offset - 4; + } +} + status_t AVCDecoder::read( MediaBuffer **out, const ReadOptions *options) { *out = NULL; @@ -254,37 +278,31 @@ status_t AVCDecoder::read( } } - const uint8_t *inPtr = - (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(); + const uint8_t *fragPtr; + size_t fragSize; + findNALFragment(mInputBuffer, &fragPtr, &fragSize); + + bool releaseFragment = true; + status_t err = UNKNOWN_ERROR; int nalType; int nalRefIdc; AVCDec_Status res = PVAVCDecGetNALType( - const_cast(inPtr), mInputBuffer->range_length(), + const_cast(fragPtr), fragSize, &nalType, &nalRefIdc); if (res != AVCDEC_SUCCESS) { LOGE("cannot determine nal type"); - - mInputBuffer->release(); - mInputBuffer = NULL; - - return UNKNOWN_ERROR; - } - - switch (nalType) { + } else switch (nalType) { case AVC_NALTYPE_SPS: { res = PVAVCDecSeqParamSet( - mHandle, const_cast(inPtr), - mInputBuffer->range_length()); + mHandle, const_cast(fragPtr), + fragSize); if (res != AVCDEC_SUCCESS) { - mInputBuffer->release(); - mInputBuffer = NULL; - - return UNKNOWN_ERROR; + break; } AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject; @@ -324,47 +342,53 @@ status_t AVCDecoder::read( int32_t aligned_width = (crop_right - crop_left + 1 + 15) & ~15; int32_t aligned_height = (crop_bottom - crop_top + 1 + 15) & ~15; - mFormat->setInt32(kKeyWidth, aligned_width); - mFormat->setInt32(kKeyHeight, aligned_height); - mInputBuffer->release(); - mInputBuffer = NULL; + int32_t oldWidth, oldHeight; + CHECK(mFormat->findInt32(kKeyWidth, &oldWidth)); + CHECK(mFormat->findInt32(kKeyHeight, &oldHeight)); - return INFO_FORMAT_CHANGED; + if (oldWidth != aligned_width || oldHeight != aligned_height) { + mFormat->setInt32(kKeyWidth, aligned_width); + mFormat->setInt32(kKeyHeight, aligned_height); + + err = INFO_FORMAT_CHANGED; + } else { + *out = new MediaBuffer(0); + err = OK; + } + break; } case AVC_NALTYPE_PPS: { res = PVAVCDecPicParamSet( - mHandle, const_cast(inPtr), - mInputBuffer->range_length()); - - mInputBuffer->release(); - mInputBuffer = NULL; + mHandle, const_cast(fragPtr), + fragSize); if (res != AVCDEC_SUCCESS) { - return UNKNOWN_ERROR; + break; } *out = new MediaBuffer(0); - return OK; + err = OK; + break; } case AVC_NALTYPE_SLICE: case AVC_NALTYPE_IDR: { res = PVAVCDecodeSlice( - mHandle, const_cast(inPtr), - mInputBuffer->range_length()); + mHandle, const_cast(fragPtr), + fragSize); if (res == AVCDEC_PICTURE_OUTPUT_READY) { int32_t index; int32_t Release; AVCFrameIO Output; Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL; - CHECK_EQ(PVAVCDecGetOutput( - mHandle, &index, &Release, &Output), + + CHECK_EQ(PVAVCDecGetOutput(mHandle, &index, &Release, &Output), AVCDEC_SUCCESS); CHECK(index >= 0); @@ -376,48 +400,44 @@ status_t AVCDecoder::read( // Do _not_ release input buffer yet. - return OK; + releaseFragment = false; + err = OK; + break; } - mInputBuffer->release(); - mInputBuffer = NULL; - if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) { *out = new MediaBuffer(0); - return OK; + err = OK; } else { LOGV("failed to decode frame (res = %d)", res); - return UNKNOWN_ERROR; } + break; } case AVC_NALTYPE_SEI: { res = PVAVCDecSEI( - mHandle, const_cast(inPtr), - mInputBuffer->range_length()); - - mInputBuffer->release(); - mInputBuffer = NULL; + mHandle, const_cast(fragPtr), + fragSize); if (res != AVCDEC_SUCCESS) { - return UNKNOWN_ERROR; + break; } *out = new MediaBuffer(0); - return OK; + err = OK; + break; } case AVC_NALTYPE_AUD: + case AVC_NALTYPE_FILL: { - mInputBuffer->release(); - mInputBuffer = NULL; - *out = new MediaBuffer(0); - return OK; + err = OK; + break; } default: @@ -428,10 +448,19 @@ status_t AVCDecoder::read( } } - mInputBuffer->release(); - mInputBuffer = NULL; + if (releaseFragment) { + size_t offset = mInputBuffer->range_offset(); + if (fragSize + 4 == mInputBuffer->range_length()) { + mInputBuffer->release(); + mInputBuffer = NULL; + } else { + mInputBuffer->set_range( + offset + fragSize + 4, + mInputBuffer->range_length() - fragSize - 4); + } + } - return UNKNOWN_ERROR; + return err; } // static diff --git a/media/libstagefright/codecs/common/Android.mk b/media/libstagefright/codecs/common/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..fffb2ad9c09d59b11eab65abc08908471dc8f79b --- /dev/null +++ b/media/libstagefright/codecs/common/Android.mk @@ -0,0 +1,33 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_PRELINK_MODULE := false + +LOCAL_SRC_FILES := cmnMemory.c + +LOCAL_MODULE := libstagefright_enc_common + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include + +LOCAL_CFLAGS := $(VO_CFLAGS) + +ifeq ($(VOTT), v5) +LOCAL_CFLAGS += -DARM -DASM_OPT +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E +endif + +ifeq ($(VOTT), v7) +LOCAL_CFLAGS += -DARM -DARMV7 -DASM_OPT +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7 +endif + +include $(BUILD_SHARED_LIBRARY) + + + diff --git a/media/libstagefright/codecs/common/Config.mk b/media/libstagefright/codecs/common/Config.mk new file mode 100644 index 0000000000000000000000000000000000000000..27a17c1c9d3bfd5256b3f2aefd2f6c95e9430e9e --- /dev/null +++ b/media/libstagefright/codecs/common/Config.mk @@ -0,0 +1,24 @@ +# +# This configure file is just for Linux projects against Android +# + +VOPRJ := +VONJ := + +# WARNING: +# Using v7 breaks generic build +ifeq ($(TARGET_ARCH),arm) +VOTT := v5 +else +VOTT := pc +endif + +# Do we also need to check on ARCH_ARM_HAVE_ARMV7A? - probably not +ifeq ($(ARCH_ARM_HAVE_NEON),true) +VOTT := v7 +endif + +VOTEST := 0 + +VO_CFLAGS:=-DLINUX + diff --git a/media/libstagefright/codecs/common/cmnMemory.c b/media/libstagefright/codecs/common/cmnMemory.c new file mode 100644 index 0000000000000000000000000000000000000000..c17264c15dbc323eed30eb1055f9c3010bb7b424 --- /dev/null +++ b/media/libstagefright/codecs/common/cmnMemory.c @@ -0,0 +1,73 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: cmnMemory.c + + Content: sample code for memory operator implementation + +*******************************************************************************/ +#include "cmnMemory.h" + +#include +#if defined LINUX +#include +#endif + +//VO_MEM_OPERATOR g_memOP; + +VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo) +{ + if (!pMemInfo) + return VO_ERR_INVALID_ARG; + + pMemInfo->VBuffer = malloc (pMemInfo->Size); + return 0; +} + +VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pMem) +{ + free (pMem); + return 0; +} + +VO_U32 cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize) +{ + memset (pBuff, uValue, uSize); + return 0; +} + +VO_U32 cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) +{ + memcpy (pDest, pSource, uSize); + return 0; +} + +VO_U32 cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize) +{ + return 0; +} + +VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize) +{ + return memcmp(pBuffer1, pBuffer2, uSize); +} + +VO_U32 cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) +{ + memmove (pDest, pSource, uSize); + return 0; +} + diff --git a/media/libstagefright/codecs/common/include/cmnMemory.h b/media/libstagefright/codecs/common/include/cmnMemory.h new file mode 100644 index 0000000000000000000000000000000000000000..931560082c5a6a25d55d6fae774a6f31b19b1950 --- /dev/null +++ b/media/libstagefright/codecs/common/include/cmnMemory.h @@ -0,0 +1,106 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: cmnMemory.h + + Content: memory operator implementation header file + +*******************************************************************************/ + +#ifndef __cmnMemory_H__ +#define __cmnMemory_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +//extern VO_MEM_OPERATOR g_memOP; + +/** + * Allocate memory + * \param uID [in] module ID + * \param uSize [in] size of memory + * \return value is the allocated memory address. NULL is failed. + */ +VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo); + +/** + * Free up memory + * \param uID [in] module ID + * \param pMem [in] address of memory + * \return value 0, if succeeded. + */ +VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pBuffer); + +/** + * memory set function + * \param uID [in] module ID + * \param pBuff [in/out] address of memory + * \param uValue [in] the value to be set + * \param uSize [in] the size to be set + * \return value 0, if succeeded. + */ +VO_U32 cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize); + +/** + * memory copy function + * \param uID [in] module ID + * \param pDest [in/out] address of destination memory + * \param pSource [in] address of source memory + * \param uSize [in] the size to be copied + * \return value 0, if succeeded. + */ +VO_U32 cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize); + +/** + * memory check function + * \param uID [in] module ID + * \param pBuff [in] address of buffer to be checked + * \param uSize [in] the size to be checked + * \return value 0, if succeeded. + */ +VO_U32 cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize); + +/** + * memory compare function + * \param uID [in] module ID + * \param pBuffer1 [in] address of buffer 1 to be compared + * \param pBuffer2 [in] address of buffer 2 to be compared + * \param uSize [in] the size to be compared + * \return value: same as standard C run-time memcmp() function. + */ +VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize); + +/** + * memory move function + * \param uID [in] module ID + * \param pDest [in/out] address of destination memory + * \param pSource [in] address of source memory + * \param uSize [in] the size to be moved + * \return value 0, if succeeded. + */ +VO_U32 cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __cmnMemory_H__ + + diff --git a/media/libstagefright/codecs/common/include/voAAC.h b/media/libstagefright/codecs/common/include/voAAC.h new file mode 100644 index 0000000000000000000000000000000000000000..d11ed83734bab30e50908c714b24e43d0887f64d --- /dev/null +++ b/media/libstagefright/codecs/common/include/voAAC.h @@ -0,0 +1,74 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: voAAC.h + + Content: AAC codec APIs & data types + +*******************************************************************************/ + +#ifndef __voAAC_H__ +#define __voAAC_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "voAudio.h" + +/*! + * the frame type that the decoder supports + */ +typedef enum { + VOAAC_RAWDATA = 0, /*! */ + VOAMRWB_N_MODES = 9, /*!< Invalid mode */ + VOAMRWB_MODE_MAX = VO_MAX_ENUM_VALUE + +}VOAMRWBMODE; + +/*!* the frame format the codec supports*/ +typedef enum { + VOAMRWB_DEFAULT = 0, /*!< the frame type is the header (defined in RFC3267) + rawdata*/ + /*One word (2-byte) for sync word (0x6b21)*/ + /*One word (2-byte) for frame length N.*/ + /*N words (2-byte) containing N bits (bit 0 = 0x007f, bit 1 = 0x0081).*/ + VOAMRWB_ITU = 1, + /*One word (2-byte) for sync word (0x6b21).*/ + /*One word (2-byte) to indicate the frame type.*/ + /*One word (2-byte) to indicate the mode.*/ + /*N words (2-byte) containing N bits (bit 0 = 0xff81, bit 1 = 0x007f).*/ + VOAMRWB_RFC3267 = 2, /* see RFC 3267 */ + VOAMRWB_TMAX = VO_MAX_ENUM_VALUE +}VOAMRWBFRAMETYPE; + + +#define VO_PID_AMRWB_Module 0x42261000 +#define VO_PID_AMRWB_FORMAT (VO_PID_AMRWB_Module | 0x0002) +#define VO_PID_AMRWB_CHANNELS (VO_PID_AMRWB_Module | 0x0003) +#define VO_PID_AMRWB_SAMPLERATE (VO_PID_AMRWB_Module | 0x0004) +#define VO_PID_AMRWB_FRAMETYPE (VO_PID_AMRWB_Module | 0x0005) +#define VO_PID_AMRWB_MODE (VO_PID_AMRWB_Module | 0x0006) +#define VO_PID_AMRWB_DTX (VO_PID_AMRWB_Module | 0x0007) + +/** + * Get audio codec API interface + * \param pEncHandle [out] Return the AMRWB Encoder handle. + * \retval VO_ERR_OK Succeeded. + */ +VO_S32 VO_API voGetAMRWBEncAPI(VO_AUDIO_CODECAPI *pEncHandle); + + +#pragma pack(pop) +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + + +#endif //__VOAMRWB_H__ + diff --git a/media/libstagefright/codecs/common/include/voAudio.h b/media/libstagefright/codecs/common/include/voAudio.h new file mode 100644 index 0000000000000000000000000000000000000000..64c9dfbb6c67ea4b328824ac9d467a010de0401e --- /dev/null +++ b/media/libstagefright/codecs/common/include/voAudio.h @@ -0,0 +1,173 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: voAudio.h + + Content: Audio types and functions + +*******************************************************************************/ + +#ifndef __voAudio_H__ +#define __voAudio_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "voIndex.h" +#include "voMem.h" + +#define VO_PID_AUDIO_BASE 0x42000000 /*!< The base param ID for AUDIO codec */ +#define VO_PID_AUDIO_FORMAT (VO_PID_AUDIO_BASE | 0X0001) /*!< The format data of audio in track */ +#define VO_PID_AUDIO_SAMPLEREATE (VO_PID_AUDIO_BASE | 0X0002) /*!< The sample rate of audio */ +#define VO_PID_AUDIO_CHANNELS (VO_PID_AUDIO_BASE | 0X0003) /*!< The channel of audio */ +#define VO_PID_AUDIO_BITRATE (VO_PID_AUDIO_BASE | 0X0004) /*!< The bit rate of audio */ +#define VO_PID_AUDIO_CHANNELMODE (VO_PID_AUDIO_BASE | 0X0005) /*!< The channel mode of audio */ + +#define VO_ERR_AUDIO_BASE 0x82000000 +#define VO_ERR_AUDIO_UNSCHANNEL VO_ERR_AUDIO_BASE | 0x0001 +#define VO_ERR_AUDIO_UNSSAMPLERATE VO_ERR_AUDIO_BASE | 0x0002 +#define VO_ERR_AUDIO_UNSFEATURE VO_ERR_AUDIO_BASE | 0x0003 + + +/** + *Enumeration used to define the possible audio coding formats. + */ +typedef enum VO_AUDIO_CODINGTYPE { + VO_AUDIO_CodingUnused = 0, /**< Placeholder value when coding is N/A */ + VO_AUDIO_CodingPCM, /**< Any variant of PCM coding */ + VO_AUDIO_CodingADPCM, /**< Any variant of ADPCM encoded data */ + VO_AUDIO_CodingAMRNB, /**< Any variant of AMR encoded data */ + VO_AUDIO_CodingAMRWB, /**< Any variant of AMR encoded data */ + VO_AUDIO_CodingAMRWBP, /**< Any variant of AMR encoded data */ + VO_AUDIO_CodingQCELP13, /**< Any variant of QCELP 13kbps encoded data */ + VO_AUDIO_CodingEVRC, /**< Any variant of EVRC encoded data */ + VO_AUDIO_CodingAAC, /**< Any variant of AAC encoded data, 0xA106 - ISO/MPEG-4 AAC, 0xFF - AAC */ + VO_AUDIO_CodingAC3, /**< Any variant of AC3 encoded data */ + VO_AUDIO_CodingFLAC, /**< Any variant of FLAC encoded data */ + VO_AUDIO_CodingMP1, /**< Any variant of MP1 encoded data */ + VO_AUDIO_CodingMP3, /**< Any variant of MP3 encoded data */ + VO_AUDIO_CodingOGG, /**< Any variant of OGG encoded data */ + VO_AUDIO_CodingWMA, /**< Any variant of WMA encoded data */ + VO_AUDIO_CodingRA, /**< Any variant of RA encoded data */ + VO_AUDIO_CodingMIDI, /**< Any variant of MIDI encoded data */ + VO_AUDIO_CodingDRA, /**< Any variant of dra encoded data */ + VO_AUDIO_CodingG729, /**< Any variant of dra encoded data */ + VO_AUDIO_Coding_MAX = VO_MAX_ENUM_VALUE +} VO_AUDIO_CODINGTYPE; + +/*! +* the channel type value +*/ +typedef enum { + VO_CHANNEL_CENTER = 1, /*!
    InputUsed is total used input data size in byte. + * \retval VO_ERR_NONE Succeeded. + * VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought. Continue to input + * data before next call. + */ + VO_U32 (VO_API * GetOutputData) (VO_HANDLE hCodec, VO_CODECBUFFER * pOutBuffer, VO_AUDIO_OUTPUTINFO * pOutInfo); + + /** + * Set the parameter for the specified param ID. + * \param hCodec [IN]] The codec handle which was created by Init function. + * \param uParamID [IN] The param ID. + * \param pData [IN] The param value. + * \retval VO_ERR_NONE Succeeded. + */ + VO_U32 (VO_API * SetParam) (VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData); + + /** + * Get the parameter for the specified param ID. + * \param hCodec [IN]] The codec handle which was created by Init function. + * \param uParamID [IN] The param ID. + * \param pData [IN] The param value. + * \retval VO_ERR_NONE Succeeded. + */ + VO_U32 (VO_API * GetParam) (VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData); + + /** + * Uninit the Codec. + * \param hCodec [IN]] The codec handle which was created by Init function. + * \retval VO_ERR_NONE Succeeded. + */ + VO_U32 (VO_API * Uninit) (VO_HANDLE hCodec); +} VO_AUDIO_CODECAPI; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __voAudio_H__ diff --git a/media/libstagefright/codecs/common/include/voIndex.h b/media/libstagefright/codecs/common/include/voIndex.h new file mode 100644 index 0000000000000000000000000000000000000000..541a0db9083d7b458febf2506d84124155d79999 --- /dev/null +++ b/media/libstagefright/codecs/common/include/voIndex.h @@ -0,0 +1,193 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: voIndex.h + + Content: module and ID definition + +*******************************************************************************/ + +#ifndef __voIndex_H__ +#define __voIndex_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "voType.h" + +/* Define the module ID */ +#define _MAKE_SOURCE_ID(id, name) \ +VO_INDEX_SRC_##name = _VO_INDEX_SOURCE | id, + +#define _MAKE_CODEC_ID(id, name) \ +VO_INDEX_DEC_##name = _VO_INDEX_DEC | id, \ +VO_INDEX_ENC_##name = _VO_INDEX_ENC | id, + +#define _MAKE_EFFECT_ID(id, name) \ +VO_INDEX_EFT_##name = _VO_INDEX_EFFECT | id, + +#define _MAKE_SINK_ID(id, name) \ +VO_INDEX_SNK_##name = _VO_INDEX_SINK | id, + +#define _MAKE_FILTER_ID(id, name) \ +VO_INDEX_FLT_##name = _VO_INDEX_FILTER | id, + +#define _MAKE_OMX_ID(id, name) \ +VO_INDEX_OMX_##name = _VO_INDEX_OMX | id, + +#define _MAKE_MFW_ID(id, name) \ +VO_INDEX_MFW_##name = _VO_INDEX_MFW | id, + +enum +{ + _VO_INDEX_SOURCE = 0x01000000, + _VO_INDEX_DEC = 0x02000000, + _VO_INDEX_ENC = 0x03000000, + _VO_INDEX_EFFECT = 0x04000000, + _VO_INDEX_SINK = 0x05000000, + _VO_INDEX_FILTER = 0x06000000, + _VO_INDEX_OMX = 0x07000000, + _VO_INDEX_MFW = 0x08000000, + + // define file parser modules + _MAKE_SOURCE_ID (0x010000, MP4) + _MAKE_SOURCE_ID (0x020000, AVI) + _MAKE_SOURCE_ID (0x030000, ASF) + _MAKE_SOURCE_ID (0x040000, REAL) + _MAKE_SOURCE_ID (0x050000, AUDIO) + _MAKE_SOURCE_ID (0x060000, FLASH) + _MAKE_SOURCE_ID (0x070000, OGG) + _MAKE_SOURCE_ID (0x080000, MKV) + + // define network source modules + _MAKE_SOURCE_ID (0x110000, RTSP) + _MAKE_SOURCE_ID (0x120000, HTTP) + + // define CMMB source modules + _MAKE_SOURCE_ID (0x200000, CMMB) + _MAKE_SOURCE_ID (0x210000, CMMB_INNO) + _MAKE_SOURCE_ID (0x220000, CMMB_TELE) + _MAKE_SOURCE_ID (0x230000, CMMB_SIANO) + + // define DVBT source modules + _MAKE_SOURCE_ID (0x300000, DVBT) + _MAKE_SOURCE_ID (0x310000, DVBT_DIBCOM) + + // define other source modules + _MAKE_SOURCE_ID (0x400000, ID3) + + // define video codec modules + _MAKE_CODEC_ID (0x010000, H264) + _MAKE_CODEC_ID (0x020000, MPEG4) + _MAKE_CODEC_ID (0x030000, H263) + _MAKE_CODEC_ID (0x040000, S263) + _MAKE_CODEC_ID (0x050000, RV) + _MAKE_CODEC_ID (0x060000, WMV) + _MAKE_CODEC_ID (0x070000, DIVX3) + _MAKE_CODEC_ID (0x080000, MJPEG) + _MAKE_CODEC_ID (0x090000, MPEG2) + _MAKE_CODEC_ID (0x0A0000, VP6) + + // define audio codec modules + _MAKE_CODEC_ID (0x210000, AAC) + _MAKE_CODEC_ID (0x220000, MP3) + _MAKE_CODEC_ID (0x230000, WMA) + _MAKE_CODEC_ID (0x240000, RA) + _MAKE_CODEC_ID (0x250000, AMRNB) + _MAKE_CODEC_ID (0x260000, AMRWB) + _MAKE_CODEC_ID (0x270000, AMRWBP) + _MAKE_CODEC_ID (0x280000, QCELP) + _MAKE_CODEC_ID (0x290000, EVRC) + _MAKE_CODEC_ID (0x2A0000, ADPCM) + _MAKE_CODEC_ID (0x2B0000, MIDI) + _MAKE_CODEC_ID (0x2C0000, AC3) + _MAKE_CODEC_ID (0x2D0000, FLAC) + _MAKE_CODEC_ID (0x2E0000, DRA) + _MAKE_CODEC_ID (0x2F0000, OGG) + _MAKE_CODEC_ID (0x300000, G729) + + // define image codec modules + _MAKE_CODEC_ID (0x410000, JPEG) + _MAKE_CODEC_ID (0x420000, GIF) + _MAKE_CODEC_ID (0x430000, PNG) + _MAKE_CODEC_ID (0x440000, TIF) + + // define effect modules + _MAKE_EFFECT_ID (0x010000, EQ) + + // define sink modules + _MAKE_SINK_ID (0x010000, VIDEO) + _MAKE_SINK_ID (0x020000, AUDIO) + _MAKE_SINK_ID (0x030000, CCRRR) + _MAKE_SINK_ID (0x040000, CCRRV) + + _MAKE_SINK_ID (0x110000, MP4) + _MAKE_SINK_ID (0x120000, AVI) + _MAKE_SINK_ID (0x130000, AFW) + + // define media frame module ID + _MAKE_MFW_ID (0x010000, VOMMPLAY) + _MAKE_MFW_ID (0x020000, VOMMREC) + _MAKE_MFW_ID (0x030000, VOME) +}; + + +/* define the error ID */ +#define VO_ERR_NONE 0x00000000 +#define VO_ERR_FINISH 0x00000001 +#define VO_ERR_BASE 0X80000000 +#define VO_ERR_FAILED 0x80000001 +#define VO_ERR_OUTOF_MEMORY 0x80000002 +#define VO_ERR_NOT_IMPLEMENT 0x80000003 +#define VO_ERR_INVALID_ARG 0x80000004 +#define VO_ERR_INPUT_BUFFER_SMALL 0x80000005 +#define VO_ERR_OUTPUT_BUFFER_SMALL 0x80000006 +#define VO_ERR_WRONG_STATUS 0x80000007 +#define VO_ERR_WRONG_PARAM_ID 0x80000008 +#define VO_ERR_LICENSE_ERROR 0x80000009 + +/* xxx is the module ID +#define VO_ERR_FAILED 0x8xxx0001 +#define VO_ERR_OUTOF_MEMORY 0x8xxx0002 +#define VO_ERR_NOT_IMPLEMENT 0x8xxx0003 +#define VO_ERR_INVALID_ARG 0x8xxx0004 +#define VO_ERR_INPUT_BUFFER_SMALL 0x8xxx0005 +#define VO_ERR_OUTPUT_BUFFER_SMALL 0x8xxx0006 +#define VO_ERR_WRONG_STATUS 0x8xxx0007 +#define VO_ERR_WRONG_PARAM_ID 0x8xxx0008 +#define VO_ERR_LICENSE_ERROR 0x8xxx0009 +// Module own error ID +#define VO_ERR_Module 0x8xxx0X00 +*/ + +#define VO_PID_COMMON_BASE 0x40000000 /*!< The base of common param ID */ +#define VO_PID_COMMON_QUERYMEM (VO_PID_COMMON_BASE | 0X0001) /*!< Query the memory needed; Reserved. */ +#define VO_PID_COMMON_INPUTTYPE (VO_PID_COMMON_BASE | 0X0002) /*!< Set or get the input buffer type. VO_INPUT_TYPE */ +#define VO_PID_COMMON_HASRESOURCE (VO_PID_COMMON_BASE | 0X0003) /*!< Query it has resource to be used. VO_U32 *, 1 have, 0 No */ +#define VO_PID_COMMON_HEADDATA (VO_PID_COMMON_BASE | 0X0004) /*!< Decoder track header data. VO_CODECBUFFER * */ +#define VO_PID_COMMON_FLUSH (VO_PID_COMMON_BASE | 0X0005) /*!< Flush the codec buffer. VO_U32 *, 1 Flush, 0 No * */ + +/* +// Module Param ID +#define VO_ID_Mdoule 0x0xxx1000 +*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __voIndex_H__ diff --git a/media/libstagefright/codecs/common/include/voMem.h b/media/libstagefright/codecs/common/include/voMem.h new file mode 100644 index 0000000000000000000000000000000000000000..8dfb634d51b64bd2902d8fed9f26ecfdbd9e5ba1 --- /dev/null +++ b/media/libstagefright/codecs/common/include/voMem.h @@ -0,0 +1,65 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: voMem.h + + Content: memory functions & data structures + +*******************************************************************************/ + +#ifndef __voMem_H__ +#define __voMem_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "voIndex.h" + +typedef struct +{ + VO_S32 Size; /*!< Buffer stride */ + VO_S32 Flag; + VO_PTR VBuffer; /*!< user data pointer */ + VO_PTR PBuffer; /*!< user data pointer */ +} +VO_MEM_INFO; + +typedef struct VO_MEM_OPERATOR +{ + VO_U32 (VO_API * Alloc) (VO_S32 uID, VO_MEM_INFO * pMemInfo); + VO_U32 (VO_API * Free) (VO_S32 uID, VO_PTR pBuff); + VO_U32 (VO_API * Set) (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize); + VO_U32 (VO_API * Copy) (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize); + VO_U32 (VO_API * Check) (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize); + VO_S32 (VO_API * Compare) (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize); + VO_U32 (VO_API * Move) (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize); +} VO_MEM_OPERATOR; + +#define voMemAlloc(pBuff, pMemOP, ID, nSize) \ +{ \ + VO_MEM_INFO voMemInfo; \ + voMemInfo.Size=nSize; \ + pMemOP->Alloc(ID, &voMemInfo); \ + pBuff=(VO_PBYTE)voMemInfo.VBuffer; \ +} + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // __voMem_H__ diff --git a/media/libstagefright/codecs/common/include/voType.h b/media/libstagefright/codecs/common/include/voType.h new file mode 100644 index 0000000000000000000000000000000000000000..2669134738be835b92cb24237d889ed7d868e5de --- /dev/null +++ b/media/libstagefright/codecs/common/include/voType.h @@ -0,0 +1,221 @@ +/* + ** Copyright 2003-2010, VisualOn, Inc. + ** + ** 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. + */ +/******************************************************************************* + File: voType.h + + Content: data type definition + +*******************************************************************************/ +#ifndef __voType_H__ +#define __voType_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef _WIN32 +# define VO_API __cdecl +# define VO_CBI __stdcall +#else +# define VO_API +# define VO_CBI +#endif //_WIN32 + +/** VO_IN is used to identify inputs to an VO 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 VO_IN +#define VO_IN +#endif + +/** VO_OUT is used to identify outputs from an VO 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 VO_OUT +#define VO_OUT +#endif + +/** VO_INOUT is used to identify parameters that may be either inputs or + outputs from an VO 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 VO_INOUT +#define VO_INOUT +#endif + +#define VO_MAX_ENUM_VALUE 0X7FFFFFFF + +/** VO_VOID */ +typedef void VO_VOID; + +/** VO_U8 is an 8 bit unsigned quantity that is byte aligned */ +typedef unsigned char VO_U8; + +/** VO_BYTE is an 8 bit unsigned quantity that is byte aligned */ +typedef unsigned char VO_BYTE; + +/** VO_S8 is an 8 bit signed quantity that is byte aligned */ +typedef signed char VO_S8; + +/** VO_CHAR is an 8 bit signed quantity that is byte aligned */ +typedef char VO_CHAR; + +/** VO_U16 is a 16 bit unsigned quantity that is 16 bit word aligned */ +typedef unsigned short VO_U16; + +/** VO_WCHAR is a 16 bit unsigned quantity that is 16 bit word aligned */ +#if defined _WIN32 +typedef unsigned short VO_WCHAR; +typedef unsigned short* VO_PWCHAR; +#elif defined LINUX +typedef unsigned char VO_WCHAR; +typedef unsigned char* VO_PWCHAR; +#endif + +/** VO_S16 is a 16 bit signed quantity that is 16 bit word aligned */ +typedef signed short VO_S16; + +/** VO_U32 is a 32 bit unsigned quantity that is 32 bit word aligned */ +typedef unsigned long VO_U32; + +/** VO_S32 is a 32 bit signed quantity that is 32 bit word aligned */ +typedef signed long VO_S32; + +/* Users with compilers that cannot accept the "long long" designation should + define the VO_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 VO_SKIP64BIT +#ifdef _WIN32 +/** VO_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ +typedef unsigned __int64 VO_U64; +/** VO_S64 is a 64 bit signed quantity that is 64 bit word aligned */ +typedef signed __int64 VO_S64; +#else // WIN32 +/** VO_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ +typedef unsigned long long VO_U64; +/** VO_S64 is a 64 bit signed quantity that is 64 bit word aligned */ +typedef signed long long VO_S64; +#endif // WIN32 +#endif // VO_SKIP64BIT + +/** The VO_BOOL type is intended to be used to represent a true or a false + value when passing parameters to and from the VO core and components. The + VO_BOOL is a 32 bit quantity and is aligned on a 32 bit word boundary. + */ +typedef enum VO_BOOL { + VO_FALSE = 0, + VO_TRUE = !VO_FALSE, + VO_BOOL_MAX = VO_MAX_ENUM_VALUE +} VO_BOOL; + +/** The VO_PTR type is intended to be used to pass pointers between the VO + applications and the VO Core and components. This is a 32 bit pointer and + is aligned on a 32 bit boundary. + */ +typedef void* VO_PTR; + +/** The VO_HANDLE type is intended to be used to pass pointers between the VO + applications and the VO Core and components. This is a 32 bit pointer and + is aligned on a 32 bit boundary. + */ +typedef void* VO_HANDLE; + +/** The VO_STRING type is intended to be used to pass "C" type strings between + the application and the core and component. The VO_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* VO_PCHAR; + +/** The VO_PBYTE type is intended to be used to pass arrays of bytes such as + buffers between the application and the component and core. The VO_PBYTE + 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* VO_PBYTE; + +/** The VO_PTCHAR type is intended to be used to pass arrays of wchar such as + unicode char between the application and the component and core. The VO_PTCHAR + type is a 32 bit pointer to a zero terminated string. The pointer is word + aligned and the string is byte aligned. + */ +/* +#if !defined LINUX +typedef unsigned short* VO_PTCHAR; +typedef unsigned short* VO_TCHAR; +#else +typedef char* VO_PTCHAR; +typedef char VO_TCHAR; +#endif +*/ + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +/** + * Input stream format, Frame or Stream.. + */ +typedef enum { + VO_INPUT_FRAME = 1, /*!< Input contains completely frame(s) data. */ + VO_INPUT_STREAM, /*!< Input is stream data. */ + VO_INPUT_STREAM_MAX = VO_MAX_ENUM_VALUE +} VO_INPUT_TYPE; + + +/** + * General data buffer, used as input or output. + */ +typedef struct { + VO_PBYTE Buffer; /*!< Buffer pointer */ + VO_U32 Length; /*!< Buffer size in byte */ + VO_S64 Time; /*!< The time of the buffer */ +} VO_CODECBUFFER; + + +/** + * The init memdata flag. + */ +typedef enum{ + VO_IMF_USERMEMOPERATOR =0, /*!< memData is the pointer of memoperator function*/ + VO_IMF_PREALLOCATEDBUFFER =1, /*!< memData is preallocated memory*/ + VO_IMF_MAX = VO_MAX_ENUM_VALUE +}VO_INIT_MEM_FlAG; + + +/** + * The init memory structure.. + */ +typedef struct{ + VO_INIT_MEM_FlAG memflag; /*! + +#include "VPXDecoder.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "vpx_codec/vpx_decoder.h" +#include "vp8/vp8dx.h" + +namespace android { + +VPXDecoder::VPXDecoder(const sp &source) + : mSource(source), + mStarted(false), + mBufferSize(0), + mCtx(NULL), + mBufferGroup(NULL) { + sp inputFormat = source->getFormat(); + const char *mime; + CHECK(inputFormat->findCString(kKeyMIMEType, &mime)); + CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_VPX)); + + CHECK(inputFormat->findInt32(kKeyWidth, &mWidth)); + CHECK(inputFormat->findInt32(kKeyHeight, &mHeight)); + + mBufferSize = (mWidth * mHeight * 3) / 2; + + mFormat = new MetaData; + mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); + mFormat->setInt32(kKeyWidth, mWidth); + mFormat->setInt32(kKeyHeight, mHeight); + mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar); + mFormat->setCString(kKeyDecoderComponent, "VPXDecoder"); + + int64_t durationUs; + if (inputFormat->findInt64(kKeyDuration, &durationUs)) { + mFormat->setInt64(kKeyDuration, durationUs); + } +} + +VPXDecoder::~VPXDecoder() { + if (mStarted) { + stop(); + } +} + +status_t VPXDecoder::start(MetaData *) { + if (mStarted) { + return UNKNOWN_ERROR; + } + + status_t err = mSource->start(); + + if (err != OK) { + return err; + } + + mCtx = new vpx_codec_ctx_t; + if (vpx_codec_dec_init( + (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, NULL, 0)) { + LOGE("on2 decoder failed to initialize."); + + mSource->stop(); + + return UNKNOWN_ERROR; + } + + mBufferGroup = new MediaBufferGroup; + mBufferGroup->add_buffer(new MediaBuffer(mBufferSize)); + mBufferGroup->add_buffer(new MediaBuffer(mBufferSize)); + + mStarted = true; + + return OK; +} + +status_t VPXDecoder::stop() { + if (!mStarted) { + return UNKNOWN_ERROR; + } + + delete mBufferGroup; + mBufferGroup = NULL; + + vpx_codec_destroy((vpx_codec_ctx_t *)mCtx); + delete (vpx_codec_ctx_t *)mCtx; + mCtx = NULL; + + mSource->stop(); + + mStarted = false; + + return OK; +} + +sp VPXDecoder::getFormat() { + return mFormat; +} + +status_t VPXDecoder::read( + MediaBuffer **out, const ReadOptions *options) { + *out = NULL; + + MediaBuffer *input; + status_t err = mSource->read(&input, options); + + if (err != OK) { + return err; + } + + LOGV("read %d bytes from source\n", input->range_length()); + + if (vpx_codec_decode( + (vpx_codec_ctx_t *)mCtx, + (uint8_t *)input->data() + input->range_offset(), + input->range_length(), + NULL, + 0)) { + LOGE("on2 decoder failed to decode frame."); + input->release(); + input = NULL; + + return UNKNOWN_ERROR; + } + + LOGV("successfully decoded 1 or more frames."); + + int64_t timeUs; + CHECK(input->meta_data()->findInt64(kKeyTime, &timeUs)); + + input->release(); + input = NULL; + + vpx_codec_iter_t iter = NULL; + vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter); + + if (img == NULL) { + LOGI("on2 decoder did not return a frame."); + + *out = new MediaBuffer(0); + return OK; + } + + CHECK_EQ(img->fmt, IMG_FMT_I420); + + int32_t width = img->d_w; + int32_t height = img->d_h; + + if (width != mWidth || height != mHeight) { + LOGI("Image dimensions changed, width = %d, height = %d", + width, height); + + mWidth = width; + mHeight = height; + mFormat->setInt32(kKeyWidth, width); + mFormat->setInt32(kKeyHeight, height); + + mBufferSize = (mWidth * mHeight * 3) / 2; + delete mBufferGroup; + mBufferGroup = new MediaBufferGroup; + mBufferGroup->add_buffer(new MediaBuffer(mBufferSize)); + mBufferGroup->add_buffer(new MediaBuffer(mBufferSize)); + + return INFO_FORMAT_CHANGED; + } + + MediaBuffer *output; + CHECK_EQ(mBufferGroup->acquire_buffer(&output), OK); + + const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y]; + uint8_t *dst = (uint8_t *)output->data(); + for (size_t i = 0; i < img->d_h; ++i) { + memcpy(dst, srcLine, img->d_w); + + srcLine += img->stride[PLANE_Y]; + dst += img->d_w; + } + + srcLine = (const uint8_t *)img->planes[PLANE_U]; + for (size_t i = 0; i < img->d_h / 2; ++i) { + memcpy(dst, srcLine, img->d_w / 2); + + srcLine += img->stride[PLANE_U]; + dst += img->d_w / 2; + } + + srcLine = (const uint8_t *)img->planes[PLANE_V]; + for (size_t i = 0; i < img->d_h / 2; ++i) { + memcpy(dst, srcLine, img->d_w / 2); + + srcLine += img->stride[PLANE_V]; + dst += img->d_w / 2; + } + + output->set_range(0, (width * height * 3) / 2); + + output->meta_data()->setInt64(kKeyTime, timeUs); + + *out = output; + + return OK; +} + +} // namespace android + diff --git a/media/libstagefright/include/AACEncoder.h b/media/libstagefright/include/AACEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..211a332eddb110bffe4f1121c96e40aefd3bbb88 --- /dev/null +++ b/media/libstagefright/include/AACEncoder.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 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 AAC_ENCODER_H +#define AAC_ENCODER_H + +#include +#include + +struct VO_AUDIO_CODECAPI; +struct VO_MEM_OPERATOR; + +namespace android { + +struct MediaBufferGroup; + +class AACEncoder: public MediaSource { + public: + AACEncoder(const sp &source, const sp &meta); + + virtual status_t start(MetaData *params); + virtual status_t stop(); + virtual sp getFormat(); + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options); + + + protected: + virtual ~AACEncoder(); + + private: + sp mSource; + sp mMeta; + bool mStarted; + MediaBufferGroup *mBufferGroup; + MediaBuffer *mInputBuffer; + status_t mInitCheck; + int32_t mSampleRate; + int32_t mChannels; + int32_t mBitRate; + int32_t mFrameCount; + uint8_t mAudioSpecificConfigData[2]; // auido specific data + void *mEncoderHandle; + VO_AUDIO_CODECAPI *mApiHandle; + VO_MEM_OPERATOR *mMemOperator; + + status_t setAudioSpecificConfigData(); + status_t initCheck(); + + AACEncoder& operator=(const AACEncoder &rhs); + AACEncoder(const AACEncoder& copy); + +}; + +} + +#endif //#ifndef AAC_ENCODER_H + diff --git a/media/libstagefright/include/AMRNBEncoder.h b/media/libstagefright/include/AMRNBEncoder.h index 7167c0096f5bddd2d292e8ab3ef1552831f13137..71160e67ebbb40dc78464f3e469bde506cf57ca1 100644 --- a/media/libstagefright/include/AMRNBEncoder.h +++ b/media/libstagefright/include/AMRNBEncoder.h @@ -19,13 +19,14 @@ #define AMR_NB_ENCODER_H_ #include +#include namespace android { struct MediaBufferGroup; struct AMRNBEncoder : public MediaSource { - AMRNBEncoder(const sp &source); + AMRNBEncoder(const sp &source, const sp &meta); virtual status_t start(MetaData *params); virtual status_t stop(); @@ -40,6 +41,7 @@ protected: private: sp mSource; + sp mMeta; bool mStarted; MediaBufferGroup *mBufferGroup; diff --git a/media/libstagefright/include/AMRWBEncoder.h b/media/libstagefright/include/AMRWBEncoder.h new file mode 100644 index 0000000000000000000000000000000000000000..f2d155fa13b82ae4b41cea97bab529043103def5 --- /dev/null +++ b/media/libstagefright/include/AMRWBEncoder.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 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 AMR_WB_ENCODER_H +#define AMR_WB_ENCODER_H + +#include +#include + +struct VO_AUDIO_CODECAPI; +struct VO_MEM_OPERATOR; + +namespace android { + +struct MediaBufferGroup; + +class AMRWBEncoder: public MediaSource { + public: + AMRWBEncoder(const sp &source, const sp &meta); + + virtual status_t start(MetaData *params); + virtual status_t stop(); + virtual sp getFormat(); + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options); + + + protected: + virtual ~AMRWBEncoder(); + + private: + sp mSource; + sp mMeta; + bool mStarted; + MediaBufferGroup *mBufferGroup; + MediaBuffer *mInputBuffer; + status_t mInitCheck; + int32_t mBitRate; + void *mEncoderHandle; + VO_AUDIO_CODECAPI *mApiHandle; + VO_MEM_OPERATOR *mMemOperator; + + int64_t mAnchorTimeUs; + int64_t mNumFramesOutput; + + int16_t mInputFrame[320]; + int32_t mNumInputSamples; + + status_t initCheck(); + + AMRWBEncoder& operator=(const AMRWBEncoder &rhs); + AMRWBEncoder(const AMRWBEncoder& copy); + +}; + +} + +#endif //#ifndef AMR_WB_ENCODER_H + diff --git a/media/libstagefright/include/VPXDecoder.h b/media/libstagefright/include/VPXDecoder.h new file mode 100644 index 0000000000000000000000000000000000000000..550c6120cd1f94b9302c283fb28b54c9726d5ac2 --- /dev/null +++ b/media/libstagefright/include/VPXDecoder.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 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 VPX_DECODER_H_ + +#define VPX_DECODER_H_ + +#include +#include + +namespace android { + +struct MediaBufferGroup; + +struct VPXDecoder : public MediaSource { + VPXDecoder(const sp &source); + + virtual status_t start(MetaData *params); + virtual status_t stop(); + + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options); + +protected: + virtual ~VPXDecoder(); + +private: + sp mSource; + bool mStarted; + int32_t mWidth, mHeight; + size_t mBufferSize; + + void *mCtx; + MediaBufferGroup *mBufferGroup; + + sp mFormat; + + VPXDecoder(const VPXDecoder &); + VPXDecoder &operator=(const VPXDecoder &); +}; + +} // namespace android + +#endif // VPX_DECODER_H_ + diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..0e7219893adba35b71d63aba72e01b13d93f458d --- /dev/null +++ b/media/libstagefright/matroska/Android.mk @@ -0,0 +1,16 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + MatroskaExtractor.cpp \ + mkvparser.cpp \ + +LOCAL_C_INCLUDES:= \ + $(JNI_H_INCLUDE) \ + $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \ + +LOCAL_CFLAGS += -Wno-multichar + +LOCAL_MODULE:= libstagefright_matroska + +include $(BUILD_STATIC_LIBRARY) diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..339a7b5a57e9fc9d471ec40d9b47dcfb875c771b --- /dev/null +++ b/media/libstagefright/matroska/MatroskaExtractor.cpp @@ -0,0 +1,594 @@ +/* + * Copyright (C) 2010 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. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "MatroskaExtractor" +#include + +#include "MatroskaExtractor.h" + +#include "mkvparser.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +struct DataSourceReader : public mkvparser::IMkvReader { + DataSourceReader(const sp &source) + : mSource(source) { + } + + virtual int Read(long long position, long length, unsigned char* buffer) { + CHECK(position >= 0); + CHECK(length >= 0); + + if (length == 0) { + return 0; + } + + ssize_t n = mSource->readAt(position, buffer, length); + + if (n <= 0) { + return -1; + } + + return 0; + } + + virtual int Length(long long* total, long long* available) { + off_t size; + if (mSource->getSize(&size) != OK) { + return -1; + } + + if (total) { + *total = size; + } + + if (available) { + *available = size; + } + + return 0; + } + +private: + sp mSource; + + DataSourceReader(const DataSourceReader &); + DataSourceReader &operator=(const DataSourceReader &); +}; + +//////////////////////////////////////////////////////////////////////////////// + +#include +static void hexdump(const void *_data, size_t size) { + const uint8_t *data = (const uint8_t *)_data; + size_t offset = 0; + while (offset < size) { + printf("0x%04x ", offset); + + size_t n = size - offset; + if (n > 16) { + n = 16; + } + + for (size_t i = 0; i < 16; ++i) { + if (i == 8) { + printf(" "); + } + + if (offset + i < size) { + printf("%02x ", data[offset + i]); + } else { + printf(" "); + } + } + + printf(" "); + + for (size_t i = 0; i < n; ++i) { + if (isprint(data[offset + i])) { + printf("%c", data[offset + i]); + } else { + printf("."); + } + } + + printf("\n"); + + offset += 16; + } +} + +struct BlockIterator { + BlockIterator(mkvparser::Segment *segment, unsigned long trackNum); + + bool eos() const; + + void advance(); + void reset(); + void seek(int64_t seekTimeUs); + + const mkvparser::Block *block() const; + int64_t blockTimeUs() const; + +private: + mkvparser::Segment *mSegment; + unsigned long mTrackNum; + + mkvparser::Cluster *mCluster; + const mkvparser::BlockEntry *mBlockEntry; + + BlockIterator(const BlockIterator &); + BlockIterator &operator=(const BlockIterator &); +}; + +struct MatroskaSource : public MediaSource { + MatroskaSource( + const sp &extractor, size_t index); + + virtual status_t start(MetaData *params); + virtual status_t stop(); + + virtual sp getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options); + +private: + enum Type { + AVC, + AAC, + OTHER + }; + + sp mExtractor; + size_t mTrackIndex; + Type mType; + BlockIterator mBlockIter; + + status_t advance(); + + MatroskaSource(const MatroskaSource &); + MatroskaSource &operator=(const MatroskaSource &); +}; + +MatroskaSource::MatroskaSource( + const sp &extractor, size_t index) + : mExtractor(extractor), + mTrackIndex(index), + mType(OTHER), + mBlockIter(mExtractor->mSegment, + mExtractor->mTracks.itemAt(index).mTrackNum) { + const char *mime; + CHECK(mExtractor->mTracks.itemAt(index).mMeta-> + findCString(kKeyMIMEType, &mime)); + + if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { + mType = AVC; + } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { + mType = AAC; + } +} + +status_t MatroskaSource::start(MetaData *params) { + mBlockIter.reset(); + + return OK; +} + +status_t MatroskaSource::stop() { + return OK; +} + +sp MatroskaSource::getFormat() { + return mExtractor->mTracks.itemAt(mTrackIndex).mMeta; +} + +//////////////////////////////////////////////////////////////////////////////// + +BlockIterator::BlockIterator( + mkvparser::Segment *segment, unsigned long trackNum) + : mSegment(segment), + mTrackNum(trackNum), + mCluster(NULL), + mBlockEntry(NULL) { + reset(); +} + +bool BlockIterator::eos() const { + return mCluster == NULL || mCluster->EOS(); +} + +void BlockIterator::advance() { + while (!eos()) { + if (mBlockEntry != NULL) { + mBlockEntry = mCluster->GetNext(mBlockEntry); + } else if (mCluster != NULL) { + mCluster = mSegment->GetNext(mCluster); + + if (eos()) { + break; + } + + mBlockEntry = mCluster->GetFirst(); + } + + if (mBlockEntry != NULL + && mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) { + break; + } + } +} + +void BlockIterator::reset() { + mCluster = mSegment->GetFirst(); + mBlockEntry = mCluster->GetFirst(); + + while (!eos() && block()->GetTrackNumber() != mTrackNum) { + advance(); + } +} + +void BlockIterator::seek(int64_t seekTimeUs) { + mCluster = mSegment->GetCluster(seekTimeUs * 1000ll); + mBlockEntry = mCluster != NULL ? mCluster->GetFirst() : NULL; + + while (!eos() && block()->GetTrackNumber() != mTrackNum) { + advance(); + } + + while (!eos() && !mBlockEntry->GetBlock()->IsKey()) { + advance(); + } +} + +const mkvparser::Block *BlockIterator::block() const { + CHECK(!eos()); + + return mBlockEntry->GetBlock(); +} + +int64_t BlockIterator::blockTimeUs() const { + return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; +} + +//////////////////////////////////////////////////////////////////////////////// + +status_t MatroskaSource::read( + MediaBuffer **out, const ReadOptions *options) { + *out = NULL; + + int64_t seekTimeUs; + if (options && options->getSeekTo(&seekTimeUs)) { + mBlockIter.seek(seekTimeUs); + } + + if (mBlockIter.eos()) { + return ERROR_END_OF_STREAM; + } + + const mkvparser::Block *block = mBlockIter.block(); + size_t size = block->GetSize(); + int64_t timeUs = mBlockIter.blockTimeUs(); + + MediaBuffer *buffer = new MediaBuffer(size + 2); + buffer->meta_data()->setInt64(kKeyTime, timeUs); + + long res = block->Read( + mExtractor->mReader, (unsigned char *)buffer->data() + 2); + + if (res != 0) { + return ERROR_END_OF_STREAM; + } + + buffer->set_range(2, size); + + if (mType == AVC) { + CHECK(size >= 2); + + uint8_t *data = (uint8_t *)buffer->data(); + + unsigned NALsize = data[2] << 8 | data[3]; + CHECK_EQ(size, NALsize + 2); + + memcpy(data, "\x00\x00\x00\x01", 4); + buffer->set_range(0, size + 2); + } else if (mType == AAC) { + // There's strange junk at the beginning... + + const uint8_t *data = (const uint8_t *)buffer->data() + 2; + size_t offset = 0; + while (offset < size && data[offset] != 0x21) { + ++offset; + } + buffer->set_range(2 + offset, size - offset); + } + + *out = buffer; + +#if 0 + hexdump((const uint8_t *)buffer->data() + buffer->range_offset(), + buffer->range_length()); +#endif + + mBlockIter.advance(); + + return OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +MatroskaExtractor::MatroskaExtractor(const sp &source) + : mDataSource(source), + mReader(new DataSourceReader(mDataSource)), + mSegment(NULL), + mExtractedThumbnails(false) { + mkvparser::EBMLHeader ebmlHeader; + long long pos; + if (ebmlHeader.Parse(mReader, pos) < 0) { + return; + } + + long long ret = + mkvparser::Segment::CreateInstance(mReader, pos, mSegment); + + if (ret) { + CHECK(mSegment == NULL); + return; + } + + ret = mSegment->Load(); + + if (ret < 0) { + delete mSegment; + mSegment = NULL; + return; + } + + addTracks(); +} + +MatroskaExtractor::~MatroskaExtractor() { + delete mSegment; + mSegment = NULL; + + delete mReader; + mReader = NULL; +} + +size_t MatroskaExtractor::countTracks() { + return mTracks.size(); +} + +sp MatroskaExtractor::getTrack(size_t index) { + if (index >= mTracks.size()) { + return NULL; + } + + return new MatroskaSource(this, index); +} + +sp MatroskaExtractor::getTrackMetaData( + size_t index, uint32_t flags) { + if (index >= mTracks.size()) { + return NULL; + } + + if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails) { + findThumbnails(); + mExtractedThumbnails = true; + } + + return mTracks.itemAt(index).mMeta; +} + +static void addESDSFromAudioSpecificInfo( + const sp &meta, const void *asi, size_t asiSize) { + static const uint8_t kStaticESDS[] = { + 0x03, 22, + 0x00, 0x00, // ES_ID + 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag + + 0x04, 17, + 0x40, // Audio ISO/IEC 14496-3 + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + 0x05, + // AudioSpecificInfo (with size prefix) follows + }; + + CHECK(asiSize < 128); + size_t esdsSize = sizeof(kStaticESDS) + asiSize + 1; + uint8_t *esds = new uint8_t[esdsSize]; + memcpy(esds, kStaticESDS, sizeof(kStaticESDS)); + uint8_t *ptr = esds + sizeof(kStaticESDS); + *ptr++ = asiSize; + memcpy(ptr, asi, asiSize); + + meta->setData(kKeyESDS, 0, esds, esdsSize); + + delete[] esds; + esds = NULL; +} + +void addVorbisCodecInfo( + const sp &meta, + const void *_codecPrivate, size_t codecPrivateSize) { + // printf("vorbis private data follows:\n"); + // hexdump(_codecPrivate, codecPrivateSize); + + CHECK(codecPrivateSize >= 3); + + const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; + CHECK(codecPrivate[0] == 0x02); + + size_t len1 = codecPrivate[1]; + size_t len2 = codecPrivate[2]; + + CHECK(codecPrivateSize > 3 + len1 + len2); + + CHECK(codecPrivate[3] == 0x01); + meta->setData(kKeyVorbisInfo, 0, &codecPrivate[3], len1); + + CHECK(codecPrivate[len1 + 3] == 0x03); + + CHECK(codecPrivate[len1 + len2 + 3] == 0x05); + meta->setData( + kKeyVorbisBooks, 0, &codecPrivate[len1 + len2 + 3], + codecPrivateSize - len1 - len2 - 3); +} + +void MatroskaExtractor::addTracks() { + const mkvparser::Tracks *tracks = mSegment->GetTracks(); + + for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { + const mkvparser::Track *track = tracks->GetTrackByIndex(index); + + const char *const codecID = track->GetCodecId(); + LOGV("codec id = %s", codecID); + LOGV("codec name = %s", track->GetCodecNameAsUTF8()); + + size_t codecPrivateSize; + const unsigned char *codecPrivate = + track->GetCodecPrivate(&codecPrivateSize); + + enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; + + sp meta = new MetaData; + + switch (track->GetType()) { + case VIDEO_TRACK: + { + const mkvparser::VideoTrack *vtrack = + static_cast(track); + + if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { + meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); + meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); + } else if (!strcmp("V_VP8", codecID)) { + meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX); + } else { + continue; + } + + meta->setInt32(kKeyWidth, vtrack->GetWidth()); + meta->setInt32(kKeyHeight, vtrack->GetHeight()); + break; + } + + case AUDIO_TRACK: + { + const mkvparser::AudioTrack *atrack = + static_cast(track); + + if (!strcmp("A_AAC", codecID)) { + meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); + CHECK(codecPrivateSize >= 2); + + addESDSFromAudioSpecificInfo( + meta, codecPrivate, codecPrivateSize); + } else if (!strcmp("A_VORBIS", codecID)) { + meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); + + addVorbisCodecInfo(meta, codecPrivate, codecPrivateSize); + } else { + continue; + } + + meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); + meta->setInt32(kKeyChannelCount, atrack->GetChannels()); + break; + } + + default: + continue; + } + + long long durationNs = mSegment->GetDuration(); + meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); + + mTracks.push(); + TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1); + trackInfo->mTrackNum = track->GetNumber(); + trackInfo->mMeta = meta; + } +} + +void MatroskaExtractor::findThumbnails() { + for (size_t i = 0; i < mTracks.size(); ++i) { + TrackInfo *info = &mTracks.editItemAt(i); + + const char *mime; + CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); + + if (strncasecmp(mime, "video/", 6)) { + continue; + } + + BlockIterator iter(mSegment, info->mTrackNum); + int32_t i = 0; + int64_t thumbnailTimeUs = 0; + size_t maxBlockSize = 0; + while (!iter.eos() && i < 20) { + if (iter.block()->IsKey()) { + ++i; + + size_t blockSize = iter.block()->GetSize(); + if (blockSize > maxBlockSize) { + maxBlockSize = blockSize; + thumbnailTimeUs = iter.blockTimeUs(); + } + } + iter.advance(); + } + info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); + } +} + +sp MatroskaExtractor::getMetaData() { + sp meta = new MetaData; + meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MATROSKA); + + return meta; +} + +bool SniffMatroska( + const sp &source, String8 *mimeType, float *confidence) { + DataSourceReader reader(source); + mkvparser::EBMLHeader ebmlHeader; + long long pos; + if (ebmlHeader.Parse(&reader, pos) < 0) { + return false; + } + + mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); + *confidence = 0.6; + + return true; +} + +} // namespace android diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h new file mode 100644 index 0000000000000000000000000000000000000000..747184852a7a0785432824dabc91774d9ae1bc32 --- /dev/null +++ b/media/libstagefright/matroska/MatroskaExtractor.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 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 MATROSKA_EXTRACTOR_H_ + +#define MATROSKA_EXTRACTOR_H_ + +#include +#include + +namespace mkvparser { +struct Segment; +}; + +namespace android { + +class String8; + +struct DataSourceReader; +struct MatroskaSource; + +struct MatroskaExtractor : public MediaExtractor { + MatroskaExtractor(const sp &source); + + virtual size_t countTracks(); + + virtual sp getTrack(size_t index); + + virtual sp getTrackMetaData( + size_t index, uint32_t flags); + + virtual sp getMetaData(); + +protected: + virtual ~MatroskaExtractor(); + +private: + friend struct MatroskaSource; + + struct TrackInfo { + unsigned long mTrackNum; + sp mMeta; + }; + Vector mTracks; + + sp mDataSource; + DataSourceReader *mReader; + mkvparser::Segment *mSegment; + bool mExtractedThumbnails; + + void addTracks(); + void findThumbnails(); + + MatroskaExtractor(const MatroskaExtractor &); + MatroskaExtractor &operator=(const MatroskaExtractor &); +}; + +bool SniffMatroska( + const sp &source, String8 *mimeType, float *confidence); + +} // namespace android + +#endif // MATROSKA_EXTRACTOR_H_ diff --git a/media/libstagefright/matroska/mkvparser.cpp b/media/libstagefright/matroska/mkvparser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e51004b487a1dedbe2c655137e8afc14b448041 --- /dev/null +++ b/media/libstagefright/matroska/mkvparser.cpp @@ -0,0 +1,3103 @@ +#include "mkvparser.hpp" +#include +#include + +mkvparser::IMkvReader::~IMkvReader() +{ +} + +long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len) +{ + assert(pReader); + assert(pos >= 0); + + long long total, available; + + long hr = pReader->Length(&total, &available); + assert(hr >= 0); + assert(pos < available); + assert((available - pos) >= 1); //assume here max u-int len is 8 + + unsigned char b; + + hr = pReader->Read(pos, 1, &b); + if (hr < 0) + return hr; + + assert(hr == 0L); + + if (b & 0x80) //1000 0000 + { + len = 1; + b &= 0x7F; //0111 1111 + } + else if (b & 0x40) //0100 0000 + { + len = 2; + b &= 0x3F; //0011 1111 + } + else if (b & 0x20) //0010 0000 + { + len = 3; + b &= 0x1F; //0001 1111 + } + else if (b & 0x10) //0001 0000 + { + len = 4; + b &= 0x0F; //0000 1111 + } + else if (b & 0x08) //0000 1000 + { + len = 5; + b &= 0x07; //0000 0111 + } + else if (b & 0x04) //0000 0100 + { + len = 6; + b &= 0x03; //0000 0011 + } + else if (b & 0x02) //0000 0010 + { + len = 7; + b &= 0x01; //0000 0001 + } + else + { + assert(b & 0x01); //0000 0001 + len = 8; + b = 0; //0000 0000 + } + + assert((available - pos) >= len); + + long long result = b; + ++pos; + for (long i = 1; i < len; ++i) + { + hr = pReader->Read(pos, 1, &b); + + if (hr < 0) + return hr; + + assert(hr == 0L); + + result <<= 8; + result |= b; + + ++pos; + } + + return result; +} + + +long long mkvparser::GetUIntLength( + IMkvReader* pReader, + long long pos, + long& len) +{ + assert(pReader); + assert(pos >= 0); + + long long total, available; + + long hr = pReader->Length(&total, &available); + assert(hr >= 0); + assert(available <= total); + + if (pos >= available) + return pos; //too few bytes available + + unsigned char b; + + hr = pReader->Read(pos, 1, &b); + + if (hr < 0) + return hr; + + assert(hr == 0L); + + if (b == 0) //we can't handle u-int values larger than 8 bytes + return E_FILE_FORMAT_INVALID; + + unsigned char m = 0x80; + len = 1; + + while (!(b & m)) + { + m >>= 1; + ++len; + } + + return 0; //success +} + + +long long mkvparser::SyncReadUInt( + IMkvReader* pReader, + long long pos, + long long stop, + long& len) +{ + assert(pReader); + + if (pos >= stop) + return E_FILE_FORMAT_INVALID; + + unsigned char b; + + long hr = pReader->Read(pos, 1, &b); + + if (hr < 0) + return hr; + + if (hr != 0L) + return E_BUFFER_NOT_FULL; + + if (b == 0) //we can't handle u-int values larger than 8 bytes + return E_FILE_FORMAT_INVALID; + + unsigned char m = 0x80; + len = 1; + + while (!(b & m)) + { + m >>= 1; + ++len; + } + + if ((pos + len) > stop) + return E_FILE_FORMAT_INVALID; + + long long result = b & (~m); + ++pos; + + for (int i = 1; i < len; ++i) + { + hr = pReader->Read(pos, 1, &b); + + if (hr < 0) + return hr; + + if (hr != 0L) + return E_BUFFER_NOT_FULL; + + result <<= 8; + result |= b; + + ++pos; + } + + return result; +} + + +long long mkvparser::UnserializeUInt( + IMkvReader* pReader, + long long pos, + long long size) +{ + assert(pReader); + assert(pos >= 0); + assert(size > 0); + assert(size <= 8); + + long long result = 0; + + for (long long i = 0; i < size; ++i) + { + unsigned char b; + + const long hr = pReader->Read(pos, 1, &b); + + if (hr < 0) + return hr; + result <<= 8; + result |= b; + + ++pos; + } + + return result; +} + + +float mkvparser::Unserialize4Float( + IMkvReader* pReader, + long long pos) +{ + assert(pReader); + assert(pos >= 0); + + long long total, available; + + long hr = pReader->Length(&total, &available); + assert(hr >= 0); + assert(available <= total); + assert((pos + 4) <= available); + + float result; + + unsigned char* const p = (unsigned char*)&result; + unsigned char* q = p + 4; + + for (;;) + { + hr = pReader->Read(pos, 1, --q); + assert(hr == 0L); + + if (q == p) + break; + + ++pos; + } + + return result; +} + + +double mkvparser::Unserialize8Double( + IMkvReader* pReader, + long long pos) +{ + assert(pReader); + assert(pos >= 0); + + double result; + + unsigned char* const p = (unsigned char*)&result; + unsigned char* q = p + 8; + + for (;;) + { + const long hr = pReader->Read(pos, 1, --q); + assert(hr == 0L); + + if (q == p) + break; + + ++pos; + } + + return result; +} + +signed char mkvparser::Unserialize1SInt( + IMkvReader* pReader, + long long pos) +{ + assert(pReader); + assert(pos >= 0); + + long long total, available; + + long hr = pReader->Length(&total, &available); + assert(hr == 0); + assert(available <= total); + assert(pos < available); + + signed char result; + + hr = pReader->Read(pos, 1, (unsigned char*)&result); + assert(hr == 0); + + return result; +} + +short mkvparser::Unserialize2SInt( + IMkvReader* pReader, + long long pos) +{ + assert(pReader); + assert(pos >= 0); + + long long total, available; + + long hr = pReader->Length(&total, &available); + assert(hr >= 0); + assert(available <= total); + assert((pos + 2) <= available); + + short result; + + unsigned char* const p = (unsigned char*)&result; + unsigned char* q = p + 2; + + for (;;) + { + hr = pReader->Read(pos, 1, --q); + assert(hr == 0L); + + if (q == p) + break; + + ++pos; + } + + return result; +} + + +bool mkvparser::Match( + IMkvReader* pReader, + long long& pos, + unsigned long id_, + long long& val) + +{ + assert(pReader); + assert(pos >= 0); + + long long total, available; + + long hr = pReader->Length(&total, &available); + assert(hr >= 0); + assert(available <= total); + + long len; + + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); + assert(len > 0); + assert(len <= 8); + assert((pos + len) <= available); + + if ((unsigned long)id != id_) + return false; + + pos += len; //consume id + + const long long size = ReadUInt(pReader, pos, len); + assert(size >= 0); + assert(size <= 8); + assert(len > 0); + assert(len <= 8); + assert((pos + len) <= available); + + pos += len; //consume length of size of payload + + val = UnserializeUInt(pReader, pos, size); + assert(val >= 0); + + pos += size; //consume size of payload + + return true; +} + +bool mkvparser::Match( + IMkvReader* pReader, + long long& pos, + unsigned long id_, + char*& val) +{ + assert(pReader); + assert(pos >= 0); + + long long total, available; + + long hr = pReader->Length(&total, &available); + assert(hr >= 0); + assert(available <= total); + + long len; + + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); + assert(len > 0); + assert(len <= 8); + assert((pos + len) <= available); + + if ((unsigned long)id != id_) + return false; + + pos += len; //consume id + + const long long size_ = ReadUInt(pReader, pos, len); + assert(size_ >= 0); + assert(len > 0); + assert(len <= 8); + assert((pos + len) <= available); + + pos += len; //consume length of size of payload + assert((pos + size_) <= available); + + const size_t size = static_cast(size_); + val = new char[size+1]; + + for (size_t i = 0; i < size; ++i) + { + char c; + + hr = pReader->Read(pos + i, 1, (unsigned char*)&c); + assert(hr == 0L); + + val[i] = c; + + if (c == '\0') + break; + + } + + val[size] = '\0'; + pos += size_; //consume size of payload + + return true; +} + +#if 0 +bool mkvparser::Match( + IMkvReader* pReader, + long long& pos, + unsigned long id, + wchar_t*& val) +{ + char* str; + + if (!Match(pReader, pos, id, str)) + return false; + + const size_t size = mbstowcs(NULL, str, 0); + + if (size == 0) + val = NULL; + else + { + val = new wchar_t[size+1]; + mbstowcs(val, str, size); + val[size] = L'\0'; + } + + delete[] str; + return true; +} +#endif + + +bool mkvparser::Match( + IMkvReader* pReader, + long long& pos, + unsigned long id_, + unsigned char*& val, + size_t *optionalSize) +{ + assert(pReader); + assert(pos >= 0); + + long long total, available; + + long hr = pReader->Length(&total, &available); + assert(hr >= 0); + assert(available <= total); + + long len; + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); + assert(len > 0); + assert(len <= 8); + assert((pos + len) <= available); + + if ((unsigned long)id != id_) + return false; + + pos += len; //consume id + + const long long size_ = ReadUInt(pReader, pos, len); + assert(size_ >= 0); + assert(len > 0); + assert(len <= 8); + assert((pos + len) <= available); + + pos += len; //consume length of size of payload + assert((pos + size_) <= available); + + const size_t size = static_cast(size_); + val = new unsigned char[size]; + + if (optionalSize) { + *optionalSize = size; + } + + for (size_t i = 0; i < size; ++i) + { + unsigned char b; + + hr = pReader->Read(pos + i, 1, &b); + assert(hr == 0L); + + val[i] = b; + } + + pos += size_; //consume size of payload + return true; +} + + +bool mkvparser::Match( + IMkvReader* pReader, + long long& pos, + unsigned long id_, + double& val) +{ + assert(pReader); + assert(pos >= 0); + + long long total, available; + + long hr = pReader->Length(&total, &available); + assert(hr >= 0); + assert(available <= total); + long idlen; + const long long id = ReadUInt(pReader, pos, idlen); + assert(id >= 0); //TODO + + if ((unsigned long)id != id_) + return false; + + long sizelen; + const long long size = ReadUInt(pReader, pos + idlen, sizelen); + + switch (size) + { + case 4: + case 8: + break; + default: + return false; + } + + pos += idlen + sizelen; //consume id and size fields + assert((pos + size) <= available); + + if (size == 4) + val = Unserialize4Float(pReader, pos); + else + { + assert(size == 8); + val = Unserialize8Double(pReader, pos); + } + + pos += size; //consume size of payload + + return true; +} + + +bool mkvparser::Match( + IMkvReader* pReader, + long long& pos, + unsigned long id_, + short& val) +{ + assert(pReader); + assert(pos >= 0); + + long long total, available; + + long hr = pReader->Length(&total, &available); + assert(hr >= 0); + assert(available <= total); + + long len; + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); + assert((pos + len) <= available); + + if ((unsigned long)id != id_) + return false; + + pos += len; //consume id + + const long long size = ReadUInt(pReader, pos, len); + assert(size <= 2); + assert((pos + len) <= available); + + pos += len; //consume length of size of payload + assert((pos + size) <= available); + + //TODO: + // Generalize this to work for any size signed int + if (size == 1) + val = Unserialize1SInt(pReader, pos); + else + val = Unserialize2SInt(pReader, pos); + + pos += size; //consume size of payload + + return true; +} + + +namespace mkvparser +{ + +EBMLHeader::EBMLHeader(): + m_docType(NULL) +{ +} + +EBMLHeader::~EBMLHeader() +{ + delete[] m_docType; +} + +long long EBMLHeader::Parse( + IMkvReader* pReader, + long long& pos) +{ + assert(pReader); + + long long total, available; + + long hr = pReader->Length(&total, &available); + + if (hr < 0) + return hr; + + pos = 0; + long long end = (1024 < available)? 1024: available; + + for (;;) + { + unsigned char b = 0; + + while (pos < end) + { + hr = pReader->Read(pos, 1, &b); + + if (hr < 0) + return hr; + + if (b == 0x1A) + break; + + ++pos; + } + + if (b != 0x1A) + { + if ((pos >= 1024) || + (available >= total) || + ((total - available) < 5)) + return -1; + + return available + 5; //5 = 4-byte ID + 1st byte of size + } + + if ((total - pos) < 5) + return E_FILE_FORMAT_INVALID; + + if ((available - pos) < 5) + return pos + 5; //try again later + + long len; + + const long long result = ReadUInt(pReader, pos, len); + + if (result < 0) //error + return result; + + if (result == 0x0A45DFA3) //ReadId masks-off length indicator bits + { + assert(len == 4); + pos += len; + break; + } + + ++pos; //throw away just the 0x1A byte, and try again + } + + long len; + long long result = GetUIntLength(pReader, pos, len); + + if (result < 0) //error + return result; + + if (result > 0) //need more data + return result; + + assert(len > 0); + assert(len <= 8); + + if ((total - pos) < len) + return E_FILE_FORMAT_INVALID; + if ((available - pos) < len) + return pos + len; //try again later + + result = ReadUInt(pReader, pos, len); + + if (result < 0) //error + return result; + + pos += len; //consume u-int + + if ((total - pos) < result) + return E_FILE_FORMAT_INVALID; + + if ((available - pos) < result) + return pos + result; + + end = pos + result; + + m_version = 1; + m_readVersion = 1; + m_maxIdLength = 4; + m_maxSizeLength = 8; + m_docTypeVersion = 1; + m_docTypeReadVersion = 1; + + while (pos < end) + { + if (Match(pReader, pos, 0x0286, m_version)) + ; + else if (Match(pReader, pos, 0x02F7, m_readVersion)) + ; + else if (Match(pReader, pos, 0x02F2, m_maxIdLength)) + ; + else if (Match(pReader, pos, 0x02F3, m_maxSizeLength)) + ; + else if (Match(pReader, pos, 0x0282, m_docType)) + ; + else if (Match(pReader, pos, 0x0287, m_docTypeVersion)) + ; + else if (Match(pReader, pos, 0x0285, m_docTypeReadVersion)) + ; + else + { + result = ReadUInt(pReader, pos, len); + assert(result > 0); + assert(len > 0); + assert(len <= 8); + + pos += len; + assert(pos < end); + + result = ReadUInt(pReader, pos, len); + assert(result >= 0); + assert(len > 0); + assert(len <= 8); + + pos += len + result; + assert(pos <= end); + } + } + + assert(pos == end); + + return 0; +} + + +Segment::Segment( + IMkvReader* pReader, + long long start, + long long size) : + m_pReader(pReader), + m_start(start), + m_size(size), + m_pos(start), + m_pInfo(NULL), + m_pTracks(NULL), + m_clusterCount(0) + //m_clusterNumber(0) +{ +} + + +Segment::~Segment() +{ + Cluster** i = m_clusters; + Cluster** j = m_clusters + m_clusterCount; + + while (i != j) + { + Cluster* p = *i++; + assert(p); + delete p; + } + + delete[] m_clusters; + + delete m_pTracks; + delete m_pInfo; +} + + +long long Segment::CreateInstance( + IMkvReader* pReader, + long long pos, + Segment*& pSegment) +{ + assert(pReader); + assert(pos >= 0); + + pSegment = NULL; + + long long total, available; + + long hr = pReader->Length(&total, &available); + assert(hr >= 0); + assert(available <= total); + + //I would assume that in practice this loop would execute + //exactly once, but we allow for other elements (e.g. Void) + //to immediately follow the EBML header. This is fine for + //the source filter case (since the entire file is available), + //but in the splitter case over a network we should probably + //just give up early. We could for example decide only to + //execute this loop a maximum of, say, 10 times. + + while (pos < total) + { + //Read ID + + long len; + long long result = GetUIntLength(pReader, pos, len); + + if (result) //error, or too few available bytes + return result; + + if ((pos + len) > total) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > available) + return pos + len; + + //TODO: if we liberalize the behavior of ReadUInt, we can + //probably eliminate having to use GetUIntLength here. + const long long id = ReadUInt(pReader, pos, len); + + if (id < 0) //error + return id; + + pos += len; //consume ID + + //Read Size + + result = GetUIntLength(pReader, pos, len); + + if (result) //error, or too few available bytes + return result; + + if ((pos + len) > total) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > available) + return pos + len; + + //TODO: if we liberalize the behavior of ReadUInt, we can + //probably eliminate having to use GetUIntLength here. + const long long size = ReadUInt(pReader, pos, len); + + if (size < 0) + return size; + + pos += len; //consume length of size of element + + //Pos now points to start of payload + + if ((pos + size) > total) + return E_FILE_FORMAT_INVALID; + + if (id == 0x08538067) //Segment ID + { + pSegment = new Segment(pReader, pos, size); + assert(pSegment); //TODO + + return 0; //success + } + + pos += size; //consume payload + } + + assert(pos == total); + + pSegment = new Segment(pReader, pos, 0); + assert(pSegment); //TODO + + return 0; //success (sort of) +} + + +long long Segment::ParseHeaders() +{ + //Outermost (level 0) segment object has been constructed, + //and pos designates start of payload. We need to find the + //inner (level 1) elements. + long long total, available; + + long hr = m_pReader->Length(&total, &available); + assert(hr >= 0); + assert(available <= total); + + const long long stop = m_start + m_size; + assert(stop <= total); + assert(m_pos <= stop); + + bool bQuit = false; + while ((m_pos < stop) && !bQuit) + { + long long pos = m_pos; + + long len; + long long result = GetUIntLength(m_pReader, pos, len); + + if (result) //error, or too few available bytes + return result; + + if ((pos + len) > stop) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > available) + return pos + len; + + const long long idpos = pos; + const long long id = ReadUInt(m_pReader, idpos, len); + + if (id < 0) //error + return id; + + pos += len; //consume ID + + //Read Size + result = GetUIntLength(m_pReader, pos, len); + + if (result) //error, or too few available bytes + return result; + + if ((pos + len) > stop) + return E_FILE_FORMAT_INVALID; + + if ((pos + len) > available) + return pos + len; + + const long long size = ReadUInt(m_pReader, pos, len); + + if (size < 0) + return size; + + pos += len; //consume length of size of element + + //Pos now points to start of payload + + if ((pos + size) > stop) + return E_FILE_FORMAT_INVALID; + + //We read EBML elements either in total or nothing at all. + + if ((pos + size) > available) + return pos + size; + + if (id == 0x0549A966) //Segment Info ID + { + assert(m_pInfo == NULL); + m_pInfo = new SegmentInfo(this, pos, size); + assert(m_pInfo); //TODO + + if (m_pTracks) + bQuit = true; + } + else if (id == 0x0654AE6B) //Tracks ID + { + assert(m_pTracks == NULL); + m_pTracks = new Tracks(this, pos, size); + assert(m_pTracks); //TODO + + if (m_pInfo) + bQuit = true; + } + else if (id == 0x0F43B675) //Cluster ID + { +#if 0 + if (m_pInfo == NULL) //TODO: liberalize + ; + else if (m_pTracks == NULL) + ; + else + //ParseCluster(idpos, pos, size); + Cluster::Parse(this, m_clusters, pos, size); +#endif + bQuit = true; + } + + m_pos = pos + size; //consume payload + } + + assert(m_pos <= stop); + + return 0; //success +} + + +long Segment::ParseCluster(Cluster*& pCluster, long long& pos_) const +{ + pCluster = NULL; + pos_ = -1; + + const long long stop = m_start + m_size; + assert(m_pos <= stop); + + long long pos = m_pos; + long long off = -1; + + + while (pos < stop) + { + long len; + const long long idpos = pos; + + const long long id = SyncReadUInt(m_pReader, pos, stop, len); + + if (id < 0) //error + return static_cast(id); + + if (id == 0) + return E_FILE_FORMAT_INVALID; + + pos += len; //consume id + assert(pos < stop); + + const long long size = SyncReadUInt(m_pReader, pos, stop, len); + + if (size < 0) //error + return static_cast(size); + + pos += len; //consume size + assert(pos <= stop); + + if (size == 0) //weird + continue; + + //pos now points to start of payload + + pos += size; //consume payload + assert(pos <= stop); + + if (off >= 0) + { + pos_ = idpos; + break; + } + + if (id == 0x0F43B675) //Cluster ID + off = idpos - m_start; + } + + Segment* const this_ = const_cast(this); + const size_t idx = m_clusterCount; + + if (pos >= stop) + { + pos_ = stop; + +#if 0 + if (off < 0) + { + pCluster = Cluster::CreateEndOfStream(this_, idx); + return 1L; + } +#else + if (off < 0) + return 1L; +#endif + + //Reading 0 bytes at pos might work too -- it would depend + //on how the reader is implemented. + + unsigned char b; + + const long hr = m_pReader->Read(pos - 1, 1, &b); + + if (hr < 0) + return hr; + + if (hr != 0L) + return E_BUFFER_NOT_FULL; + } + + assert(off >= 0); + assert(pos_ >= m_start); + assert(pos_ <= stop); + + pCluster = Cluster::Parse(this_, idx, off); + return 0L; +} + + +bool Segment::AddCluster(Cluster* pCluster, long long pos) +{ + assert(pos >= m_start); + + const long long stop = m_start + m_size; + assert(pos <= stop); + + if (pCluster) + m_clusters[pos] = pCluster; + + m_pos = pos; //m_pos >= stop is now we know we have all clusters + + return (pos >= stop); +} + + +long Segment::Load() +{ + //Outermost (level 0) segment object has been constructed, + //and pos designates start of payload. We need to find the + //inner (level 1) elements. + const long long stop = m_start + m_size; +#ifdef _DEBUG + { + long long total, available; + + long hr = m_pReader->Length(&total, &available); + assert(hr >= 0); + assert(available >= total); + assert(stop <= total); + } +#endif + long long index = m_pos; + + m_clusterCount = 0; + + while (index < stop) + { + long len = 0; + + long long result = GetUIntLength(m_pReader, index, len); + + if (result < 0) //error + return static_cast(result); + + if ((index + len) > stop) + return E_FILE_FORMAT_INVALID; + + const long long idpos = index; + const long long id = ReadUInt(m_pReader, idpos, len); + + if (id < 0) //error + return static_cast(id); + + index += len; //consume ID + + //Read Size + result = GetUIntLength(m_pReader, index, len); + + if (result < 0) //error + return static_cast(result); + + if ((index + len) > stop) + return E_FILE_FORMAT_INVALID; + + const long long size = ReadUInt(m_pReader, index, len); + + if (size < 0) //error + return static_cast(size); + + index += len; //consume length of size of element + + if (id == 0x0F43B675) // Cluster ID + break; + + if (id == 0x014D9B74) // SeekHead ID + { + ParseSeekHead(index, size, NULL); + break; + } + index += size; + } + + if (m_clusterCount == 0) + return -1L; + + while (m_pos < stop) + { + long long pos = m_pos; + + long len; + + long long result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) //error + return static_cast(result); + + if ((pos + len) > stop) + return E_FILE_FORMAT_INVALID; + + const long long idpos = pos; + const long long id = ReadUInt(m_pReader, idpos, len); + + if (id < 0) //error + return static_cast(id); + + pos += len; //consume ID + + //Read Size + result = GetUIntLength(m_pReader, pos, len); + + if (result < 0) //error + return static_cast(result); + + if ((pos + len) > stop) + return E_FILE_FORMAT_INVALID; + + const long long size = ReadUInt(m_pReader, pos, len); + + if (size < 0) //error + return static_cast(size); + + pos += len; //consume length of size of element + + //Pos now points to start of payload + + if ((pos + size) > stop) + return E_FILE_FORMAT_INVALID; + + if (id == 0x0F43B675) //Cluster ID + break; + + if (id == 0x014D9B74) //SeekHead ID + { + m_clusters = new Cluster*[m_clusterCount]; + size_t index = 0; + + ParseSeekHead(pos, size, &index); + assert(index == m_clusterCount); + } + else if (id == 0x0549A966) //Segment Info ID + { + assert(m_pInfo == NULL); + m_pInfo = new SegmentInfo(this, pos, size); + assert(m_pInfo); //TODO + } + else if (id == 0x0654AE6B) //Tracks ID + { + assert(m_pTracks == NULL); + m_pTracks = new Tracks(this, pos, size); + assert(m_pTracks); //TODO + } + + m_pos = pos + size; //consume payload + } + + assert(m_clusters); + + //TODO: see notes above. This check is here (temporarily) to ensure + //that the first seekhead has entries for the clusters (because that's + //when they're loaded). In case we are given a file that lists the + //clusters in a second seekhead, the worst thing that happens is that + //we treat this as an invalid file (which is better then simply + //asserting somewhere). But that's only a work-around. What we need + //to do is be able to handle having multiple seekheads, and having + //clusters listed somewhere besides the first seekhead. + // + //if (m_clusters == NULL) + // return E_FILE_FORMAT_INVALID; + + //NOTE: we stop parsing when we reach the first cluster, under the + //assumption all clusters are named in some SeekHead. Clusters + //will have been (pre)loaded, so we indicate that we have all clusters + //by adjusting the parse position: + m_pos = stop; //means "we have all clusters" + + return 0L; +} + + +void Segment::ParseSeekHead(long long start, long long size_, size_t* pIndex) +{ + long long pos = start; + const long long stop = start + size_; + while (pos < stop) + { + long len; + + const long long id = ReadUInt(m_pReader, pos, len); + assert(id >= 0); //TODO + assert((pos + len) <= stop); + + pos += len; //consume ID + + const long long size = ReadUInt(m_pReader, pos, len); + assert(size >= 0); + assert((pos + len) <= stop); + + pos += len; //consume Size field + assert((pos + size) <= stop); + + if (id == 0x0DBB) //SeekEntry ID + ParseSeekEntry(pos, size, pIndex); + + pos += size; //consume payload + assert(pos <= stop); + } + + assert(pos == stop); +} + + +void Segment::ParseSecondarySeekHead(long long off, size_t* pIndex) +{ + assert(off >= 0); + assert(off < m_size); + + long long pos = m_start + off; + const long long stop = m_start + m_size; + + long len; + + long long result = GetUIntLength(m_pReader, pos, len); + assert(result == 0); + assert((pos + len) <= stop); + + const long long idpos = pos; + + const long long id = ReadUInt(m_pReader, idpos, len); + assert(id == 0x014D9B74); //SeekHead ID + + pos += len; //consume ID + assert(pos < stop); + + //Read Size + + result = GetUIntLength(m_pReader, pos, len); + assert(result == 0); + assert((pos + len) <= stop); + + const long long size = ReadUInt(m_pReader, pos, len); + assert(size >= 0); + + pos += len; //consume length of size of element + assert((pos + size) <= stop); + + //Pos now points to start of payload + + ParseSeekHead(pos, size, pIndex); +} + + +void Segment::ParseSeekEntry(long long start, long long size_, size_t* pIndex) +{ + long long pos = start; + + const long long stop = start + size_; + + long len; + + const long long seekIdId = ReadUInt(m_pReader, pos, len); + //seekIdId; + assert(seekIdId == 0x13AB); //SeekID ID + assert((pos + len) <= stop); + + pos += len; //consume id + + const long long seekIdSize = ReadUInt(m_pReader, pos, len); + assert(seekIdSize >= 0); + assert((pos + len) <= stop); + + pos += len; //consume size + + const long long seekId = ReadUInt(m_pReader, pos, len); //payload + assert(seekId >= 0); + assert(len == seekIdSize); + assert((pos + len) <= stop); + + pos += seekIdSize; //consume payload + + const long long seekPosId = ReadUInt(m_pReader, pos, len); + //seekPosId; + assert(seekPosId == 0x13AC); //SeekPos ID + assert((pos + len) <= stop); + + pos += len; //consume id + + const long long seekPosSize = ReadUInt(m_pReader, pos, len); + assert(seekPosSize >= 0); + assert((pos + len) <= stop); + + pos += len; //consume size + assert((pos + seekPosSize) <= stop); + + const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize); + assert(seekOff >= 0); + assert(seekOff < m_size); + + pos += seekPosSize; //consume payload + assert(pos == stop); + + const long long seekPos = m_start + seekOff; + assert(seekPos < (m_start + m_size)); + + if (seekId == 0x0F43B675) //cluster id + { + if (pIndex == NULL) + ++m_clusterCount; + else + { + assert(m_clusters); + assert(m_clusterCount > 0); + + size_t& index = *pIndex; + assert(index < m_clusterCount); + + Cluster*& pCluster = m_clusters[index]; + + pCluster = Cluster::Parse(this, index, seekOff); + assert(pCluster); //TODO + + ++index; + } + } + else if (seekId == 0x014D9B74) //SeekHead ID + { + ParseSecondarySeekHead(seekOff, pIndex); + } +} + + +long long Segment::Unparsed() const +{ + const long long stop = m_start + m_size; + + const long long result = stop - m_pos; + assert(result >= 0); + + return result; +} + + +#if 0 //NOTE: too inefficient +long long Segment::Load(long long time_ns) +{ + if (Unparsed() <= 0) + return 0; + + while (m_clusters.empty()) + { + const long long result = Parse(); + + if (result) //error, or not enough bytes available + return result; + + if (Unparsed() <= 0) + return 0; + } + + while (m_clusters.back()->GetTime() < time_ns) + { + const long long result = Parse(); + + if (result) //error, or not enough bytes available + return result; + + if (Unparsed() <= 0) + return 0; + } + + return 0; +} +#endif + + +Cluster* Segment::GetFirst() +{ + if ((m_clusters == NULL) || (m_clusterCount <= 0)) + return &m_eos; + + Cluster* const pCluster = m_clusters[0]; + assert(pCluster); + + return pCluster; +} + + +Cluster* Segment::GetLast() +{ + if ((m_clusters == NULL) || (m_clusterCount <= 0)) + return &m_eos; + + const size_t idx = m_clusterCount - 1; + Cluster* const pCluster = m_clusters[idx]; + assert(pCluster); + + return pCluster; +} + + +unsigned long Segment::GetCount() const +{ + //TODO: m_clusterCount should not be long long. + return static_cast(m_clusterCount); +} + + +Cluster* Segment::GetNext(const Cluster* pCurr) +{ + assert(pCurr); + assert(pCurr != &m_eos); + assert(m_clusters); + assert(m_clusterCount > 0); + + size_t idx = pCurr->m_index; + assert(idx < m_clusterCount); + assert(pCurr == m_clusters[idx]); + + idx++; + + if (idx >= m_clusterCount) + return &m_eos; + + Cluster* const pNext = m_clusters[idx]; + assert(pNext); + + return pNext; +} + + +Cluster* Segment::GetCluster(long long time_ns) +{ + if ((m_clusters == NULL) || (m_clusterCount <= 0)) + return &m_eos; + + { + Cluster* const pCluster = m_clusters[0]; + assert(pCluster); + assert(pCluster->m_index == 0); + + if (time_ns <= pCluster->GetTime()) + return pCluster; + } + + //Binary search of cluster array + + size_t i = 0; + size_t j = m_clusterCount; + + while (i < j) + { + //INVARIANT: + //[0, i) <= time_ns + //[i, j) ? + //[j, m_clusterCount) > time_ns + + const size_t k = i + (j - i) / 2; + assert(k < m_clusterCount); + + Cluster* const pCluster = m_clusters[k]; + assert(pCluster); + assert(pCluster->m_index == k); + + const long long t = pCluster->GetTime(); + + if (t <= time_ns) + i = k + 1; + else + j = k; + + assert(i <= j); + } + + assert(i == j); + assert(i > 0); + assert(i <= m_clusterCount); + + const size_t k = i - 1; + + Cluster* const pCluster = m_clusters[k]; + assert(pCluster); + assert(pCluster->m_index == k); + assert(pCluster->GetTime() <= time_ns); + + return pCluster; +} + + +Tracks* Segment::GetTracks() const +{ + return m_pTracks; +} + + +const SegmentInfo* const Segment::GetInfo() const +{ + return m_pInfo; +} + + +long long Segment::GetDuration() const +{ + assert(m_pInfo); + return m_pInfo->GetDuration(); +} + + +SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_) : + m_pSegment(pSegment), + m_start(start), + m_size(size_), + m_pMuxingAppAsUTF8(NULL), + m_pWritingAppAsUTF8(NULL), + m_pTitleAsUTF8(NULL) +{ + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long pos = start; + const long long stop = start + size_; + + m_timecodeScale = 1000000; + m_duration = 0; + + + while (pos < stop) + { + if (Match(pReader, pos, 0x0AD7B1, m_timecodeScale)) + assert(m_timecodeScale > 0); + + else if (Match(pReader, pos, 0x0489, m_duration)) + assert(m_duration >= 0); + + else if (Match(pReader, pos, 0x0D80, m_pMuxingAppAsUTF8)) //[4D][80] + assert(m_pMuxingAppAsUTF8); + + else if (Match(pReader, pos, 0x1741, m_pWritingAppAsUTF8)) //[57][41] + assert(m_pWritingAppAsUTF8); + + else if (Match(pReader, pos, 0x3BA9, m_pTitleAsUTF8)) //[7B][A9] + assert(m_pTitleAsUTF8); + + else + { + long len; + + const long long id = ReadUInt(pReader, pos, len); + //id; + assert(id >= 0); + assert((pos + len) <= stop); + + pos += len; //consume id + assert((stop - pos) > 0); + + const long long size = ReadUInt(pReader, pos, len); + assert(size >= 0); + assert((pos + len) <= stop); + + pos += len + size; //consume size and payload + assert(pos <= stop); + } + } + + assert(pos == stop); +} + +SegmentInfo::~SegmentInfo() +{ + if (m_pMuxingAppAsUTF8) + { + delete[] m_pMuxingAppAsUTF8; + m_pMuxingAppAsUTF8 = NULL; + } + + if (m_pWritingAppAsUTF8) + { + delete[] m_pWritingAppAsUTF8; + m_pWritingAppAsUTF8 = NULL; + } + + if (m_pTitleAsUTF8) + { + delete[] m_pTitleAsUTF8; + m_pTitleAsUTF8 = NULL; + } +} + +long long SegmentInfo::GetTimeCodeScale() const +{ + return m_timecodeScale; +} + + +long long SegmentInfo::GetDuration() const +{ + assert(m_duration >= 0); + assert(m_timecodeScale >= 1); + + const double dd = double(m_duration) * double(m_timecodeScale); + const long long d = static_cast(dd); + + return d; +} + +const char* SegmentInfo::GetMuxingAppAsUTF8() const +{ + return m_pMuxingAppAsUTF8; +} + +const char* SegmentInfo::GetWritingAppAsUTF8() const +{ + return m_pWritingAppAsUTF8; +} + +const char* SegmentInfo::GetTitleAsUTF8() const +{ + return m_pTitleAsUTF8; +} + +Track::Track(Segment* pSegment, const Info& i) : + m_pSegment(pSegment), + m_info(i) +{ +} + +Track::~Track() +{ + Info& info = const_cast(m_info); + info.Clear(); +} + +Track::Info::Info(): + type(-1), + number(-1), + uid(-1), + nameAsUTF8(NULL), + codecId(NULL), + codecPrivate(NULL), + codecPrivateSize(0), + codecNameAsUTF8(NULL) +{ +} + +void Track::Info::Clear() +{ + delete[] nameAsUTF8; + nameAsUTF8 = NULL; + + delete[] codecId; + codecId = NULL; + + delete[] codecPrivate; + codecPrivate = NULL; + + delete[] codecNameAsUTF8; + codecNameAsUTF8 = NULL; +} + +const BlockEntry* Track::GetEOS() const +{ + return &m_eos; +} + +long long Track::GetType() const +{ + const unsigned long result = static_cast(m_info.type); + return result; +} + +unsigned long Track::GetNumber() const +{ + assert(m_info.number >= 0); + const unsigned long result = static_cast(m_info.number); + return result; +} + +const char* Track::GetNameAsUTF8() const +{ + return m_info.nameAsUTF8; +} + +const char* Track::GetCodecNameAsUTF8() const +{ + return m_info.codecNameAsUTF8; +} + + +const char* Track::GetCodecId() const +{ + return m_info.codecId; +} + + +const unsigned char* Track::GetCodecPrivate(size_t *optionalSize) const +{ + if (optionalSize) { + *optionalSize = m_info.codecPrivateSize; + } + return m_info.codecPrivate; +} + + +long Track::GetFirst(const BlockEntry*& pBlockEntry) const +{ + Cluster* const pCluster = m_pSegment->GetFirst(); + + //If Segment::GetFirst returns NULL, then this must be a network + //download, and we haven't loaded any clusters yet. In this case, + //returning NULL from Track::GetFirst means the same thing. + + if ((pCluster == NULL) || pCluster->EOS()) + { + pBlockEntry = NULL; + return E_BUFFER_NOT_FULL; //return 1L instead? + } + + pBlockEntry = pCluster->GetFirst(); + + while (pBlockEntry) + { + const Block* const pBlock = pBlockEntry->GetBlock(); + assert(pBlock); + + if (pBlock->GetTrackNumber() == (unsigned long)m_info.number) + return 0L; + + pBlockEntry = pCluster->GetNext(pBlockEntry); + } + + //NOTE: if we get here, it means that we didn't find a block with + //a matching track number. We interpret that as an error (which + //might be too conservative). + + pBlockEntry = GetEOS(); //so we can return a non-NULL value + return 1L; +} + + +long Track::GetNext(const BlockEntry* pCurrEntry, const BlockEntry*& pNextEntry) const +{ + assert(pCurrEntry); + assert(!pCurrEntry->EOS()); //? + assert(pCurrEntry->GetBlock()->GetTrackNumber() == (unsigned long)m_info.number); + + const Cluster* const pCurrCluster = pCurrEntry->GetCluster(); + assert(pCurrCluster); + assert(!pCurrCluster->EOS()); + + pNextEntry = pCurrCluster->GetNext(pCurrEntry); + + while (pNextEntry) + { + const Block* const pNextBlock = pNextEntry->GetBlock(); + assert(pNextBlock); + + if (pNextBlock->GetTrackNumber() == (unsigned long)m_info.number) + return 0L; + + pNextEntry = pCurrCluster->GetNext(pNextEntry); + } + + Segment* pSegment = pCurrCluster->m_pSegment; + Cluster* const pNextCluster = pSegment->GetNext(pCurrCluster); + + if ((pNextCluster == NULL) || pNextCluster->EOS()) + { + if (pSegment->Unparsed() <= 0) //all clusters have been loaded + { + pNextEntry = GetEOS(); + return 1L; + } + + pNextEntry = NULL; + return E_BUFFER_NOT_FULL; + } + + pNextEntry = pNextCluster->GetFirst(); + + while (pNextEntry) + { + const Block* const pNextBlock = pNextEntry->GetBlock(); + assert(pNextBlock); + + if (pNextBlock->GetTrackNumber() == (unsigned long)m_info.number) + return 0L; + + pNextEntry = pNextCluster->GetNext(pNextEntry); + } + + //TODO: what has happened here is that we did not find a block + //with a matching track number on the next cluster. It might + //be the case that some cluster beyond the next cluster + //contains a block having a matching track number, but for + //now we terminate the search immediately. We do this so that + //we don't end up searching the entire file looking for the + //next block. Another possibility is to try searching for the next + //block in a small, fixed number of clusters (intead searching + //just the next one), or to terminate the search when when the + //there is a large gap in time, or large gap in file position. It + //might very well be the case that the approach we use here is + //unnecessarily conservative. + + //TODO: again, here's a case where we need to return the special + //EOS block. Or something. It's OK if pNext is NULL, because + //we only need it to set the stop time of the media sample. + //(The start time is determined from pCurr, which is non-NULL + //and non-EOS.) The problem is when we set pCurr=pNext; when + //pCurr has the value NULL we interpret that to mean that we + //haven't fully initialized pCurr and we attempt to set it to + //point to the first block for this track. But that's not what + //we want at all; we want the next call to PopulateSample to + //return end-of-stream, not (re)start from the beginning. + // + //One work-around is to send EOS immediately. We would send + //the EOS the next pass anyway, so maybe it's no great loss. The + //only problem is that if this the stream really does end one + //cluster early (relative to other tracks), or the last frame + //happens to be a keyframe ("CanSeekToEnd"). + // + //The problem is that we need a way to mark as stream as + //"at end of stream" without actually being at end of stream. + //We need to give pCurr some value that means "you've reached EOS". + //We can't synthesize the special EOS Cluster immediately + //(when we first open the file, say), because we use the existance + //of that special cluster value to mean that we've read all of + //the clusters (this is a network download, so we can't know apriori + //how many we have). + // + //Or, we could return E_FAIL, and set another bit in the stream + //object itself, to indicate that it should send EOS earlier + //than when (pCurr=pStop). + // + //Or, probably the best solution, when we actually load the + //blocks into a cluster: if we notice that there's no block + //for a track, we synthesize a nonce EOS block for that track. + //That way we always have something to return. But that will + //only work for sequential scan??? + + //pNext = NULL; + //return E_FAIL; + pNextEntry = GetEOS(); + return 1L; +} + + +Track::EOSBlock::EOSBlock() +{ +} + + +bool Track::EOSBlock::EOS() const +{ + return true; +} + + +Cluster* Track::EOSBlock::GetCluster() const +{ + return NULL; +} + + +size_t Track::EOSBlock::GetIndex() const +{ + return 0; +} + + +const Block* Track::EOSBlock::GetBlock() const +{ + return NULL; +} + + +bool Track::EOSBlock::IsBFrame() const +{ + return false; +} + + +VideoTrack::VideoTrack(Segment* pSegment, const Info& i) : + Track(pSegment, i), + m_width(-1), + m_height(-1), + m_rate(-1) +{ + assert(i.type == 1); + assert(i.number > 0); + + IMkvReader* const pReader = pSegment->m_pReader; + + const Settings& s = i.settings; + assert(s.start >= 0); + assert(s.size >= 0); + + long long pos = s.start; + assert(pos >= 0); + + const long long stop = pos + s.size; + + while (pos < stop) + { +#ifdef _DEBUG + long len; + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); //TODO: handle error case + assert((pos + len) <= stop); +#endif + if (Match(pReader, pos, 0x30, m_width)) + ; + else if (Match(pReader, pos, 0x3A, m_height)) + ; + else if (Match(pReader, pos, 0x0383E3, m_rate)) + ; + else + { + long len; + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); //TODO: handle error case + assert((pos + len) <= stop); + + pos += len; //consume id + + const long long size = ReadUInt(pReader, pos, len); + assert(size >= 0); //TODO: handle error case + assert((pos + len) <= stop); + + pos += len; //consume length of size + assert((pos + size) <= stop); + + //pos now designates start of payload + + pos += size; //consume payload + assert(pos <= stop); + } + } + + return; +} + + +bool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const +{ + assert(pBlockEntry); + + const Block* const pBlock = pBlockEntry->GetBlock(); + assert(pBlock); + assert(pBlock->GetTrackNumber() == (unsigned long)m_info.number); + + return pBlock->IsKey(); +} + + + +long long VideoTrack::GetWidth() const +{ + return m_width; +} + + +long long VideoTrack::GetHeight() const +{ + return m_height; +} + + +double VideoTrack::GetFrameRate() const +{ + return m_rate; +} + + +AudioTrack::AudioTrack(Segment* pSegment, const Info& i) : + Track(pSegment, i) +{ + assert(i.type == 2); + assert(i.number > 0); + + IMkvReader* const pReader = pSegment->m_pReader; + + const Settings& s = i.settings; + assert(s.start >= 0); + assert(s.size >= 0); + + long long pos = s.start; + assert(pos >= 0); + + const long long stop = pos + s.size; + + while (pos < stop) + { +#ifdef _DEBUG + long len; + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); //TODO: handle error case + assert((pos + len) <= stop); +#endif + if (Match(pReader, pos, 0x35, m_rate)) + ; + else if (Match(pReader, pos, 0x1F, m_channels)) + ; + else if (Match(pReader, pos, 0x2264, m_bitDepth)) + ; + else + { + long len; + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); //TODO: handle error case + assert((pos + len) <= stop); + + pos += len; //consume id + + const long long size = ReadUInt(pReader, pos, len); + assert(size >= 0); //TODO: handle error case + assert((pos + len) <= stop); + + pos += len; //consume length of size + assert((pos + size) <= stop); + + //pos now designates start of payload + + pos += size; //consume payload + assert(pos <= stop); + } + } + + return; +} + +bool AudioTrack::VetEntry(const BlockEntry* pBlockEntry) const +{ + assert(pBlockEntry); + + const Block* const pBlock = pBlockEntry->GetBlock(); + assert(pBlock); + assert(pBlock->GetTrackNumber() == (unsigned long)m_info.number); + + return true; +} + + +double AudioTrack::GetSamplingRate() const +{ + return m_rate; +} + + +long long AudioTrack::GetChannels() const +{ + return m_channels; +} + +long long AudioTrack::GetBitDepth() const +{ + return m_bitDepth; +} + +Tracks::Tracks(Segment* pSegment, long long start, long long size_) : + m_pSegment(pSegment), + m_start(start), + m_size(size_), + m_trackEntries(NULL), + m_trackEntriesEnd(NULL) +{ + long long stop = m_start + m_size; + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long pos1 = m_start; + int count = 0; + + while (pos1 < stop) + { + long len; + const long long id = ReadUInt(pReader, pos1, len); + assert(id >= 0); + assert((pos1 + len) <= stop); + + pos1 += len; //consume id + + const long long size = ReadUInt(pReader, pos1, len); + assert(size >= 0); + assert((pos1 + len) <= stop); + + pos1 += len; //consume length of size + + //pos now desinates start of element + if (id == 0x2E) //TrackEntry ID + ++count; + + pos1 += size; //consume payload + assert(pos1 <= stop); + } + + if (count <= 0) + return; + + m_trackEntries = new Track*[count]; + m_trackEntriesEnd = m_trackEntries; + + long long pos = m_start; + + while (pos < stop) + { + long len; + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); + assert((pos + len) <= stop); + + pos += len; //consume id + + const long long size1 = ReadUInt(pReader, pos, len); + assert(size1 >= 0); + assert((pos + len) <= stop); + + pos += len; //consume length of size + + //pos now desinates start of element + + if (id == 0x2E) //TrackEntry ID + ParseTrackEntry(pos, size1, *m_trackEntriesEnd++); + + pos += size1; //consume payload + assert(pos <= stop); + } +} + +unsigned long Tracks::GetTracksCount() const +{ + const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries; + assert(result >= 0); + + return static_cast(result); +} + + +void Tracks::ParseTrackEntry( + long long start, + long long size, + Track*& pTrack) +{ + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long pos = start; + const long long stop = start + size; + + Track::Info i; + + Track::Settings videoSettings; + videoSettings.start = -1; + + Track::Settings audioSettings; + audioSettings.start = -1; + + while (pos < stop) + { +#ifdef _DEBUG + long len; + const long long id = ReadUInt(pReader, pos, len); + len; + id; +#endif + if (Match(pReader, pos, 0x57, i.number)) + assert(i.number > 0); + + else if (Match(pReader, pos, 0x33C5, i.uid)) + ; + + else if (Match(pReader, pos, 0x03, i.type)) + ; + + else if (Match(pReader, pos, 0x136E, i.nameAsUTF8)) + assert(i.nameAsUTF8); + + else if (Match(pReader, pos, 0x06, i.codecId)) + ; + + else if (Match(pReader, pos, 0x23A2, i.codecPrivate, &i.codecPrivateSize)) + ; + + else if (Match(pReader, pos, 0x058688, i.codecNameAsUTF8)) + assert(i.codecNameAsUTF8); + + else + { + long len; + + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); //TODO: handle error case + assert((pos + len) <= stop); + + pos += len; //consume id + + const long long size = ReadUInt(pReader, pos, len); + assert(size >= 0); //TODO: handle error case + assert((pos + len) <= stop); + + pos += len; //consume length of size + const long long start = pos; + + pos += size; //consume payload + assert(pos <= stop); + + if (id == 0x60) + { + videoSettings.start = start; + videoSettings.size = size; + } + else if (id == 0x61) + { + audioSettings.start = start; + audioSettings.size = size; + } + } + } + + assert(pos == stop); + //TODO: propertly vet info.number, to ensure both its existence, + //and that it is unique among all tracks. + assert(i.number > 0); + + //TODO: vet settings, to ensure that video settings (0x60) + //were specified when type = 1, and that audio settings (0x61) + //were specified when type = 2. + if (i.type == 1) //video + { + assert(audioSettings.start < 0); + assert(videoSettings.start >= 0); + + i.settings = videoSettings; + + VideoTrack* const t = new VideoTrack(m_pSegment, i); + assert(t); //TODO + pTrack = t; + } + else if (i.type == 2) //audio + { + assert(videoSettings.start < 0); + assert(audioSettings.start >= 0); + + i.settings = audioSettings; + + AudioTrack* const t = new AudioTrack(m_pSegment, i); + assert(t); //TODO + pTrack = t; + } + else + { + // for now we do not support other track types yet. + // TODO: support other track types + i.Clear(); + + pTrack = NULL; + } + + return; +} + + +Tracks::~Tracks() +{ + Track** i = m_trackEntries; + Track** const j = m_trackEntriesEnd; + + while (i != j) + { + Track* pTrack = *i++; + delete pTrack; + pTrack = NULL; + } + + delete[] m_trackEntries; +} + + +Track* Tracks::GetTrackByNumber(unsigned long tn) const +{ + Track** i = m_trackEntries; + Track** const j = m_trackEntriesEnd; + + while (i != j) + { + Track* const pTrack = *i++; + + if (pTrack == NULL) + continue; + + if (tn == pTrack->GetNumber()) + return pTrack; + } + + return NULL; //not found +} + + +Track* Tracks::GetTrackByIndex(unsigned long idx) const +{ + const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries; + + if (idx >= static_cast(count)) + return NULL; + + return m_trackEntries[idx]; +} + + +void Cluster::Load() +{ + assert(m_pSegment); + + if (m_start > 0) + { + assert(m_size > 0); + assert(m_timecode >= 0); + return; + } + + assert(m_size == 0); + assert(m_timecode < 0); + + IMkvReader* const pReader = m_pSegment->m_pReader; + + const long long off = -m_start; //relative to segment + long long pos = m_pSegment->m_start + off; //absolute + + long len; + + const long long id_ = ReadUInt(pReader, pos, len); + assert(id_ >= 0); + assert(id_ == 0x0F43B675); //Cluster ID + + pos += len; //consume id + + const long long size_ = ReadUInt(pReader, pos, len); + assert(size_ >= 0); + + pos += len; //consume size + + m_start = pos; + m_size = size_; + + const long long stop = m_start + size_; + + long long timecode = -1; + + while (pos < stop) + { + if (Match(pReader, pos, 0x67, timecode)) + break; + else + { + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); //TODO + assert((pos + len) <= stop); + + pos += len; //consume id + + const long long size = ReadUInt(pReader, pos, len); + assert(size >= 0); //TODO + assert((pos + len) <= stop); + + pos += len; //consume size + + if (id == 0x20) //BlockGroup ID + break; + + if (id == 0x23) //SimpleBlock ID + break; + + pos += size; //consume payload + assert(pos <= stop); + } + } + + assert(pos <= stop); + assert(timecode >= 0); + + m_timecode = timecode; +} + + +Cluster* Cluster::Parse( + Segment* pSegment, + size_t idx, + long long off) +{ + assert(pSegment); + assert(off >= 0); + assert(off < pSegment->m_size); + Cluster* const pCluster = new Cluster(pSegment, idx, -off); + assert(pCluster); + + return pCluster; +} + + +Cluster::Cluster() : + m_pSegment(NULL), + m_index(0), + m_start(0), + m_size(0), + m_timecode(0), + m_pEntries(NULL), + m_entriesCount(0) +{ +} + +Cluster::Cluster( + Segment* pSegment, + size_t idx, + long long off) : + m_pSegment(pSegment), + m_index(idx), + m_start(off), + m_size(0), + m_timecode(-1), + m_pEntries(NULL), + m_entriesCount(0) +{ +} + + +Cluster::~Cluster() +{ +#if 0 + while (!m_pEntries.empty()) + { + BlockEntry* pBlockEntry = m_pEntries.front(); + assert(pBlockEntry); + + m_pEntries.pop_front(); + delete pBlockEntry; + } +#else + BlockEntry** i = m_pEntries; + BlockEntry** const j = m_pEntries + m_entriesCount; + while (i != j) + { + BlockEntry* p = *i++; + + assert(p); + delete p; + } + + delete[] m_pEntries; +#endif + +} + +bool Cluster::EOS() const +{ + return (m_pSegment == 0); +} + + +void Cluster::LoadBlockEntries() +{ + if (m_pEntries) + return; + + Load(); + assert(m_timecode >= 0); + assert(m_start > 0); + assert(m_size > 0); + + IMkvReader* const pReader = m_pSegment->m_pReader; + + long long pos = m_start; + const long long stop = m_start + m_size; + long long timecode = -1; + + long long idx = pos; + + m_entriesCount = 0; + + while (idx < stop) + { + if (Match(pReader, idx, 0x67, timecode)) + assert(timecode == m_timecode); + else + { + long len; + + const long long id = ReadUInt(pReader, idx, len); + assert(id >= 0); //TODO + assert((idx + len) <= stop); + + idx += len; //consume id + + const long long size = ReadUInt(pReader, idx, len); + assert(size >= 0); //TODO + assert((idx + len) <= stop); + + idx += len; //consume size + + if (id == 0x20) //BlockGroup ID + ++m_entriesCount; + else if (id == 0x23) //SimpleBlock ID + ++m_entriesCount; + + idx += size; //consume payload + + assert(idx <= stop); + } + } + + if (m_entriesCount == 0) + return; + + m_pEntries = new BlockEntry*[m_entriesCount]; + size_t index = 0; + + while (pos < stop) + { + if (Match(pReader, pos, 0x67, timecode)) + assert(timecode == m_timecode); + else + { + long len; + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); //TODO + assert((pos + len) <= stop); + + pos += len; //consume id + + const long long size = ReadUInt(pReader, pos, len); + assert(size >= 0); //TODO + assert((pos + len) <= stop); + + pos += len; //consume size + + if (id == 0x20) //BlockGroup ID + ParseBlockGroup(pos, size, index++); + else if (id == 0x23) //SimpleBlock ID + ParseSimpleBlock(pos, size, index++); + + pos += size; //consume payload + assert(pos <= stop); + } + } + + assert(pos == stop); + assert(timecode >= 0); + assert(index == m_entriesCount); +} + + + +long long Cluster::GetTimeCode() +{ + Load(); + return m_timecode; +} + + +long long Cluster::GetTime() +{ + const long long tc = GetTimeCode(); + assert(tc >= 0); + + const SegmentInfo* const pInfo = m_pSegment->GetInfo(); + assert(pInfo); + + const long long scale = pInfo->GetTimeCodeScale(); + assert(scale >= 1); + + const long long t = m_timecode * scale; + + return t; +} + + +void Cluster::ParseBlockGroup(long long start, long long size, size_t index) +{ + assert(m_pEntries); + assert(m_entriesCount); + assert(index < m_entriesCount); + + BlockGroup* const pGroup = new BlockGroup(this, index, start, size); + assert(pGroup); //TODO + + m_pEntries[index] = pGroup; +} + + + +void Cluster::ParseSimpleBlock(long long start, long long size, size_t index) +{ + assert(m_pEntries); + assert(m_entriesCount); + assert(index < m_entriesCount); + + SimpleBlock* const pSimpleBlock = new SimpleBlock(this, index, start, size); + assert(pSimpleBlock); //TODO + + m_pEntries[index] = pSimpleBlock; +} + + +const BlockEntry* Cluster::GetFirst() +{ + LoadBlockEntries(); + + return m_pEntries[0]; +} + + +const BlockEntry* Cluster::GetLast() +{ + if (m_entriesCount == 0) + return m_pEntries[0]; + + return m_pEntries[m_entriesCount-1]; +} + + +const BlockEntry* Cluster::GetNext(const BlockEntry* pEntry) const +{ + assert(pEntry); + + size_t idx = pEntry->GetIndex(); + + ++idx; + + if (idx == m_entriesCount) + return NULL; + + return m_pEntries[idx]; + +} + + +const BlockEntry* Cluster::GetEntry(const Track* pTrack) +{ + + assert(pTrack); + + if (m_pSegment == NULL) //EOS + return pTrack->GetEOS(); + + LoadBlockEntries(); + + BlockEntry* i = *m_pEntries; + BlockEntry* j = *m_pEntries + m_entriesCount; + while (i != j) + { + BlockEntry* pEntry = i; + i++; + assert(pEntry); + assert(!pEntry->EOS()); + + const Block* const pBlock = pEntry->GetBlock(); + assert(pBlock); + + if (pBlock->GetTrackNumber() != pTrack->GetNumber()) + continue; + + if (pTrack->VetEntry(pEntry)) + return pEntry; + } + + return pTrack->GetEOS(); //no satisfactory block found +} + + +BlockEntry::BlockEntry() +{ +} + + +BlockEntry::~BlockEntry() +{ +} + + + +SimpleBlock::SimpleBlock( + Cluster* pCluster, + size_t idx, + long long start, + long long size) : + m_pCluster(pCluster), + m_index(idx), + m_block(start, size, pCluster->m_pSegment->m_pReader) +{ +} + + +bool SimpleBlock::EOS() const +{ + return false; +} + + +Cluster* SimpleBlock::GetCluster() const +{ + return m_pCluster; +} + + +size_t SimpleBlock::GetIndex() const +{ + return m_index; +} + + +const Block* SimpleBlock::GetBlock() const +{ + return &m_block; +} + + +bool SimpleBlock::IsBFrame() const +{ + return false; +} + + +BlockGroup::BlockGroup( + Cluster* pCluster, + size_t idx, + long long start, + long long size_) : + m_pCluster(pCluster), + m_index(idx), + m_prevTimeCode(0), + m_nextTimeCode(0), + m_pBlock(NULL) //TODO: accept multiple blocks within a block group +{ + IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader; + + long long pos = start; + const long long stop = start + size_; + + bool bSimpleBlock = false; + + while (pos < stop) + { + short t; + + if (Match(pReader, pos, 0x7B, t)) + { + if (t < 0) + m_prevTimeCode = t; + else if (t > 0) + m_nextTimeCode = t; + else + assert(false); + } + else + { + long len; + const long long id = ReadUInt(pReader, pos, len); + assert(id >= 0); //TODO + assert((pos + len) <= stop); + + pos += len; //consume ID + + const long long size = ReadUInt(pReader, pos, len); + assert(size >= 0); //TODO + assert((pos + len) <= stop); + + pos += len; //consume size + + switch (id) + { + case 0x23: //SimpleBlock ID + bSimpleBlock = true; + //YES, FALL THROUGH TO NEXT CASE + + case 0x21: //Block ID + ParseBlock(pos, size); + break; + + default: + break; + } + + pos += size; //consume payload + assert(pos <= stop); + } + } + + assert(pos == stop); + assert(m_pBlock); + + if (!bSimpleBlock) + m_pBlock->SetKey(m_prevTimeCode >= 0); +} + + +BlockGroup::~BlockGroup() +{ + delete m_pBlock; +} + + +void BlockGroup::ParseBlock(long long start, long long size) +{ + IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader; + + Block* const pBlock = new Block(start, size, pReader); + assert(pBlock); //TODO + + //TODO: the Matroska spec says you have multiple blocks within the + //same block group, with blocks ranked by priority (the flag bits). + //I haven't ever seen such a file (mkvmux certainly doesn't make + //one), so until then I'll just assume block groups contain a single + //block. +#if 0 + m_blocks.push_back(pBlock); +#else + assert(m_pBlock == NULL); + m_pBlock = pBlock; +#endif + +#if 0 + Track* const pTrack = pBlock->GetTrack(); + assert(pTrack); + + pTrack->Insert(pBlock); +#endif +} + + +bool BlockGroup::EOS() const +{ + return false; +} + + +Cluster* BlockGroup::GetCluster() const +{ + return m_pCluster; +} + + +size_t BlockGroup::GetIndex() const +{ + return m_index; +} + + +const Block* BlockGroup::GetBlock() const +{ + return m_pBlock; +} + + +short BlockGroup::GetPrevTimeCode() const +{ + return m_prevTimeCode; +} + + +short BlockGroup::GetNextTimeCode() const +{ + return m_nextTimeCode; +} + + +bool BlockGroup::IsBFrame() const +{ + return (m_nextTimeCode > 0); +} + + + +Block::Block(long long start, long long size_, IMkvReader* pReader) : + m_start(start), + m_size(size_) +{ + long long pos = start; + const long long stop = start + size_; + + long len; + + m_track = ReadUInt(pReader, pos, len); + assert(m_track > 0); + assert((pos + len) <= stop); + + pos += len; //consume track number + assert((stop - pos) >= 2); + + m_timecode = Unserialize2SInt(pReader, pos); + + pos += 2; + assert((stop - pos) >= 1); + + const long hr = pReader->Read(pos, 1, &m_flags); + assert(hr == 0L); + + ++pos; + assert(pos <= stop); + + m_frameOff = pos; + + const long long frame_size = stop - pos; + + assert(frame_size <= 2147483647L); + + m_frameSize = static_cast(frame_size); +} + + +long long Block::GetTimeCode(Cluster* pCluster) const +{ + assert(pCluster); + + const long long tc0 = pCluster->GetTimeCode(); + assert(tc0 >= 0); + + const long long tc = tc0 + static_cast(m_timecode); + assert(tc >= 0); + + return tc; //unscaled timecode units +} + + +long long Block::GetTime(Cluster* pCluster) const +{ + assert(pCluster); + + const long long tc = GetTimeCode(pCluster); + + const Segment* const pSegment = pCluster->m_pSegment; + const SegmentInfo* const pInfo = pSegment->GetInfo(); + assert(pInfo); + + const long long scale = pInfo->GetTimeCodeScale(); + assert(scale >= 1); + + const long long ns = tc * scale; + + return ns; +} + + +unsigned long Block::GetTrackNumber() const +{ + assert(m_track > 0); + + return static_cast(m_track); +} + + +bool Block::IsKey() const +{ + return ((m_flags & static_cast(1 << 7)) != 0); +} + + +void Block::SetKey(bool bKey) +{ + if (bKey) + m_flags |= static_cast(1 << 7); + else + m_flags &= 0x7F; +} + + +long Block::GetSize() const +{ + return m_frameSize; +} + + +long Block::Read(IMkvReader* pReader, unsigned char* buf) const +{ + + assert(pReader); + assert(buf); + + const long hr = pReader->Read(m_frameOff, m_frameSize, buf); + + return hr; +} + + +} //end namespace mkvparser diff --git a/media/libstagefright/matroska/mkvparser.hpp b/media/libstagefright/matroska/mkvparser.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4d311b48615accb51107cac5c85a214bd4efdf12 --- /dev/null +++ b/media/libstagefright/matroska/mkvparser.hpp @@ -0,0 +1,428 @@ +#ifndef MKVPARSER_HPP +#define MKVPARSER_HPP + +#include +#include + +namespace mkvparser +{ + +const int E_FILE_FORMAT_INVALID = -2; +const int E_BUFFER_NOT_FULL = -3; + +class IMkvReader +{ +public: + virtual int Read(long long position, long length, unsigned char* buffer) = 0; + virtual int Length(long long* total, long long* available) = 0; +protected: + virtual ~IMkvReader(); +}; + +long long GetUIntLength(IMkvReader*, long long, long&); +long long ReadUInt(IMkvReader*, long long, long&); +long long SyncReadUInt(IMkvReader*, long long pos, long long stop, long&); +long long UnserializeUInt(IMkvReader*, long long pos, long long size); +float Unserialize4Float(IMkvReader*, long long); +double Unserialize8Double(IMkvReader*, long long); +short Unserialize2SInt(IMkvReader*, long long); +signed char Unserialize1SInt(IMkvReader*, long long); +bool Match(IMkvReader*, long long&, unsigned long, long long&); +bool Match(IMkvReader*, long long&, unsigned long, char*&); +bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&, + size_t *optionalSize = NULL); +bool Match(IMkvReader*, long long&, unsigned long, double&); +bool Match(IMkvReader*, long long&, unsigned long, short&); + + +struct EBMLHeader +{ + EBMLHeader(); + ~EBMLHeader(); + long long m_version; + long long m_readVersion; + long long m_maxIdLength; + long long m_maxSizeLength; + char* m_docType; + long long m_docTypeVersion; + long long m_docTypeReadVersion; + + long long Parse(IMkvReader*, long long&); +}; + + +class Segment; +class Track; +class Cluster; + +class Block +{ + Block(const Block&); + Block& operator=(const Block&); + +public: + const long long m_start; + const long long m_size; + + Block(long long start, long long size, IMkvReader*); + + unsigned long GetTrackNumber() const; + + long long GetTimeCode(Cluster*) const; //absolute, but not scaled + long long GetTime(Cluster*) const; //absolute, and scaled (nanosecond units) + bool IsKey() const; + void SetKey(bool); + + long GetSize() const; + long Read(IMkvReader*, unsigned char*) const; + +private: + long long m_track; //Track::Number() + short m_timecode; //relative to cluster + unsigned char m_flags; + long long m_frameOff; + long m_frameSize; + +}; + + +class BlockEntry +{ + BlockEntry(const BlockEntry&); + BlockEntry& operator=(const BlockEntry&); + +public: + virtual ~BlockEntry(); + virtual bool EOS() const = 0; + virtual Cluster* GetCluster() const = 0; + virtual size_t GetIndex() const = 0; + virtual const Block* GetBlock() const = 0; + virtual bool IsBFrame() const = 0; + +protected: + BlockEntry(); + +}; + + +class SimpleBlock : public BlockEntry +{ + SimpleBlock(const SimpleBlock&); + SimpleBlock& operator=(const SimpleBlock&); + +public: + SimpleBlock(Cluster*, size_t, long long start, long long size); + + bool EOS() const; + Cluster* GetCluster() const; + size_t GetIndex() const; + const Block* GetBlock() const; + bool IsBFrame() const; + +protected: + Cluster* const m_pCluster; + const size_t m_index; + Block m_block; + +}; + + +class BlockGroup : public BlockEntry +{ + BlockGroup(const BlockGroup&); + BlockGroup& operator=(const BlockGroup&); + +public: + BlockGroup(Cluster*, size_t, long long, long long); + ~BlockGroup(); + + bool EOS() const; + Cluster* GetCluster() const; + size_t GetIndex() const; + const Block* GetBlock() const; + bool IsBFrame() const; + + short GetPrevTimeCode() const; //relative to block's time + short GetNextTimeCode() const; //as above + +protected: + Cluster* const m_pCluster; + const size_t m_index; + +private: + BlockGroup(Cluster*, size_t, unsigned long); + void ParseBlock(long long start, long long size); + + short m_prevTimeCode; + short m_nextTimeCode; + + //TODO: the Matroska spec says you can have multiple blocks within the + //same block group, with blocks ranked by priority (the flag bits). + //For now we just cache a single block. +#if 0 + typedef std::deque blocks_t; + blocks_t m_blocks; //In practice should contain only a single element. +#else + Block* m_pBlock; +#endif + +}; + + +class Track +{ + Track(const Track&); + Track& operator=(const Track&); + +public: + Segment* const m_pSegment; + virtual ~Track(); + + long long GetType() const; + unsigned long GetNumber() const; + const char* GetNameAsUTF8() const; + const char* GetCodecNameAsUTF8() const; + const char* GetCodecId() const; + const unsigned char* GetCodecPrivate( + size_t *optionalSize = NULL) const; + + const BlockEntry* GetEOS() const; + + struct Settings + { + long long start; + long long size; + }; + + struct Info + { + long long type; + long long number; + long long uid; + char* nameAsUTF8; + char* codecId; + unsigned char* codecPrivate; + size_t codecPrivateSize; + char* codecNameAsUTF8; + Settings settings; + Info(); + void Clear(); + }; + + long GetFirst(const BlockEntry*&) const; + long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const; + virtual bool VetEntry(const BlockEntry*) const = 0; + +protected: + Track(Segment*, const Info&); + const Info m_info; + + class EOSBlock : public BlockEntry + { + public: + EOSBlock(); + + bool EOS() const; + Cluster* GetCluster() const; + size_t GetIndex() const; + const Block* GetBlock() const; + bool IsBFrame() const; + }; + + EOSBlock m_eos; + +}; + + +class VideoTrack : public Track +{ + VideoTrack(const VideoTrack&); + VideoTrack& operator=(const VideoTrack&); + +public: + VideoTrack(Segment*, const Info&); + long long GetWidth() const; + long long GetHeight() const; + double GetFrameRate() const; + + bool VetEntry(const BlockEntry*) const; + +private: + long long m_width; + long long m_height; + double m_rate; + +}; + + +class AudioTrack : public Track +{ + AudioTrack(const AudioTrack&); + AudioTrack& operator=(const AudioTrack&); + +public: + AudioTrack(Segment*, const Info&); + double GetSamplingRate() const; + long long GetChannels() const; + long long GetBitDepth() const; + bool VetEntry(const BlockEntry*) const; + +private: + double m_rate; + long long m_channels; + long long m_bitDepth; +}; + + +class Tracks +{ + Tracks(const Tracks&); + Tracks& operator=(const Tracks&); + +public: + Segment* const m_pSegment; + const long long m_start; + const long long m_size; + + Tracks(Segment*, long long start, long long size); + virtual ~Tracks(); + + Track* GetTrackByNumber(unsigned long tn) const; + Track* GetTrackByIndex(unsigned long idx) const; + +private: + Track** m_trackEntries; + Track** m_trackEntriesEnd; + + void ParseTrackEntry(long long, long long, Track*&); + +public: + unsigned long GetTracksCount() const; +}; + + +class SegmentInfo +{ + SegmentInfo(const SegmentInfo&); + SegmentInfo& operator=(const SegmentInfo&); + +public: + Segment* const m_pSegment; + const long long m_start; + const long long m_size; + + SegmentInfo(Segment*, long long start, long long size); + ~SegmentInfo(); + long long GetTimeCodeScale() const; + long long GetDuration() const; //scaled + const char* GetMuxingAppAsUTF8() const; + const char* GetWritingAppAsUTF8() const; + const char* GetTitleAsUTF8() const; + +private: + long long m_timecodeScale; + double m_duration; + char* m_pMuxingAppAsUTF8; + char* m_pWritingAppAsUTF8; + char* m_pTitleAsUTF8; +}; + + +class Cluster +{ + Cluster(const Cluster&); + Cluster& operator=(const Cluster&); + +public: + Segment* const m_pSegment; + const size_t m_index; + +public: + static Cluster* Parse(Segment*, size_t, long long off); + + Cluster(); //EndOfStream + ~Cluster(); + + bool EOS() const; + + long long GetTimeCode(); //absolute, but not scaled + long long GetTime(); //absolute, and scaled (nanosecond units) + + const BlockEntry* GetFirst(); + const BlockEntry* GetLast(); + const BlockEntry* GetNext(const BlockEntry*) const; + const BlockEntry* GetEntry(const Track*); +protected: + Cluster(Segment*, size_t, long long off); + +private: + long long m_start; + long long m_size; + long long m_timecode; + BlockEntry** m_pEntries; + size_t m_entriesCount; + + void Load(); + void LoadBlockEntries(); + void ParseBlockGroup(long long, long long, size_t); + void ParseSimpleBlock(long long, long long, size_t); + +}; + + +class Segment +{ + Segment(const Segment&); + Segment& operator=(const Segment&); + +private: + Segment(IMkvReader*, long long pos, long long size); + +public: + IMkvReader* const m_pReader; + const long long m_start; //posn of segment payload + const long long m_size; //size of segment payload + Cluster m_eos; //TODO: make private? + + static long long CreateInstance(IMkvReader*, long long, Segment*&); + ~Segment(); + + //for big-bang loading (source filter) + long Load(); + + //for incremental loading (splitter) + long long Unparsed() const; + long long ParseHeaders(); + long ParseCluster(Cluster*&, long long& newpos) const; + bool AddCluster(Cluster*, long long); + + Tracks* GetTracks() const; + const SegmentInfo* const GetInfo() const; + long long GetDuration() const; + + //NOTE: this turned out to be too inefficient. + //long long Load(long long time_nanoseconds); + + Cluster* GetFirst(); + Cluster* GetLast(); + unsigned long GetCount() const; + + Cluster* GetNext(const Cluster*); + Cluster* GetCluster(long long time_nanoseconds); + +private: + long long m_pos; //absolute file posn; what has been consumed so far + SegmentInfo* m_pInfo; + Tracks* m_pTracks; + Cluster** m_clusters; + size_t m_clusterCount; + + void ParseSeekHead(long long pos, long long size, size_t*); + void ParseSeekEntry(long long pos, long long size, size_t*); + void ParseSecondarySeekHead(long long off, size_t*); +}; + + +} //end namespace mkvparser + +#endif //MKVPARSER_HPP diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index c1a010c2cbbf2efdc1215489d619b181c82457b0..5db516e9c72705d0480fff4db56a54001ca93c34 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -264,6 +264,8 @@ status_t OMXNodeInstance::useBuffer( return UNKNOWN_ERROR; } + CHECK_EQ(header->pAppPrivate, buffer_meta); + *buffer = header; addActiveBuffer(portIndex, *buffer); @@ -294,6 +296,8 @@ status_t OMXNodeInstance::allocateBuffer( return UNKNOWN_ERROR; } + CHECK_EQ(header->pAppPrivate, buffer_meta); + *buffer = header; *buffer_data = header->pBuffer; @@ -325,6 +329,8 @@ status_t OMXNodeInstance::allocateBufferWithBackup( return UNKNOWN_ERROR; } + CHECK_EQ(header->pAppPrivate, buffer_meta); + *buffer = header; addActiveBuffer(portIndex, *buffer); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java index 2e599f22acda3aa51d18ce14acfdc1f98b468b93..bbd6bea6bf249a5a900cc47301a0392f19ba5849 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java @@ -19,21 +19,20 @@ package com.android.mediaframeworktest.functional; import com.android.mediaframeworktest.MediaFrameworkTest; import com.android.mediaframeworktest.MediaNames; -import java.io.*; - import android.content.Context; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.hardware.Camera.PreviewCallback; import android.hardware.Camera.ShutterCallback; +import android.os.ConditionVariable; +import android.os.Environment; +import android.os.Looper; import android.test.ActivityInstrumentationTestCase; +import android.test.suitebuilder.annotation.LargeTest; import android.util.Log; import android.view.SurfaceHolder; -import android.os.ConditionVariable; -import android.os.Looper; - -import android.test.suitebuilder.annotation.LargeTest; +import java.io.*; /** * Junit / Instrumentation test case for the camera api @@ -153,7 +152,8 @@ public class CameraTest extends ActivityInstrumentationTestCase +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Temporary until native surface API is defined. +struct android_surface_t; +typedef struct android_surface_t android_surface_t; + +struct android_activity_callbacks_t; + +/** + * This structure defines the native side of an android.app.NativeActivity. + * It is created by the framework, and handed to the application's native + * code as it is being launched. + */ +typedef struct android_activity_t { + /** + * Pointer to the callback function table of the native application. + * You can set the functions here to your own callbacks. The callbacks + * pointer itself here should not be changed; it is allocated and managed + * for you by the framework. + */ + struct android_activity_callbacks_t* callbacks; + + /** + * JNI context for the main thread of the app. + */ + JNIEnv* env; + + /** + * The NativeActivity Java class. + */ + jobject clazz; + + /** + * This is the native instance of the application. It is not used by + * the framework, but can be set by the application to its own instance + * state. + */ + void* instance; +} android_activity_t; + +/** + * These are the callbacks the framework makes into a native application. + * All of these callbacks happen on the main thread of the application. + * By default, all callbacks are NULL; set to a pointer to your own function + * to have it called. + */ +typedef struct android_activity_callbacks_t { + /** + * NativeActivity has started. See Java documentation for Activity.onStart() + * for more information. + */ + void (*onStart)(android_activity_t* activity); + + /** + * NativeActivity has resumed. See Java documentation for Activity.onResume() + * for more information. + */ + void (*onResume)(android_activity_t* activity); + + /** + * Framework is asking NativeActivity to save its current instance state. + * See Java documentation for Activity.onSaveInstanceState() for more + * information. The returned pointer needs to be created with malloc(); + * the framework will call free() on it for you. You also must fill in + * outSize with the number of bytes in the allocation. Note that the + * saved state will be persisted, so it can not contain any active + * entities (pointers to memory, file descriptors, etc). + */ + void* (*onSaveInstanceState)(android_activity_t* activity, size_t* outSize); + + /** + * NativeActivity has paused. See Java documentation for Activity.onPause() + * for more information. + */ + void (*onPause)(android_activity_t* activity); + + /** + * NativeActivity has stopped. See Java documentation for Activity.onStop() + * for more information. + */ + void (*onStop)(android_activity_t* activity); + + /** + * NativeActivity is being destroyed. See Java documentation for Activity.onDestroy() + * for more information. + */ + void (*onDestroy)(android_activity_t* activity); + + /** + * Focus has changed in this NativeActivity's window. This is often used, + * for example, to pause a game when it loses input focus. + */ + void (*onWindowFocusChanged)(android_activity_t* activity, int hasFocus); + + /** + * The drawing surface for this native activity has been created. You + * can use the given surface object to start drawing. NOTE: surface + * drawing API is not yet defined. + */ + void (*onSurfaceCreated)(android_activity_t* activity, android_surface_t* surface); + + /** + * The drawing surface for this native activity has changed. The surface + * given here is guaranteed to be the same as the one last given to + * onSurfaceCreated. This is simply to inform you about interesting + * changed to that surface. + */ + void (*onSurfaceChanged)(android_activity_t* activity, android_surface_t* surface, + int format, int width, int height); + + /** + * The drawing surface for this native activity is going to be destroyed. + * You MUST ensure that you do not touch the surface object after returning + * from this function: in the common case of drawing to the surface from + * another thread, that means the implementation of this callback must + * properly synchronize with the other thread to stop its drawing before + * returning from here. + */ + void (*onSurfaceDestroyed)(android_activity_t* activity, android_surface_t* surface); + + /** + * The system is running low on memory. Use this callback to release + * resources you do not need, to help the system avoid killing more + * important processes. + */ + void (*onLowMemory)(android_activity_t* activity); +} android_activity_callbacks_t; + +/** + * This is the function that must be in the native code to instantiate the + * application's native activity. It is called with the activity instance (see + * above); if the code is being instantiated from a previously saved instance, + * the savedState will be non-NULL and point to the saved data. + */ +typedef void android_activity_create_t(android_activity_t* activity, + void* savedState, size_t savedStateSize); + +/** + * The name of the function that NativeInstance looks for when launching its + * native code. + */ +extern android_activity_create_t android_onCreateActivity; + +#ifdef __cplusplus +}; +#endif + +#endif // ANDROID_NATIVE_ACTIVITY_H + diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index f904cdf6babbb0b65da366ceb0f30bf1a600d6c8..2ff231da52ec606c124cb4fd24d42237293f3775 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -222,7 +222,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback // underlying surface is created and destroyed SurfaceHolder holder = getHolder(); holder.addCallback(this); - holder.setFormat(PixelFormat.RGB_565); // setType is not needed for SDK 2.0 or newer. Uncomment this // statement if back-porting this code to older SDKs. // holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk index 6cb146c0609469e576f98b50c913e1b70d6c36c6..8abd6499689ba3ec33053c23be6e3aae1c427792 100644 --- a/opengl/libagl/Android.mk +++ b/opengl/libagl/Android.mk @@ -37,6 +37,10 @@ ifeq ($(TARGET_ARCH),arm) LOCAL_CFLAGS += -fstrict-aliasing endif +ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) + LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER +endif + ifneq ($(TARGET_SIMULATOR),true) # we need to access the private Bionic header # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index b6e0aae74ee8d54729cd1edd59baf0ba2ebb8131..7cb01d0e1a0bb562495b27c8cd92d85c27131ef8 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -1525,8 +1525,13 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, } if (ggl_unlikely(attrib_list==0)) { - *num_config = 0; - return EGL_TRUE; + /* + * A NULL attrib_list should be treated as though it was an empty + * one (terminated with EGL_NONE) as defined in + * section 3.4.1 "Querying Configurations" in the EGL specification. + */ + static const EGLint dummy = EGL_NONE; + attrib_list = &dummy; } int numAttributes = 0; diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp index 9407bd55305e4122a14c0ce594b66771ec02cf6e..d67612e681a8f8938db499f0f1dc6c3a17c62df8 100644 --- a/opengl/libagl/texture.cpp +++ b/opengl/libagl/texture.cpp @@ -1515,7 +1515,7 @@ void glReadPixels( ogles_error(c, GL_INVALID_VALUE); return; } - if (x<0 || x<0) { + if (x<0 || y<0) { ogles_error(c, GL_INVALID_VALUE); return; } diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index 89b3e1f2abca8aedc2fae8243f905838ed68b786..ba09d082feecceb1a140e474fc5ef7af0d951b70 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -239,7 +239,7 @@ struct tls_t // ---------------------------------------------------------------------------- -egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS]; +static egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS]; static egl_display_t gDisplay[NUM_DISPLAYS]; static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_key_t gEGLThreadLocalStorageKey = -1; @@ -843,10 +843,12 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, EGLint patch_index = -1; GLint attr; size_t size = 0; - while ((attr=attrib_list[size]) != EGL_NONE) { - if (attr == EGL_CONFIG_ID) - patch_index = size; - size += 2; + if (attrib_list) { + while ((attr=attrib_list[size]) != EGL_NONE) { + if (attr == EGL_CONFIG_ID) + patch_index = size; + size += 2; + } } if (patch_index >= 0) { size += 2; // we need copy the sentinel as well diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h index 1fba209f77072f1ab63c0bb8d2bf7c19483167fe..c8f529ac0569af7496f8f8c7b89c0fc365cc85ee 100644 --- a/opengl/libs/egl_impl.h +++ b/opengl/libs/egl_impl.h @@ -31,6 +31,7 @@ namespace android { struct egl_connection_t { + inline egl_connection_t() : dso(0) { } void * dso; gl_hooks_t * hooks[2]; EGLint major; diff --git a/opengl/tests/gl_jni/jni/gl_code.cpp b/opengl/tests/gl_jni/jni/gl_code.cpp index 33b25ab6c7750eb7dda52c51018d6561e48f3524..f031c79cd33e69aefdad94d5cdc765c81902fdaf 100644 --- a/opengl/tests/gl_jni/jni/gl_code.cpp +++ b/opengl/tests/gl_jni/jni/gl_code.cpp @@ -180,4 +180,5 @@ JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_step(JNIEnv * env, jobjec JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_changeBackground(JNIEnv * env, jobject obj) { background = 1.0f - background; -} \ No newline at end of file +} + diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml index d057ab7fdb518fe36d960f0ab6885b11af802159..dd0d064ceeef3241c31841c4ba880113baa89107 100644 --- a/packages/SettingsProvider/AndroidManifest.xml +++ b/packages/SettingsProvider/AndroidManifest.xml @@ -8,6 +8,8 @@ android:backupAgent="SettingsBackupAgent" android:killAfterRestore="false" android:icon="@drawable/ic_launcher_settings"> + + = 0) { // remove the provider from the list if present - // remove leading and trailing commas - if (index > 0) index--; - if (end < providers.length()) end++; + // remove leading or trailing comma + if (index > 0) { + index--; + } else if (end < providers.length()) { + end++; + } newProviders = providers.substring(0, index); if (end < providers.length()) { diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java index 5672a016ec9b0f915be209da4a4f5ab7c2ea98e3..eeafd5a1639cc052dd246e9fabc2f6481091823b 100644 --- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java +++ b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java @@ -52,8 +52,11 @@ public class VpnServiceBinder extends Service { // The actual implementation is delegated to the VpnService class. private VpnService mService; + // TODO(oam): Test VPN when EFS is enabled (will do later)... private static String getStateFilePath() { - return Environment.getDataDirectory().getPath() + STATES_FILE_RELATIVE_PATH; + // This call will return the correcu directory whether Encrypted FS is enabled or not + // Disabled: /data/misc/vpn/.states Enabled: /data/secure/misc/vpn/.states + return Environment.getSecureDataDirectory().getPath() + STATES_FILE_RELATIVE_PATH; } private final IBinder mBinder = new IVpnService.Stub() { diff --git a/policy/Android.mk b/policy/Android.mk new file mode 100644 index 0000000000000000000000000000000000000000..a887142601bd6e4174e1c45a828921ab7811e58a --- /dev/null +++ b/policy/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) + +# the library +# ============================================================ +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + $(call all-subdir-java-files) + +LOCAL_MODULE := android.policy + +include $(BUILD_JAVA_LIBRARY) diff --git a/policy/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/com/android/internal/policy/impl/AccountUnlockScreen.java new file mode 100644 index 0000000000000000000000000000000000000000..840c5e198e21c57f3ae8d86fead544aa0192fa4c --- /dev/null +++ b/policy/com/android/internal/policy/impl/AccountUnlockScreen.java @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +import com.android.internal.R; +import com.android.internal.widget.LockPatternUtils; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.accounts.OperationCanceledException; +import android.accounts.AccountManagerFuture; +import android.accounts.AuthenticatorException; +import android.accounts.AccountManagerCallback; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.Rect; +import android.text.Editable; +import android.text.InputFilter; +import android.text.LoginFilter; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.os.Bundle; + +import java.io.IOException; + +/** + * When the user forgets their password a bunch of times, we fall back on their + * account's login/password to unlock the phone (and reset their lock pattern). + */ +public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen, + KeyguardUpdateMonitor.InfoCallback,View.OnClickListener, TextWatcher { + private static final String LOCK_PATTERN_PACKAGE = "com.android.settings"; + private static final String LOCK_PATTERN_CLASS = + "com.android.settings.ChooseLockPattern"; + + /** + * The amount of millis to stay awake once this screen detects activity + */ + private static final int AWAKE_POKE_MILLIS = 30000; + + private final KeyguardScreenCallback mCallback; + private final LockPatternUtils mLockPatternUtils; + private KeyguardUpdateMonitor mUpdateMonitor; + + private TextView mTopHeader; + private TextView mInstructions; + private EditText mLogin; + private EditText mPassword; + private Button mOk; + private Button mEmergencyCall; + + /** + * Shown while making asynchronous check of password. + */ + private ProgressDialog mCheckingDialog; + + /** + * AccountUnlockScreen constructor. + * @param configuration + * @param updateMonitor + */ + public AccountUnlockScreen(Context context,Configuration configuration, + KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback, + LockPatternUtils lockPatternUtils) { + super(context); + mCallback = callback; + mLockPatternUtils = lockPatternUtils; + + LayoutInflater.from(context).inflate( + R.layout.keyguard_screen_glogin_unlock, this, true); + + mTopHeader = (TextView) findViewById(R.id.topHeader); + mTopHeader.setText(mLockPatternUtils.isPermanentlyLocked() ? + R.string.lockscreen_glogin_too_many_attempts : + R.string.lockscreen_glogin_forgot_pattern); + + mInstructions = (TextView) findViewById(R.id.instructions); + + mLogin = (EditText) findViewById(R.id.login); + mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } ); + mLogin.addTextChangedListener(this); + + mPassword = (EditText) findViewById(R.id.password); + mPassword.addTextChangedListener(this); + + mOk = (Button) findViewById(R.id.ok); + mOk.setOnClickListener(this); + + mEmergencyCall = (Button) findViewById(R.id.emergencyCall); + mEmergencyCall.setOnClickListener(this); + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall); + + mUpdateMonitor = updateMonitor; + mUpdateMonitor.registerInfoCallback(this); + } + + public void afterTextChanged(Editable s) { + } + + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + public void onTextChanged(CharSequence s, int start, int before, int count) { + mCallback.pokeWakelock(AWAKE_POKE_MILLIS); + } + + @Override + protected boolean onRequestFocusInDescendants(int direction, + Rect previouslyFocusedRect) { + // send focus to the login field + return mLogin.requestFocus(direction, previouslyFocusedRect); + } + + /** {@inheritDoc} */ + public boolean needsInput() { + return true; + } + + /** {@inheritDoc} */ + public void onPause() { + + } + + /** {@inheritDoc} */ + public void onResume() { + // start fresh + mLogin.setText(""); + mPassword.setText(""); + mLogin.requestFocus(); + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall); + } + + /** {@inheritDoc} */ + public void cleanUp() { + if (mCheckingDialog != null) { + mCheckingDialog.hide(); + } + mUpdateMonitor.removeCallback(this); + } + + /** {@inheritDoc} */ + public void onClick(View v) { + mCallback.pokeWakelock(); + if (v == mOk) { + asyncCheckPassword(); + } + + if (v == mEmergencyCall) { + mCallback.takeEmergencyCallAction(); + } + } + + private void postOnCheckPasswordResult(final boolean success) { + // ensure this runs on UI thread + mLogin.post(new Runnable() { + public void run() { + if (success) { + // clear out forgotten password + mLockPatternUtils.setPermanentlyLocked(false); + mLockPatternUtils.setLockPatternEnabled(false); + mLockPatternUtils.saveLockPattern(null); + + // launch the 'choose lock pattern' activity so + // the user can pick a new one if they want to + Intent intent = new Intent(); + intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + mCallback.reportSuccessfulUnlockAttempt(); + + // close the keyguard + mCallback.keyguardDone(true); + } else { + mInstructions.setText(R.string.lockscreen_glogin_invalid_input); + mPassword.setText(""); + mCallback.reportFailedUnlockAttempt(); + } + } + }); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN + && event.getKeyCode() == KeyEvent.KEYCODE_BACK) { + if (mLockPatternUtils.isPermanentlyLocked()) { + mCallback.goToLockScreen(); + } else { + mCallback.forgotPattern(false); + } + return true; + } + return super.dispatchKeyEvent(event); + } + + /** + * Given the string the user entered in the 'username' field, find + * the stored account that they probably intended. Prefer, in order: + * + * - an exact match for what was typed, or + * - a case-insensitive match for what was typed, or + * - if they didn't include a domain, an exact match of the username, or + * - if they didn't include a domain, a case-insensitive + * match of the username. + * + * If there is a tie for the best match, choose neither -- + * the user needs to be more specific. + * + * @return an account name from the database, or null if we can't + * find a single best match. + */ + private Account findIntendedAccount(String username) { + Account[] accounts = AccountManager.get(mContext).getAccountsByType("com.google"); + + // Try to figure out which account they meant if they + // typed only the username (and not the domain), or got + // the case wrong. + + Account bestAccount = null; + int bestScore = 0; + for (Account a: accounts) { + int score = 0; + if (username.equals(a.name)) { + score = 4; + } else if (username.equalsIgnoreCase(a.name)) { + score = 3; + } else if (username.indexOf('@') < 0) { + int i = a.name.indexOf('@'); + if (i >= 0) { + String aUsername = a.name.substring(0, i); + if (username.equals(aUsername)) { + score = 2; + } else if (username.equalsIgnoreCase(aUsername)) { + score = 1; + } + } + } + if (score > bestScore) { + bestAccount = a; + bestScore = score; + } else if (score == bestScore) { + bestAccount = null; + } + } + return bestAccount; + } + + private void asyncCheckPassword() { + mCallback.pokeWakelock(AWAKE_POKE_MILLIS); + final String login = mLogin.getText().toString(); + final String password = mPassword.getText().toString(); + Account account = findIntendedAccount(login); + if (account == null) { + postOnCheckPasswordResult(false); + return; + } + getProgressDialog().show(); + Bundle options = new Bundle(); + options.putString(AccountManager.KEY_PASSWORD, password); + AccountManager.get(mContext).confirmCredentials(account, options, null /* activity */, + new AccountManagerCallback() { + public void run(AccountManagerFuture future) { + try { + mCallback.pokeWakelock(AWAKE_POKE_MILLIS); + final Bundle result = future.getResult(); + final boolean verified = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT); + postOnCheckPasswordResult(verified); + } catch (OperationCanceledException e) { + postOnCheckPasswordResult(false); + } catch (IOException e) { + postOnCheckPasswordResult(false); + } catch (AuthenticatorException e) { + postOnCheckPasswordResult(false); + } finally { + mLogin.post(new Runnable() { + public void run() { + getProgressDialog().hide(); + } + }); + } + } + }, null /* handler */); + } + + private Dialog getProgressDialog() { + if (mCheckingDialog == null) { + mCheckingDialog = new ProgressDialog(mContext); + mCheckingDialog.setMessage( + mContext.getString(R.string.lockscreen_glogin_checking_password)); + mCheckingDialog.setIndeterminate(true); + mCheckingDialog.setCancelable(false); + mCheckingDialog.getWindow().setType( + WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + if (!mContext.getResources().getBoolean( + com.android.internal.R.bool.config_sf_slowBlur)) { + mCheckingDialog.getWindow().setFlags( + WindowManager.LayoutParams.FLAG_BLUR_BEHIND, + WindowManager.LayoutParams.FLAG_BLUR_BEHIND); + } + } + return mCheckingDialog; + } + + public void onPhoneStateChanged(String newState) { + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall); + } + + public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { + + } + + public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { + + } + + public void onRingerModeChanged(int state) { + + } + + public void onTimeChanged() { + + } +} diff --git a/policy/com/android/internal/policy/impl/GlobalActions.java b/policy/com/android/internal/policy/impl/GlobalActions.java new file mode 100644 index 0000000000000000000000000000000000000000..1f06dcc4c6f218cdd3ee220f0daf3b99455c2a5e --- /dev/null +++ b/policy/com/android/internal/policy/impl/GlobalActions.java @@ -0,0 +1,578 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.StatusBarManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.media.AudioManager; +import android.os.Handler; +import android.os.Message; +import android.os.SystemProperties; +import android.provider.Settings; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; +import android.telephony.TelephonyManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; +import com.android.internal.R; +import com.android.internal.app.ShutdownThread; +import com.android.internal.telephony.TelephonyIntents; +import com.android.internal.telephony.TelephonyProperties; +import com.google.android.collect.Lists; + +import java.util.ArrayList; + +/** + * Helper to show the global actions dialog. Each item is an {@link Action} that + * may show depending on whether the keyguard is showing, and whether the device + * is provisioned. + */ +class GlobalActions implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener { + + private static final String TAG = "GlobalActions"; + + private StatusBarManager mStatusBar; + + private final Context mContext; + private final AudioManager mAudioManager; + + private ArrayList mItems; + private AlertDialog mDialog; + + private ToggleAction mSilentModeToggle; + private ToggleAction mAirplaneModeOn; + + private MyAdapter mAdapter; + + private boolean mKeyguardShowing = false; + private boolean mDeviceProvisioned = false; + private ToggleAction.State mAirplaneState = ToggleAction.State.Off; + private boolean mIsWaitingForEcmExit = false; + + /** + * @param context everything needs a context :( + */ + public GlobalActions(Context context) { + mContext = context; + mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + + // receive broadcasts + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); + filter.addAction(Intent.ACTION_SCREEN_OFF); + filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); + context.registerReceiver(mBroadcastReceiver, filter); + + // get notified of phone state changes + TelephonyManager telephonyManager = + (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE); + } + + /** + * Show the global actions dialog (creating if necessary) + * @param keyguardShowing True if keyguard is showing + */ + public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) { + mKeyguardShowing = keyguardShowing; + mDeviceProvisioned = isDeviceProvisioned; + if (mDialog == null) { + mStatusBar = (StatusBarManager)mContext.getSystemService(Context.STATUS_BAR_SERVICE); + mDialog = createDialog(); + } + prepareDialog(); + + mStatusBar.disable(StatusBarManager.DISABLE_EXPAND); + mDialog.show(); + } + + /** + * Create the global actions dialog. + * @return A new dialog. + */ + private AlertDialog createDialog() { + mSilentModeToggle = new ToggleAction( + R.drawable.ic_lock_silent_mode, + R.drawable.ic_lock_silent_mode_off, + R.string.global_action_toggle_silent_mode, + R.string.global_action_silent_mode_on_status, + R.string.global_action_silent_mode_off_status) { + + void willCreate() { + // XXX: FIXME: switch to ic_lock_vibrate_mode when available + mEnabledIconResId = (Settings.System.getInt(mContext.getContentResolver(), + Settings.System.VIBRATE_IN_SILENT, 1) == 1) + ? R.drawable.ic_lock_silent_mode_vibrate + : R.drawable.ic_lock_silent_mode; + } + + void onToggle(boolean on) { + if (on) { + mAudioManager.setRingerMode((Settings.System.getInt(mContext.getContentResolver(), + Settings.System.VIBRATE_IN_SILENT, 1) == 1) + ? AudioManager.RINGER_MODE_VIBRATE + : AudioManager.RINGER_MODE_SILENT); + } else { + mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); + } + } + + public boolean showDuringKeyguard() { + return true; + } + + public boolean showBeforeProvisioning() { + return false; + } + }; + + mAirplaneModeOn = new ToggleAction( + R.drawable.ic_lock_airplane_mode, + R.drawable.ic_lock_airplane_mode_off, + R.string.global_actions_toggle_airplane_mode, + R.string.global_actions_airplane_mode_on_status, + R.string.global_actions_airplane_mode_off_status) { + + void onToggle(boolean on) { + if (Boolean.parseBoolean( + SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) { + mIsWaitingForEcmExit = true; + // Launch ECM exit dialog + Intent ecmDialogIntent = + new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null); + ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(ecmDialogIntent); + } else { + changeAirplaneModeSystemSetting(on); + } + } + + @Override + protected void changeStateFromPress(boolean buttonOn) { + // In ECM mode airplane state cannot be changed + if (!(Boolean.parseBoolean( + SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)))) { + mState = buttonOn ? State.TurningOn : State.TurningOff; + mAirplaneState = mState; + } + } + + public boolean showDuringKeyguard() { + return true; + } + + public boolean showBeforeProvisioning() { + return false; + } + }; + + mItems = Lists.newArrayList( + // silent mode + mSilentModeToggle, + // next: airplane mode + mAirplaneModeOn, + // last: power off + new SinglePressAction( + com.android.internal.R.drawable.ic_lock_power_off, + R.string.global_action_power_off) { + + public void onPress() { + // shutdown by making sure radio and power are handled accordingly. + ShutdownThread.shutdown(mContext, true); + } + + public boolean showDuringKeyguard() { + return true; + } + + public boolean showBeforeProvisioning() { + return true; + } + }); + + mAdapter = new MyAdapter(); + + final AlertDialog.Builder ab = new AlertDialog.Builder(mContext); + + ab.setAdapter(mAdapter, this) + .setInverseBackgroundForced(true) + .setTitle(R.string.global_actions); + + final AlertDialog dialog = ab.create(); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); + if (!mContext.getResources().getBoolean( + com.android.internal.R.bool.config_sf_slowBlur)) { + dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND, + WindowManager.LayoutParams.FLAG_BLUR_BEHIND); + } + + dialog.setOnDismissListener(this); + + return dialog; + } + + private void prepareDialog() { + final boolean silentModeOn = + mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL; + mSilentModeToggle.updateState( + silentModeOn ? ToggleAction.State.On : ToggleAction.State.Off); + mAirplaneModeOn.updateState(mAirplaneState); + mAdapter.notifyDataSetChanged(); + if (mKeyguardShowing) { + mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + } else { + mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); + } + } + + + /** {@inheritDoc} */ + public void onDismiss(DialogInterface dialog) { + mStatusBar.disable(StatusBarManager.DISABLE_NONE); + } + + /** {@inheritDoc} */ + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + mAdapter.getItem(which).onPress(); + } + + + /** + * The adapter used for the list within the global actions dialog, taking + * into account whether the keyguard is showing via + * {@link GlobalActions#mKeyguardShowing} and whether the device is provisioned + * via {@link GlobalActions#mDeviceProvisioned}. + */ + private class MyAdapter extends BaseAdapter { + + public int getCount() { + int count = 0; + + for (int i = 0; i < mItems.size(); i++) { + final Action action = mItems.get(i); + + if (mKeyguardShowing && !action.showDuringKeyguard()) { + continue; + } + if (!mDeviceProvisioned && !action.showBeforeProvisioning()) { + continue; + } + count++; + } + return count; + } + + @Override + public boolean isEnabled(int position) { + return getItem(position).isEnabled(); + } + + @Override + public boolean areAllItemsEnabled() { + return false; + } + + public Action getItem(int position) { + + int filteredPos = 0; + for (int i = 0; i < mItems.size(); i++) { + final Action action = mItems.get(i); + if (mKeyguardShowing && !action.showDuringKeyguard()) { + continue; + } + if (!mDeviceProvisioned && !action.showBeforeProvisioning()) { + continue; + } + if (filteredPos == position) { + return action; + } + filteredPos++; + } + + throw new IllegalArgumentException("position " + position + " out of " + + "range of showable actions, filtered count = " + + "= " + getCount() + ", keyguardshowing=" + mKeyguardShowing + + ", provisioned=" + mDeviceProvisioned); + } + + + public long getItemId(int position) { + return position; + } + + public View getView(int position, View convertView, ViewGroup parent) { + Action action = getItem(position); + return action.create(mContext, convertView, parent, LayoutInflater.from(mContext)); + } + } + + // note: the scheme below made more sense when we were planning on having + // 8 different things in the global actions dialog. seems overkill with + // only 3 items now, but may as well keep this flexible approach so it will + // be easy should someone decide at the last minute to include something + // else, such as 'enable wifi', or 'enable bluetooth' + + /** + * What each item in the global actions dialog must be able to support. + */ + private interface Action { + View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater); + + void onPress(); + + /** + * @return whether this action should appear in the dialog when the keygaurd + * is showing. + */ + boolean showDuringKeyguard(); + + /** + * @return whether this action should appear in the dialog before the + * device is provisioned. + */ + boolean showBeforeProvisioning(); + + boolean isEnabled(); + } + + /** + * A single press action maintains no state, just responds to a press + * and takes an action. + */ + private static abstract class SinglePressAction implements Action { + private final int mIconResId; + private final int mMessageResId; + + protected SinglePressAction(int iconResId, int messageResId) { + mIconResId = iconResId; + mMessageResId = messageResId; + } + + public boolean isEnabled() { + return true; + } + + abstract public void onPress(); + + public View create( + Context context, View convertView, ViewGroup parent, LayoutInflater inflater) { + View v = (convertView != null) ? + convertView : + inflater.inflate(R.layout.global_actions_item, parent, false); + + ImageView icon = (ImageView) v.findViewById(R.id.icon); + TextView messageView = (TextView) v.findViewById(R.id.message); + + v.findViewById(R.id.status).setVisibility(View.GONE); + + icon.setImageDrawable(context.getResources().getDrawable(mIconResId)); + messageView.setText(mMessageResId); + + return v; + } + } + + /** + * A toggle action knows whether it is on or off, and displays an icon + * and status message accordingly. + */ + private static abstract class ToggleAction implements Action { + + enum State { + Off(false), + TurningOn(true), + TurningOff(true), + On(false); + + private final boolean inTransition; + + State(boolean intermediate) { + inTransition = intermediate; + } + + public boolean inTransition() { + return inTransition; + } + } + + protected State mState = State.Off; + + // prefs + protected int mEnabledIconResId; + protected int mDisabledIconResid; + protected int mMessageResId; + protected int mEnabledStatusMessageResId; + protected int mDisabledStatusMessageResId; + + /** + * @param enabledIconResId The icon for when this action is on. + * @param disabledIconResid The icon for when this action is off. + * @param essage The general information message, e.g 'Silent Mode' + * @param enabledStatusMessageResId The on status message, e.g 'sound disabled' + * @param disabledStatusMessageResId The off status message, e.g. 'sound enabled' + */ + public ToggleAction(int enabledIconResId, + int disabledIconResid, + int essage, + int enabledStatusMessageResId, + int disabledStatusMessageResId) { + mEnabledIconResId = enabledIconResId; + mDisabledIconResid = disabledIconResid; + mMessageResId = essage; + mEnabledStatusMessageResId = enabledStatusMessageResId; + mDisabledStatusMessageResId = disabledStatusMessageResId; + } + + /** + * Override to make changes to resource IDs just before creating the + * View. + */ + void willCreate() { + + } + + public View create(Context context, View convertView, ViewGroup parent, + LayoutInflater inflater) { + willCreate(); + + View v = (convertView != null) ? + convertView : + inflater.inflate(R + .layout.global_actions_item, parent, false); + + ImageView icon = (ImageView) v.findViewById(R.id.icon); + TextView messageView = (TextView) v.findViewById(R.id.message); + TextView statusView = (TextView) v.findViewById(R.id.status); + + messageView.setText(mMessageResId); + + boolean on = ((mState == State.On) || (mState == State.TurningOn)); + icon.setImageDrawable(context.getResources().getDrawable( + (on ? mEnabledIconResId : mDisabledIconResid))); + statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId); + statusView.setVisibility(View.VISIBLE); + + final boolean enabled = isEnabled(); + messageView.setEnabled(enabled); + statusView.setEnabled(enabled); + icon.setEnabled(enabled); + v.setEnabled(enabled); + + return v; + } + + public final void onPress() { + if (mState.inTransition()) { + Log.w(TAG, "shouldn't be able to toggle when in transition"); + return; + } + + final boolean nowOn = !(mState == State.On); + onToggle(nowOn); + changeStateFromPress(nowOn); + } + + public boolean isEnabled() { + return !mState.inTransition(); + } + + /** + * Implementations may override this if their state can be in on of the intermediate + * states until some notification is received (e.g airplane mode is 'turning off' until + * we know the wireless connections are back online + * @param buttonOn Whether the button was turned on or off + */ + protected void changeStateFromPress(boolean buttonOn) { + mState = buttonOn ? State.On : State.Off; + } + + abstract void onToggle(boolean on); + + public void updateState(State state) { + mState = state; + } + } + + private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action) + || Intent.ACTION_SCREEN_OFF.equals(action)) { + String reason = intent.getStringExtra(PhoneWindowManager.SYSTEM_DIALOG_REASON_KEY); + if (!PhoneWindowManager.SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS.equals(reason)) { + mHandler.sendEmptyMessage(MESSAGE_DISMISS); + } + } else if (TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) { + // Airplane mode can be changed after ECM exits if airplane toggle button + // is pressed during ECM mode + if (!(intent.getBooleanExtra("PHONE_IN_ECM_STATE", false)) && + mIsWaitingForEcmExit) { + mIsWaitingForEcmExit = false; + changeAirplaneModeSystemSetting(true); + } + } + } + }; + + PhoneStateListener mPhoneStateListener = new PhoneStateListener() { + @Override + public void onServiceStateChanged(ServiceState serviceState) { + final boolean inAirplaneMode = serviceState.getState() == ServiceState.STATE_POWER_OFF; + mAirplaneState = inAirplaneMode ? ToggleAction.State.On : ToggleAction.State.Off; + mAirplaneModeOn.updateState(mAirplaneState); + mAdapter.notifyDataSetChanged(); + } + }; + + private static final int MESSAGE_DISMISS = 0; + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + if (msg.what == MESSAGE_DISMISS) { + if (mDialog != null) { + mDialog.dismiss(); + } + } + } + }; + + /** + * Change the airplane mode system setting + */ + private void changeAirplaneModeSystemSetting(boolean on) { + Settings.System.putInt( + mContext.getContentResolver(), + Settings.System.AIRPLANE_MODE_ON, + on ? 1 : 0); + Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + intent.putExtra("state", on); + mContext.sendBroadcast(intent); + } +} diff --git a/policy/com/android/internal/policy/impl/IconUtilities.java b/policy/com/android/internal/policy/impl/IconUtilities.java new file mode 100644 index 0000000000000000000000000000000000000000..99055cf731589ab244b614c805e7a5310977f817 --- /dev/null +++ b/policy/com/android/internal/policy/impl/IconUtilities.java @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.PaintDrawable; +import android.graphics.drawable.StateListDrawable; +import android.graphics.Bitmap; +import android.graphics.BlurMaskFilter; +import android.graphics.Canvas; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.Paint; +import android.graphics.PaintFlagsDrawFilter; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.TableMaskFilter; +import android.graphics.Typeface; +import android.text.Layout.Alignment; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.util.DisplayMetrics; +import android.util.Log; +import android.content.res.Resources; +import android.content.Context; + +/** + * Various utilities shared amongst the Launcher's classes. + */ +final class IconUtilities { + private static final String TAG = "IconUtilities"; + + private static final int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff }; + + private int mIconWidth = -1; + private int mIconHeight = -1; + private int mIconTextureWidth = -1; + private int mIconTextureHeight = -1; + + private final Paint mPaint = new Paint(); + private final Paint mBlurPaint = new Paint(); + private final Paint mGlowColorPressedPaint = new Paint(); + private final Paint mGlowColorFocusedPaint = new Paint(); + private final Rect mOldBounds = new Rect(); + private final Canvas mCanvas = new Canvas(); + private final DisplayMetrics mDisplayMetrics; + + private int mColorIndex = 0; + + public IconUtilities(Context context) { + final Resources resources = context.getResources(); + DisplayMetrics metrics = mDisplayMetrics = resources.getDisplayMetrics(); + final float density = metrics.density; + final float blurPx = 5 * density; + + mIconWidth = mIconHeight = (int) resources.getDimension(android.R.dimen.app_icon_size); + mIconTextureWidth = mIconTextureHeight = mIconWidth + (int)(blurPx*2); + + mBlurPaint.setMaskFilter(new BlurMaskFilter(blurPx, BlurMaskFilter.Blur.NORMAL)); + mGlowColorPressedPaint.setColor(0xffffc300); + mGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30)); + mGlowColorFocusedPaint.setColor(0xffff8e00); + mGlowColorFocusedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30)); + + ColorMatrix cm = new ColorMatrix(); + cm.setSaturation(0.2f); + + mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, + Paint.FILTER_BITMAP_FLAG)); + } + + public Drawable createIconDrawable(Drawable src) { + Bitmap scaled = createIconBitmap(src); + + StateListDrawable result = new StateListDrawable(); + + result.addState(new int[] { android.R.attr.state_focused }, + new BitmapDrawable(createSelectedBitmap(scaled, false))); + result.addState(new int[] { android.R.attr.state_pressed }, + new BitmapDrawable(createSelectedBitmap(scaled, true))); + result.addState(new int[0], new BitmapDrawable(scaled)); + + result.setBounds(0, 0, mIconTextureWidth, mIconTextureHeight); + return result; + } + + /** + * Returns a bitmap suitable for the all apps view. The bitmap will be a power + * of two sized ARGB_8888 bitmap that can be used as a gl texture. + */ + private Bitmap createIconBitmap(Drawable icon) { + int width = mIconWidth; + int height = mIconHeight; + + if (icon instanceof PaintDrawable) { + PaintDrawable painter = (PaintDrawable) icon; + painter.setIntrinsicWidth(width); + painter.setIntrinsicHeight(height); + } else if (icon instanceof BitmapDrawable) { + // Ensure the bitmap has a density. + BitmapDrawable bitmapDrawable = (BitmapDrawable) icon; + Bitmap bitmap = bitmapDrawable.getBitmap(); + if (bitmap.getDensity() == Bitmap.DENSITY_NONE) { + bitmapDrawable.setTargetDensity(mDisplayMetrics); + } + } + int sourceWidth = icon.getIntrinsicWidth(); + int sourceHeight = icon.getIntrinsicHeight(); + + if (sourceWidth > 0 && sourceWidth > 0) { + // There are intrinsic sizes. + if (width < sourceWidth || height < sourceHeight) { + // It's too big, scale it down. + final float ratio = (float) sourceWidth / sourceHeight; + if (sourceWidth > sourceHeight) { + height = (int) (width / ratio); + } else if (sourceHeight > sourceWidth) { + width = (int) (height * ratio); + } + } else if (sourceWidth < width && sourceHeight < height) { + // It's small, use the size they gave us. + width = sourceWidth; + height = sourceHeight; + } + } + + // no intrinsic size --> use default size + int textureWidth = mIconTextureWidth; + int textureHeight = mIconTextureHeight; + + final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight, + Bitmap.Config.ARGB_8888); + final Canvas canvas = mCanvas; + canvas.setBitmap(bitmap); + + final int left = (textureWidth-width) / 2; + final int top = (textureHeight-height) / 2; + + if (false) { + // draw a big box for the icon for debugging + canvas.drawColor(sColors[mColorIndex]); + if (++mColorIndex >= sColors.length) mColorIndex = 0; + Paint debugPaint = new Paint(); + debugPaint.setColor(0xffcccc00); + canvas.drawRect(left, top, left+width, top+height, debugPaint); + } + + mOldBounds.set(icon.getBounds()); + icon.setBounds(left, top, left+width, top+height); + icon.draw(canvas); + icon.setBounds(mOldBounds); + + return bitmap; + } + + private Bitmap createSelectedBitmap(Bitmap src, boolean pressed) { + final Bitmap result = Bitmap.createBitmap(mIconTextureWidth, mIconTextureHeight, + Bitmap.Config.ARGB_8888); + final Canvas dest = new Canvas(result); + + dest.drawColor(0, PorterDuff.Mode.CLEAR); + + int[] xy = new int[2]; + Bitmap mask = src.extractAlpha(mBlurPaint, xy); + + dest.drawBitmap(mask, xy[0], xy[1], + pressed ? mGlowColorPressedPaint : mGlowColorFocusedPaint); + + mask.recycle(); + + dest.drawBitmap(src, 0, 0, mPaint); + + return result; + } +} diff --git a/policy/com/android/internal/policy/impl/KeyguardScreen.java b/policy/com/android/internal/policy/impl/KeyguardScreen.java new file mode 100644 index 0000000000000000000000000000000000000000..bbb687554e739a29a77d70ce94de21dc72a20bfa --- /dev/null +++ b/policy/com/android/internal/policy/impl/KeyguardScreen.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +/** + * Common interface of each {@link android.view.View} that is a screen of + * {@link LockPatternKeyguardView}. + */ +public interface KeyguardScreen { + + /** + * Return true if your view needs input, so should allow the soft + * keyboard to be displayed. + */ + boolean needsInput(); + + /** + * This screen is no longer in front of the user. + */ + void onPause(); + + /** + * This screen is going to be in front of the user. + */ + void onResume(); + + /** + * This view is going away; a hook to do cleanup. + */ + void cleanUp(); +} diff --git a/policy/com/android/internal/policy/impl/KeyguardScreenCallback.java b/policy/com/android/internal/policy/impl/KeyguardScreenCallback.java new file mode 100644 index 0000000000000000000000000000000000000000..a84360340c91411d68b518f9d3c053318770c354 --- /dev/null +++ b/policy/com/android/internal/policy/impl/KeyguardScreenCallback.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +import android.content.res.Configuration; + +/** + * Within a keyguard, there may be several screens that need a callback + * to the host keyguard view. + */ +public interface KeyguardScreenCallback extends KeyguardViewCallback { + + /** + * Transition to the lock screen. + */ + void goToLockScreen(); + + /** + * Transition to the unlock screen. + */ + void goToUnlockScreen(); + + /** + * The user reported that they forgot their pattern (or not, when they want to back out of the + * forgot pattern screen). + * + * @param isForgotten True if the user hit the forgot pattern, false if they want to back out + * of the account screen. + */ + void forgotPattern(boolean isForgotten); + + /** + * @return Whether the keyguard requires some sort of PIN. + */ + boolean isSecure(); + + /** + * @return Whether we are in a mode where we only want to verify the + * user can get past the keyguard. + */ + boolean isVerifyUnlockOnly(); + + /** + * Stay on me, but recreate me (so I can use a different layout). + */ + void recreateMe(Configuration config); + + /** + * Take action to send an emergency call. + */ + void takeEmergencyCallAction(); + + /** + * Report that the user had a failed attempt to unlock with password or pattern. + */ + void reportFailedUnlockAttempt(); + + /** + * Report that the user successfully entered their password or pattern. + */ + void reportSuccessfulUnlockAttempt(); + + /** + * Report whether we there's another way to unlock the device. + * @return true + */ + boolean doesFallbackUnlockScreenExist(); +} diff --git a/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java new file mode 100644 index 0000000000000000000000000000000000000000..b225e56b3b7233c0a2be16bba1f0238e937d1729 --- /dev/null +++ b/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java @@ -0,0 +1,526 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Configuration; +import android.database.ContentObserver; +import static android.os.BatteryManager.BATTERY_STATUS_CHARGING; +import static android.os.BatteryManager.BATTERY_STATUS_FULL; +import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; +import android.media.AudioManager; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.provider.Settings; +import android.provider.Telephony; +import static android.provider.Telephony.Intents.EXTRA_PLMN; +import static android.provider.Telephony.Intents.EXTRA_SHOW_PLMN; +import static android.provider.Telephony.Intents.EXTRA_SHOW_SPN; +import static android.provider.Telephony.Intents.EXTRA_SPN; +import static android.provider.Telephony.Intents.SPN_STRINGS_UPDATED_ACTION; + +import com.android.internal.telephony.IccCard; +import com.android.internal.telephony.TelephonyIntents; + +import android.telephony.TelephonyManager; +import android.util.Log; +import com.android.internal.R; +import com.google.android.collect.Lists; + +import java.util.ArrayList; + +/** + * Watches for updates that may be interesting to the keyguard, and provides + * the up to date information as well as a registration for callbacks that care + * to be updated. + * + * Note: under time crunch, this has been extended to include some stuff that + * doesn't really belong here. see {@link #handleBatteryUpdate} where it shutdowns + * the device, and {@link #getFailedAttempts()}, {@link #reportFailedAttempt()} + * and {@link #clearFailedAttempts()}. Maybe we should rename this 'KeyguardContext'... + */ +public class KeyguardUpdateMonitor { + + static private final String TAG = "KeyguardUpdateMonitor"; + static private final boolean DEBUG = false; + + private static final int LOW_BATTERY_THRESHOLD = 20; + + private final Context mContext; + + private IccCard.State mSimState = IccCard.State.READY; + + private boolean mKeyguardBypassEnabled; + + private boolean mDevicePluggedIn; + + private boolean mDeviceProvisioned; + + private int mBatteryLevel; + + private CharSequence mTelephonyPlmn; + private CharSequence mTelephonySpn; + + private int mFailedAttempts = 0; + + private Handler mHandler; + + private ArrayList mInfoCallbacks = Lists.newArrayList(); + private ArrayList mSimStateCallbacks = Lists.newArrayList(); + private ContentObserver mContentObserver; + + // messages for the handler + private static final int MSG_TIME_UPDATE = 301; + private static final int MSG_BATTERY_UPDATE = 302; + private static final int MSG_CARRIER_INFO_UPDATE = 303; + private static final int MSG_SIM_STATE_CHANGE = 304; + private static final int MSG_RINGER_MODE_CHANGED = 305; + private static final int MSG_PHONE_STATE_CHANGED = 306; + + + /** + * When we receive a + * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast, + * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange}, + * we need a single object to pass to the handler. This class helps decode + * the intent and provide a {@link SimCard.State} result. + */ + private static class SimArgs { + + public final IccCard.State simState; + + private SimArgs(Intent intent) { + if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) { + throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED"); + } + String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE); + if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { + this.simState = IccCard.State.ABSENT; + } else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) { + this.simState = IccCard.State.READY; + } else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { + final String lockedReason = intent + .getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON); + if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { + this.simState = IccCard.State.PIN_REQUIRED; + } else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { + this.simState = IccCard.State.PUK_REQUIRED; + } else { + this.simState = IccCard.State.UNKNOWN; + } + } else if (IccCard.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) { + this.simState = IccCard.State.NETWORK_LOCKED; + } else { + this.simState = IccCard.State.UNKNOWN; + } + } + + public String toString() { + return simState.toString(); + } + } + + public KeyguardUpdateMonitor(Context context) { + mContext = context; + + mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_TIME_UPDATE: + handleTimeUpdate(); + break; + case MSG_BATTERY_UPDATE: + handleBatteryUpdate(msg.arg1, msg.arg2); + break; + case MSG_CARRIER_INFO_UPDATE: + handleCarrierInfoUpdate(); + break; + case MSG_SIM_STATE_CHANGE: + handleSimStateChange((SimArgs) msg.obj); + break; + case MSG_RINGER_MODE_CHANGED: + handleRingerModeChange(msg.arg1); + break; + case MSG_PHONE_STATE_CHANGED: + handlePhoneStateChanged((String)msg.obj); + break; + } + } + }; + + mKeyguardBypassEnabled = context.getResources().getBoolean( + com.android.internal.R.bool.config_bypass_keyguard_if_slider_open); + + mDeviceProvisioned = Settings.Secure.getInt( + mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0; + + // Since device can't be un-provisioned, we only need to register a content observer + // to update mDeviceProvisioned when we are... + if (!mDeviceProvisioned) { + mContentObserver = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + mDeviceProvisioned = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.DEVICE_PROVISIONED, 0) != 0; + if (mDeviceProvisioned && mContentObserver != null) { + // We don't need the observer anymore... + mContext.getContentResolver().unregisterContentObserver(mContentObserver); + mContentObserver = null; + } + if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned); + } + }; + + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.DEVICE_PROVISIONED), + false, mContentObserver); + + // prevent a race condition between where we check the flag and where we register the + // observer by grabbing the value once again... + mDeviceProvisioned = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.DEVICE_PROVISIONED, 0) != 0; + } + + // take a guess to start + mSimState = IccCard.State.READY; + mDevicePluggedIn = true; + mBatteryLevel = 100; + + mTelephonyPlmn = getDefaultPlmn(); + + // setup receiver + final IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_TIME_TICK); + filter.addAction(Intent.ACTION_TIME_CHANGED); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); + filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); + filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); + filter.addAction(SPN_STRINGS_UPDATED_ACTION); + filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); + context.registerReceiver(new BroadcastReceiver() { + + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (DEBUG) Log.d(TAG, "received broadcast " + action); + + if (Intent.ACTION_TIME_TICK.equals(action) + || Intent.ACTION_TIME_CHANGED.equals(action) + || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) { + mHandler.sendMessage(mHandler.obtainMessage(MSG_TIME_UPDATE)); + } else if (SPN_STRINGS_UPDATED_ACTION.equals(action)) { + mTelephonyPlmn = getTelephonyPlmnFrom(intent); + mTelephonySpn = getTelephonySpnFrom(intent); + mHandler.sendMessage(mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE)); + } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { + final int pluggedInStatus = intent + .getIntExtra("status", BATTERY_STATUS_UNKNOWN); + int batteryLevel = intent.getIntExtra("level", 0); + final Message msg = mHandler.obtainMessage( + MSG_BATTERY_UPDATE, + pluggedInStatus, + batteryLevel); + mHandler.sendMessage(msg); + } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) { + mHandler.sendMessage(mHandler.obtainMessage( + MSG_SIM_STATE_CHANGE, + new SimArgs(intent))); + } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) { + mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED, + intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0)); + } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) { + String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); + mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state)); + } + } + }, filter); + } + + protected void handlePhoneStateChanged(String newState) { + if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")"); + for (int i = 0; i < mInfoCallbacks.size(); i++) { + mInfoCallbacks.get(i).onPhoneStateChanged(newState); + } + } + + protected void handleRingerModeChange(int mode) { + if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")"); + for (int i = 0; i < mInfoCallbacks.size(); i++) { + mInfoCallbacks.get(i).onRingerModeChanged(mode); + } + } + + /** + * Handle {@link #MSG_TIME_UPDATE} + */ + private void handleTimeUpdate() { + if (DEBUG) Log.d(TAG, "handleTimeUpdate"); + for (int i = 0; i < mInfoCallbacks.size(); i++) { + mInfoCallbacks.get(i).onTimeChanged(); + } + } + + /** + * Handle {@link #MSG_BATTERY_UPDATE} + */ + private void handleBatteryUpdate(int pluggedInStatus, int batteryLevel) { + if (DEBUG) Log.d(TAG, "handleBatteryUpdate"); + final boolean pluggedIn = isPluggedIn(pluggedInStatus); + + if (isBatteryUpdateInteresting(pluggedIn, batteryLevel)) { + mBatteryLevel = batteryLevel; + mDevicePluggedIn = pluggedIn; + for (int i = 0; i < mInfoCallbacks.size(); i++) { + mInfoCallbacks.get(i).onRefreshBatteryInfo( + shouldShowBatteryInfo(), pluggedIn, batteryLevel); + } + } + } + + /** + * Handle {@link #MSG_CARRIER_INFO_UPDATE} + */ + private void handleCarrierInfoUpdate() { + if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn + + ", spn = " + mTelephonySpn); + + for (int i = 0; i < mInfoCallbacks.size(); i++) { + mInfoCallbacks.get(i).onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn); + } + } + + /** + * Handle {@link #MSG_SIM_STATE_CHANGE} + */ + private void handleSimStateChange(SimArgs simArgs) { + final IccCard.State state = simArgs.simState; + + if (DEBUG) { + Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " " + + "state resolved to " + state.toString()); + } + + if (state != IccCard.State.UNKNOWN && state != mSimState) { + mSimState = state; + for (int i = 0; i < mSimStateCallbacks.size(); i++) { + mSimStateCallbacks.get(i).onSimStateChanged(state); + } + } + } + + /** + * @param status One of the statuses of {@link android.os.BatteryManager} + * @return Whether the status maps to a status for being plugged in. + */ + private boolean isPluggedIn(int status) { + return status == BATTERY_STATUS_CHARGING || status == BATTERY_STATUS_FULL; + } + + private boolean isBatteryUpdateInteresting(boolean pluggedIn, int batteryLevel) { + // change in plug is always interesting + if (mDevicePluggedIn != pluggedIn) { + return true; + } + + // change in battery level while plugged in + if (pluggedIn && mBatteryLevel != batteryLevel) { + return true; + } + + if (!pluggedIn) { + // not plugged in and below threshold + if (batteryLevel < LOW_BATTERY_THRESHOLD && batteryLevel != mBatteryLevel) { + return true; + } + } + return false; + } + + /** + * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION} + * @return The string to use for the plmn, or null if it should not be shown. + */ + private CharSequence getTelephonyPlmnFrom(Intent intent) { + if (intent.getBooleanExtra(EXTRA_SHOW_PLMN, false)) { + final String plmn = intent.getStringExtra(EXTRA_PLMN); + if (plmn != null) { + return plmn; + } else { + return getDefaultPlmn(); + } + } + return null; + } + + /** + * @return The default plmn (no service) + */ + private CharSequence getDefaultPlmn() { + return mContext.getResources().getText( + R.string.lockscreen_carrier_default); + } + + /** + * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION} + * @return The string to use for the plmn, or null if it should not be shown. + */ + private CharSequence getTelephonySpnFrom(Intent intent) { + if (intent.getBooleanExtra(EXTRA_SHOW_SPN, false)) { + final String spn = intent.getStringExtra(EXTRA_SPN); + if (spn != null) { + return spn; + } + } + return null; + } + + /** + * Remove the given observer from being registered from any of the kinds + * of callbacks. + * @param observer The observer to remove (an instance of {@link ConfigurationChangeCallback}, + * {@link InfoCallback} or {@link SimStateCallback} + */ + public void removeCallback(Object observer) { + mInfoCallbacks.remove(observer); + mSimStateCallbacks.remove(observer); + } + + /** + * Callback for general information relevant to lock screen. + */ + interface InfoCallback { + void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel); + void onTimeChanged(); + + /** + * @param plmn The operator name of the registered network. May be null if it shouldn't + * be displayed. + * @param spn The service provider name. May be null if it shouldn't be displayed. + */ + void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn); + + /** + * Called when the ringer mode changes. + * @param state the current ringer state, as defined in + * {@link AudioManager#RINGER_MODE_CHANGED_ACTION} + */ + void onRingerModeChanged(int state); + + /** + * Called when the phone state changes. String will be one of: + * {@link TelephonyManager#EXTRA_STATE_IDLE} + * {@link TelephonyManager@EXTRA_STATE_RINGING} + * {@link TelephonyManager#EXTRA_STATE_OFFHOOK + */ + void onPhoneStateChanged(String newState); + } + + /** + * Callback to notify of sim state change. + */ + interface SimStateCallback { + void onSimStateChanged(IccCard.State simState); + } + + /** + * Register to receive notifications about general keyguard information + * (see {@link InfoCallback}. + * @param callback The callback. + */ + public void registerInfoCallback(InfoCallback callback) { + if (!mInfoCallbacks.contains(callback)) { + mInfoCallbacks.add(callback); + } else { + Log.e(TAG, "Object tried to add another INFO callback", new Exception("Whoops")); + } + } + + /** + * Register to be notified of sim state changes. + * @param callback The callback. + */ + public void registerSimStateCallback(SimStateCallback callback) { + if (!mSimStateCallbacks.contains(callback)) { + mSimStateCallbacks.add(callback); + } else { + Log.e(TAG, "Object tried to add another SIM callback", new Exception("Whoops")); + } + } + + public IccCard.State getSimState() { + return mSimState; + } + + /** + * Report that the user succesfully entered the sim pin so we + * have the information earlier than waiting for the intent + * broadcast from the telephony code. + */ + public void reportSimPinUnlocked() { + mSimState = IccCard.State.READY; + } + + public boolean isKeyguardBypassEnabled() { + return mKeyguardBypassEnabled; + } + + public boolean isDevicePluggedIn() { + return mDevicePluggedIn; + } + + public int getBatteryLevel() { + return mBatteryLevel; + } + + public boolean shouldShowBatteryInfo() { + return mDevicePluggedIn || mBatteryLevel < LOW_BATTERY_THRESHOLD; + } + + public CharSequence getTelephonyPlmn() { + return mTelephonyPlmn; + } + + public CharSequence getTelephonySpn() { + return mTelephonySpn; + } + + /** + * @return Whether the device is provisioned (whether they have gone through + * the setup wizard) + */ + public boolean isDeviceProvisioned() { + return mDeviceProvisioned; + } + + public int getFailedAttempts() { + return mFailedAttempts; + } + + public void clearFailedAttempts() { + mFailedAttempts = 0; + } + + public void reportFailedAttempt() { + mFailedAttempts++; + } +} diff --git a/policy/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/com/android/internal/policy/impl/KeyguardViewBase.java new file mode 100644 index 0000000000000000000000000000000000000000..9dcbcb6500caa1269bd8b15fd7125d5147d6e6c7 --- /dev/null +++ b/policy/com/android/internal/policy/impl/KeyguardViewBase.java @@ -0,0 +1,209 @@ +/* + * 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. + */ + +package com.android.internal.policy.impl; + +import android.content.Context; +import android.content.Intent; +import android.media.AudioManager; +import android.telephony.TelephonyManager; +import android.view.KeyEvent; +import android.view.View; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.util.AttributeSet; + +/** + * Base class for keyguard views. {@link #reset} is where you should + * reset the state of your view. Use the {@link KeyguardViewCallback} via + * {@link #getCallback()} to send information back (such as poking the wake lock, + * or finishing the keyguard). + * + * Handles intercepting of media keys that still work when the keyguard is + * showing. + */ +public abstract class KeyguardViewBase extends FrameLayout { + + private KeyguardViewCallback mCallback; + private AudioManager mAudioManager; + private TelephonyManager mTelephonyManager = null; + + public KeyguardViewBase(Context context) { + super(context); + + // drop shadow below status bar in keyguard too + mForegroundInPadding = false; + setForegroundGravity(Gravity.FILL_HORIZONTAL | Gravity.TOP); + setForeground( + context.getResources().getDrawable( + com.android.internal.R.drawable.title_bar_shadow)); + } + + // used to inject callback + void setCallback(KeyguardViewCallback callback) { + mCallback = callback; + } + + public KeyguardViewCallback getCallback() { + return mCallback; + } + + /** + * Called when you need to reset the state of your view. + */ + abstract public void reset(); + + /** + * Called when the screen turned off. + */ + abstract public void onScreenTurnedOff(); + + /** + * Called when the screen turned on. + */ + abstract public void onScreenTurnedOn(); + + /** + * Called when a key has woken the device to give us a chance to adjust our + * state according the the key. We are responsible for waking the device + * (by poking the wake lock) once we are ready. + * + * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}. + * Be sure not to take any action that takes a long time; any significant + * action should be posted to a handler. + * + * @param keyCode The wake key, which may be relevant for configuring the + * keyguard. + */ + abstract public void wakeWhenReadyTq(int keyCode); + + /** + * Verify that the user can get past the keyguard securely. This is called, + * for example, when the phone disables the keyguard but then wants to launch + * something else that requires secure access. + * + * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)} + */ + abstract public void verifyUnlock(); + + /** + * Called before this view is being removed. + */ + abstract public void cleanUp(); + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (shouldEventKeepScreenOnWhileKeyguardShowing(event)) { + mCallback.pokeWakelock(); + } + + if (interceptMediaKey(event)) { + return true; + } + return super.dispatchKeyEvent(event); + } + + private boolean shouldEventKeepScreenOnWhileKeyguardShowing(KeyEvent event) { + if (event.getAction() != KeyEvent.ACTION_DOWN) { + return false; + } + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + case KeyEvent.KEYCODE_DPAD_UP: + return false; + default: + return true; + } + } + + /** + * Allows the media keys to work when the keyguard is showing. + * The media keys should be of no interest to the actual keyguard view(s), + * so intercepting them here should not be of any harm. + * @param event The key event + * @return whether the event was consumed as a media key. + */ + private boolean interceptMediaKey(KeyEvent event) { + final int keyCode = event.getKeyCode(); + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (keyCode) { + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + /* Suppress PLAYPAUSE toggle when phone is ringing or + * in-call to avoid music playback */ + if (mTelephonyManager == null) { + mTelephonyManager = (TelephonyManager) getContext().getSystemService( + Context.TELEPHONY_SERVICE); + } + if (mTelephonyManager != null && + mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { + return true; // suppress key event + } + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { + Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); + intent.putExtra(Intent.EXTRA_KEY_EVENT, event); + getContext().sendOrderedBroadcast(intent, null); + return true; + } + + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_DOWN: { + synchronized (this) { + if (mAudioManager == null) { + mAudioManager = (AudioManager) getContext().getSystemService( + Context.AUDIO_SERVICE); + } + } + // Volume buttons should only function for music. + if (mAudioManager.isMusicActive()) { + mAudioManager.adjustStreamVolume( + AudioManager.STREAM_MUSIC, + keyCode == KeyEvent.KEYCODE_VOLUME_UP + ? AudioManager.ADJUST_RAISE + : AudioManager.ADJUST_LOWER, + 0); + } + // Don't execute default volume behavior + return true; + } + } + } else if (event.getAction() == KeyEvent.ACTION_UP) { + switch (keyCode) { + case KeyEvent.KEYCODE_MUTE: + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { + Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); + intent.putExtra(Intent.EXTRA_KEY_EVENT, event); + getContext().sendOrderedBroadcast(intent, null); + return true; + } + } + } + return false; + } + +} diff --git a/policy/com/android/internal/policy/impl/KeyguardViewCallback.java b/policy/com/android/internal/policy/impl/KeyguardViewCallback.java new file mode 100644 index 0000000000000000000000000000000000000000..b376d657cc809544dda9305fd00ad492fe5e5b9e --- /dev/null +++ b/policy/com/android/internal/policy/impl/KeyguardViewCallback.java @@ -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. + */ + +package com.android.internal.policy.impl; + +/** + * The callback used by the keyguard view to tell the {@link KeyguardViewMediator} + * various things. + */ +public interface KeyguardViewCallback { + + /** + * Request the wakelock to be poked for the default amount of time. + */ + void pokeWakelock(); + + /** + * Request the wakelock to be poked for a specific amount of time. + * @param millis The amount of time in millis. + */ + void pokeWakelock(int millis); + + /** + * Report that the keyguard is done. + * @param authenticated Whether the user securely got past the keyguard. + * the only reason for this to be false is if the keyguard was instructed + * to appear temporarily to verify the user is supposed to get past the + * keyguard, and the user fails to do so. + */ + void keyguardDone(boolean authenticated); + + /** + * Report that the keyguard is done drawing. + */ + void keyguardDoneDrawing(); +} diff --git a/policy/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/com/android/internal/policy/impl/KeyguardViewManager.java new file mode 100644 index 0000000000000000000000000000000000000000..ba1d7f530294647c5eef22144b9172837608dc91 --- /dev/null +++ b/policy/com/android/internal/policy/impl/KeyguardViewManager.java @@ -0,0 +1,241 @@ +/* + * 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. + */ + +package com.android.internal.policy.impl; + +import com.android.internal.R; + +import android.content.Context; +import android.content.pm.ActivityInfo; +import android.graphics.PixelFormat; +import android.graphics.Canvas; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewManager; +import android.view.WindowManager; +import android.widget.FrameLayout; + +/** + * Manages creating, showing, hiding and resetting the keyguard. Calls back + * via {@link com.android.internal.policy.impl.KeyguardViewCallback} to poke + * the wake lock and report that the keyguard is done, which is in turn, + * reported to this class by the current {@link KeyguardViewBase}. + */ +public class KeyguardViewManager implements KeyguardWindowController { + private final static boolean DEBUG = false; + private static String TAG = "KeyguardViewManager"; + + private final Context mContext; + private final ViewManager mViewManager; + private final KeyguardViewCallback mCallback; + private final KeyguardViewProperties mKeyguardViewProperties; + + private final KeyguardUpdateMonitor mUpdateMonitor; + + private WindowManager.LayoutParams mWindowLayoutParams; + private boolean mNeedsInput = false; + + private FrameLayout mKeyguardHost; + private KeyguardViewBase mKeyguardView; + + private boolean mScreenOn = false; + + /** + * @param context Used to create views. + * @param viewManager Keyguard will be attached to this. + * @param callback Used to notify of changes. + */ + public KeyguardViewManager(Context context, ViewManager viewManager, + KeyguardViewCallback callback, KeyguardViewProperties keyguardViewProperties, KeyguardUpdateMonitor updateMonitor) { + mContext = context; + mViewManager = viewManager; + mCallback = callback; + mKeyguardViewProperties = keyguardViewProperties; + + mUpdateMonitor = updateMonitor; + } + + /** + * Helper class to host the keyguard view. + */ + private static class KeyguardViewHost extends FrameLayout { + private final KeyguardViewCallback mCallback; + + private KeyguardViewHost(Context context, KeyguardViewCallback callback) { + super(context); + mCallback = callback; + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + mCallback.keyguardDoneDrawing(); + } + } + + /** + * Show the keyguard. Will handle creating and attaching to the view manager + * lazily. + */ + public synchronized void show() { + if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView); + + if (mKeyguardHost == null) { + if (DEBUG) Log.d(TAG, "keyguard host is null, creating it..."); + + mKeyguardHost = new KeyguardViewHost(mContext, mCallback); + + final int stretch = ViewGroup.LayoutParams.MATCH_PARENT; + int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN + | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER + | WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING + /*| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR*/ ; + if (!mNeedsInput) { + flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } + WindowManager.LayoutParams lp = new WindowManager.LayoutParams( + stretch, stretch, WindowManager.LayoutParams.TYPE_KEYGUARD, + flags, PixelFormat.TRANSLUCENT); + lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN; + lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen; + lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; + lp.setTitle("Keyguard"); + mWindowLayoutParams = lp; + + mViewManager.addView(mKeyguardHost, lp); + } + + if (mKeyguardView == null) { + if (DEBUG) Log.d(TAG, "keyguard view is null, creating it..."); + mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this); + mKeyguardView.setId(R.id.lock_screen); + mKeyguardView.setCallback(mCallback); + + final ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT); + + mKeyguardHost.addView(mKeyguardView, lp); + + if (mScreenOn) { + mKeyguardView.onScreenTurnedOn(); + } + } + + mKeyguardHost.setVisibility(View.VISIBLE); + mKeyguardView.requestFocus(); + } + + public void setNeedsInput(boolean needsInput) { + mNeedsInput = needsInput; + if (mWindowLayoutParams != null) { + if (needsInput) { + mWindowLayoutParams.flags &= + ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } else { + mWindowLayoutParams.flags |= + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } + mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams); + } + } + + /** + * Reset the state of the view. + */ + public synchronized void reset() { + if (DEBUG) Log.d(TAG, "reset()"); + if (mKeyguardView != null) { + mKeyguardView.reset(); + } + } + + public synchronized void onScreenTurnedOff() { + if (DEBUG) Log.d(TAG, "onScreenTurnedOff()"); + mScreenOn = false; + if (mKeyguardView != null) { + mKeyguardView.onScreenTurnedOff(); + } + } + + public synchronized void onScreenTurnedOn() { + if (DEBUG) Log.d(TAG, "onScreenTurnedOn()"); + mScreenOn = true; + if (mKeyguardView != null) { + mKeyguardView.onScreenTurnedOn(); + } + } + + public synchronized void verifyUnlock() { + if (DEBUG) Log.d(TAG, "verifyUnlock()"); + show(); + mKeyguardView.verifyUnlock(); + } + + /** + * A key has woken the device. We use this to potentially adjust the state + * of the lock screen based on the key. + * + * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}. + * Be sure not to take any action that takes a long time; any significant + * action should be posted to a handler. + * + * @param keyCode The wake key. + */ + public boolean wakeWhenReadyTq(int keyCode) { + if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")"); + if (mKeyguardView != null) { + mKeyguardView.wakeWhenReadyTq(keyCode); + return true; + } else { + Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq"); + return false; + } + } + + /** + * Hides the keyguard view + */ + public synchronized void hide() { + if (DEBUG) Log.d(TAG, "hide()"); + if (mKeyguardHost != null) { + mKeyguardHost.setVisibility(View.GONE); + // Don't do this right away, so we can let the view continue to animate + // as it goes away. + if (mKeyguardView != null) { + final KeyguardViewBase lastView = mKeyguardView; + mKeyguardView = null; + mKeyguardHost.postDelayed(new Runnable() { + public void run() { + synchronized (KeyguardViewManager.this) { + mKeyguardHost.removeView(lastView); + lastView.cleanUp(); + } + } + }, 500); + } + } + } + + /** + * @return Whether the keyguard is showing + */ + public synchronized boolean isShowing() { + return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE); + } +} diff --git a/policy/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/com/android/internal/policy/impl/KeyguardViewMediator.java new file mode 100644 index 0000000000000000000000000000000000000000..c255041df36ab3b7132f02d5a5269d97b8ce3cc5 --- /dev/null +++ b/policy/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -0,0 +1,1135 @@ +/* + * 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. + */ + +package com.android.internal.policy.impl; + +import com.android.internal.telephony.IccCard; +import com.android.internal.widget.LockPatternUtils; + +import android.app.ActivityManagerNative; +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.app.StatusBarManager; +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.media.AudioManager; +import android.media.Ringtone; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Handler; +import android.os.IBinder; +import android.os.LocalPowerManager; +import android.os.Message; +import android.os.PowerManager; +import android.os.RemoteException; +import android.os.SystemClock; +import android.os.SystemProperties; +import android.provider.Settings; +import android.telephony.TelephonyManager; +import android.util.Config; +import android.util.EventLog; +import android.util.Log; +import android.view.KeyEvent; +import android.view.WindowManagerImpl; +import android.view.WindowManagerPolicy; + + +/** + * Mediates requests related to the keyguard. This includes queries about the + * state of the keyguard, power management events that effect whether the keyguard + * should be shown or reset, callbacks to the phone window manager to notify + * it of when the keyguard is showing, and events from the keyguard view itself + * stating that the keyguard was succesfully unlocked. + * + * Note that the keyguard view is shown when the screen is off (as appropriate) + * so that once the screen comes on, it will be ready immediately. + * + * Example queries about the keyguard: + * - is {movement, key} one that should wake the keygaurd? + * - is the keyguard showing? + * - are input events restricted due to the state of the keyguard? + * + * Callbacks to the phone window manager: + * - the keyguard is showing + * + * Example external events that translate to keyguard view changes: + * - screen turned off -> reset the keyguard, and show it so it will be ready + * next time the screen turns on + * - keyboard is slid open -> if the keyguard is not secure, hide it + * + * Events from the keyguard view: + * - user succesfully unlocked keyguard -> hide keyguard view, and no longer + * restrict input events. + * + * Note: in addition to normal power managment events that effect the state of + * whether the keyguard should be showing, external apps and services may request + * that the keyguard be disabled via {@link #setKeyguardEnabled(boolean)}. When + * false, this will override all other conditions for turning on the keyguard. + * + * Threading and synchronization: + * This class is created by the initialization routine of the {@link WindowManagerPolicy}, + * and runs on its thread. The keyguard UI is created from that thread in the + * constructor of this class. The apis may be called from other threads, including the + * {@link com.android.server.KeyInputQueue}'s and {@link android.view.WindowManager}'s. + * Therefore, methods on this class are synchronized, and any action that is pointed + * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI + * thread of the keyguard. + */ +public class KeyguardViewMediator implements KeyguardViewCallback, + KeyguardUpdateMonitor.SimStateCallback { + private final static boolean DEBUG = false && Config.LOGD; + private final static boolean DBG_WAKE = DEBUG || true; + + private final static String TAG = "KeyguardViewMediator"; + + private static final String DELAYED_KEYGUARD_ACTION = + "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD"; + + // used for handler messages + private static final int TIMEOUT = 1; + private static final int SHOW = 2; + private static final int HIDE = 3; + private static final int RESET = 4; + private static final int VERIFY_UNLOCK = 5; + private static final int NOTIFY_SCREEN_OFF = 6; + private static final int NOTIFY_SCREEN_ON = 7; + private static final int WAKE_WHEN_READY = 8; + private static final int KEYGUARD_DONE = 9; + private static final int KEYGUARD_DONE_DRAWING = 10; + private static final int KEYGUARD_DONE_AUTHENTICATING = 11; + private static final int SET_HIDDEN = 12; + private static final int KEYGUARD_TIMEOUT = 13; + + /** + * The default amount of time we stay awake (used for all key input) + */ + protected static final int AWAKE_INTERVAL_DEFAULT_MS = 5000; + + + /** + * The default amount of time we stay awake (used for all key input) when + * the keyboard is open + */ + protected static final int AWAKE_INTERVAL_DEFAULT_KEYBOARD_OPEN_MS = 10000; + + /** + * How long to wait after the screen turns off due to timeout before + * turning on the keyguard (i.e, the user has this much time to turn + * the screen back on without having to face the keyguard). + */ + private static final int KEYGUARD_DELAY_MS = 5000; + + /** + * How long we'll wait for the {@link KeyguardViewCallback#keyguardDoneDrawing()} + * callback before unblocking a call to {@link #setKeyguardEnabled(boolean)} + * that is reenabling the keyguard. + */ + private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000; + + private Context mContext; + private AlarmManager mAlarmManager; + private StatusBarManager mStatusBarManager; + private boolean mShowLockIcon = false; + private IBinder mSecureLockIcon = null; + + private boolean mSystemReady; + + // Whether the next call to playSounds() should be skipped. Defaults to + // true because the first lock (on boot) should be silent. + private boolean mSuppressNextLockSound = true; + + + /** Low level access to the power manager for enableUserActivity. Having this + * requires that we run in the system process. */ + LocalPowerManager mRealPowerManager; + + /** High level access to the power manager for WakeLocks */ + private PowerManager mPM; + + /** + * Used to keep the device awake while the keyguard is showing, i.e for + * calls to {@link #pokeWakelock()} + */ + private PowerManager.WakeLock mWakeLock; + + /** + * Used to keep the device awake while to ensure the keyguard finishes opening before + * we sleep. + */ + private PowerManager.WakeLock mShowKeyguardWakeLock; + + /** + * Does not turn on screen, held while a call to {@link KeyguardViewManager#wakeWhenReadyTq(int)} + * is called to make sure the device doesn't sleep before it has a chance to poke + * the wake lock. + * @see #wakeWhenReadyLocked(int) + */ + private PowerManager.WakeLock mWakeAndHandOff; + + private KeyguardViewManager mKeyguardViewManager; + + // these are protected by synchronized (this) + + /** + * External apps (like the phone app) can tell us to disable the keygaurd. + */ + private boolean mExternallyEnabled = true; + + /** + * Remember if an external call to {@link #setKeyguardEnabled} with value + * false caused us to hide the keyguard, so that we need to reshow it once + * the keygaurd is reenabled with another call with value true. + */ + private boolean mNeedToReshowWhenReenabled = false; + + // cached value of whether we are showing (need to know this to quickly + // answer whether the input should be restricted) + private boolean mShowing = false; + + // true if the keyguard is hidden by another window + private boolean mHidden = false; + + /** + * Helps remember whether the screen has turned on since the last time + * it turned off due to timeout. see {@link #onScreenTurnedOff(int)} + */ + private int mDelayedShowingSequence; + + private int mWakelockSequence; + + private PhoneWindowManager mCallback; + + /** + * If the user has disabled the keyguard, then requests to exit, this is + * how we'll ultimately let them know whether it was successful. We use this + * var being non-null as an indicator that there is an in progress request. + */ + private WindowManagerPolicy.OnKeyguardExitResult mExitSecureCallback; + + // the properties of the keyguard + private KeyguardViewProperties mKeyguardViewProperties; + + private KeyguardUpdateMonitor mUpdateMonitor; + + private boolean mKeyboardOpen = false; + + private boolean mScreenOn = false; + + // last known state of the cellular connection + private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE; + + /** + * we send this intent when the keyguard is dismissed. + */ + private Intent mUserPresentIntent; + + /** + * {@link #setKeyguardEnabled} waits on this condition when it reenables + * the keyguard. + */ + private boolean mWaitingUntilKeyguardVisible = false; + + public KeyguardViewMediator(Context context, PhoneWindowManager callback, + LocalPowerManager powerManager) { + mContext = context; + + mRealPowerManager = powerManager; + mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + mWakeLock = mPM.newWakeLock( + PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, + "keyguard"); + mWakeLock.setReferenceCounted(false); + mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard"); + mShowKeyguardWakeLock.setReferenceCounted(false); + + mWakeAndHandOff = mPM.newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, + "keyguardWakeAndHandOff"); + mWakeAndHandOff.setReferenceCounted(false); + + IntentFilter filter = new IntentFilter(); + filter.addAction(DELAYED_KEYGUARD_ACTION); + filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); + context.registerReceiver(mBroadCastReceiver, filter); + mAlarmManager = (AlarmManager) context + .getSystemService(Context.ALARM_SERVICE); + mCallback = callback; + + mUpdateMonitor = new KeyguardUpdateMonitor(context); + + mUpdateMonitor.registerSimStateCallback(this); + + mKeyguardViewProperties = new LockPatternKeyguardViewProperties( + new LockPatternUtils(mContext), mUpdateMonitor); + + mKeyguardViewManager = new KeyguardViewManager( + context, WindowManagerImpl.getDefault(), this, + mKeyguardViewProperties, mUpdateMonitor); + + mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT); + mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + + final ContentResolver cr = mContext.getContentResolver(); + mShowLockIcon = (Settings.System.getInt(cr, "show_status_bar_lock", 0) == 1); + } + + /** + * Let us know that the system is ready after startup. + */ + public void onSystemReady() { + synchronized (this) { + if (DEBUG) Log.d(TAG, "onSystemReady"); + mSystemReady = true; + doKeyguard(); + } + } + + /** + * Called to let us know the screen was turned off. + * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER}, + * {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or + * {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}. + */ + public void onScreenTurnedOff(int why) { + synchronized (this) { + mScreenOn = false; + if (DEBUG) Log.d(TAG, "onScreenTurnedOff(" + why + ")"); + + if (mExitSecureCallback != null) { + if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled"); + mExitSecureCallback.onKeyguardExitResult(false); + mExitSecureCallback = null; + if (!mExternallyEnabled) { + hideLocked(); + } + } else if (mShowing) { + notifyScreenOffLocked(); + resetStateLocked(); + } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT) { + // if the screen turned off because of timeout, set an alarm + // to enable it a little bit later (i.e, give the user a chance + // to turn the screen back on within a certain window without + // having to unlock the screen) + long when = SystemClock.elapsedRealtime() + KEYGUARD_DELAY_MS; + Intent intent = new Intent(DELAYED_KEYGUARD_ACTION); + intent.putExtra("seq", mDelayedShowingSequence); + PendingIntent sender = PendingIntent.getBroadcast(mContext, + 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, + sender); + if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = " + + mDelayedShowingSequence); + } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) { + // Do not enable the keyguard if the prox sensor forced the screen off. + } else { + doKeyguard(); + } + } + } + + /** + * Let's us know the screen was turned on. + */ + public void onScreenTurnedOn() { + synchronized (this) { + mScreenOn = true; + mDelayedShowingSequence++; + if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence); + notifyScreenOnLocked(); + } + } + + /** + * Same semantics as {@link WindowManagerPolicy#enableKeyguard}; provide + * a way for external stuff to override normal keyguard behavior. For instance + * the phone app disables the keyguard when it receives incoming calls. + */ + public void setKeyguardEnabled(boolean enabled) { + synchronized (this) { + if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")"); + + + mExternallyEnabled = enabled; + + if (!enabled && mShowing) { + if (mExitSecureCallback != null) { + if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring"); + // we're in the process of handling a request to verify the user + // can get past the keyguard. ignore extraneous requests to disable / reenable + return; + } + + // hiding keyguard that is showing, remember to reshow later + if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, " + + "disabling status bar expansion"); + mNeedToReshowWhenReenabled = true; + hideLocked(); + } else if (enabled && mNeedToReshowWhenReenabled) { + // reenabled after previously hidden, reshow + if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling " + + "status bar expansion"); + mNeedToReshowWhenReenabled = false; + + if (mExitSecureCallback != null) { + if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting"); + mExitSecureCallback.onKeyguardExitResult(false); + mExitSecureCallback = null; + resetStateLocked(); + } else { + showLocked(); + + // block until we know the keygaurd is done drawing (and post a message + // to unblock us after a timeout so we don't risk blocking too long + // and causing an ANR). + mWaitingUntilKeyguardVisible = true; + mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS); + if (DEBUG) Log.d(TAG, "waiting until mWaitingUntilKeyguardVisible is false"); + while (mWaitingUntilKeyguardVisible) { + try { + wait(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + if (DEBUG) Log.d(TAG, "done waiting for mWaitingUntilKeyguardVisible"); + } + } + } + } + + /** + * @see android.app.KeyguardManager#exitKeyguardSecurely + */ + public void verifyUnlock(WindowManagerPolicy.OnKeyguardExitResult callback) { + synchronized (this) { + if (DEBUG) Log.d(TAG, "verifyUnlock"); + if (!mUpdateMonitor.isDeviceProvisioned()) { + // don't allow this api when the device isn't provisioned + if (DEBUG) Log.d(TAG, "ignoring because device isn't provisioned"); + callback.onKeyguardExitResult(false); + } else if (mExternallyEnabled) { + // this only applies when the user has externally disabled the + // keyguard. this is unexpected and means the user is not + // using the api properly. + Log.w(TAG, "verifyUnlock called when not externally disabled"); + callback.onKeyguardExitResult(false); + } else if (mExitSecureCallback != null) { + // already in progress with someone else + callback.onKeyguardExitResult(false); + } else { + mExitSecureCallback = callback; + verifyUnlockLocked(); + } + } + } + + /** + * Is the keyguard currently showing? + */ + public boolean isShowing() { + return mShowing; + } + + /** + * Is the keyguard currently showing and not being force hidden? + */ + public boolean isShowingAndNotHidden() { + return mShowing && !mHidden; + } + + /** + * Notify us when the keyguard is hidden by another window + */ + public void setHidden(boolean isHidden) { + if (DEBUG) Log.d(TAG, "setHidden " + isHidden); + mHandler.removeMessages(SET_HIDDEN); + Message msg = mHandler.obtainMessage(SET_HIDDEN, (isHidden ? 1 : 0), 0); + mHandler.sendMessage(msg); + } + + /** + * Handles SET_HIDDEN message sent by setHidden() + */ + private void handleSetHidden(boolean isHidden) { + synchronized (KeyguardViewMediator.this) { + if (mHidden != isHidden) { + mHidden = isHidden; + adjustUserActivityLocked(); + adjustStatusBarLocked(); + } + } + } + + /** + * Used by PhoneWindowManager to enable the keyguard due to a user activity timeout. + * This must be safe to call from any thread and with any window manager locks held. + */ + public void doKeyguardTimeout() { + mHandler.removeMessages(KEYGUARD_TIMEOUT); + Message msg = mHandler.obtainMessage(KEYGUARD_TIMEOUT); + mHandler.sendMessage(msg); + } + + /** + * Given the state of the keyguard, is the input restricted? + * Input is restricted when the keyguard is showing, or when the keyguard + * was suppressed by an app that disabled the keyguard or we haven't been provisioned yet. + */ + public boolean isInputRestricted() { + return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned(); + } + + /** + * Returns true if the change is resulting in the keyguard beign dismissed, + * meaning the screen can turn on immediately. Otherwise returns false. + */ + public boolean doLidChangeTq(boolean isLidOpen) { + mKeyboardOpen = isLidOpen; + + if (mUpdateMonitor.isKeyguardBypassEnabled() && mKeyboardOpen + && !mKeyguardViewProperties.isSecure() && mKeyguardViewManager.isShowing()) { + if (DEBUG) Log.d(TAG, "bypassing keyguard on sliding open of keyboard with non-secure keyguard"); + mHandler.sendEmptyMessage(KEYGUARD_DONE_AUTHENTICATING); + return true; + } + return false; + } + + /** + * Enable the keyguard if the settings are appropriate. + */ + private void doKeyguard() { + synchronized (this) { + // if another app is disabling us, don't show + if (!mExternallyEnabled) { + if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); + + // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes + // for an occasional ugly flicker in this situation: + // 1) receive a call with the screen on (no keyguard) or make a call + // 2) screen times out + // 3) user hits key to turn screen back on + // instead, we reenable the keyguard when we know the screen is off and the call + // ends (see the broadcast receiver below) + // TODO: clean this up when we have better support at the window manager level + // for apps that wish to be on top of the keyguard + return; + } + + // if the keyguard is already showing, don't bother + if (mKeyguardViewManager.isShowing()) { + if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing"); + return; + } + + // if the setup wizard hasn't run yet, don't show + final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", + false); + final boolean provisioned = mUpdateMonitor.isDeviceProvisioned(); + final IccCard.State state = mUpdateMonitor.getSimState(); + final boolean lockedOrMissing = state.isPinLocked() + || ((state == IccCard.State.ABSENT) && requireSim); + + if (!lockedOrMissing && !provisioned) { + if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned" + + " and the sim is not locked or missing"); + return; + } + + if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen"); + showLocked(); + } + } + + /** + * Send message to keyguard telling it to reset its state. + * @see #handleReset() + */ + private void resetStateLocked() { + if (DEBUG) Log.d(TAG, "resetStateLocked"); + Message msg = mHandler.obtainMessage(RESET); + mHandler.sendMessage(msg); + } + + /** + * Send message to keyguard telling it to verify unlock + * @see #handleVerifyUnlock() + */ + private void verifyUnlockLocked() { + if (DEBUG) Log.d(TAG, "verifyUnlockLocked"); + mHandler.sendEmptyMessage(VERIFY_UNLOCK); + } + + + /** + * Send a message to keyguard telling it the screen just turned on. + * @see #onScreenTurnedOff(int) + * @see #handleNotifyScreenOff + */ + private void notifyScreenOffLocked() { + if (DEBUG) Log.d(TAG, "notifyScreenOffLocked"); + mHandler.sendEmptyMessage(NOTIFY_SCREEN_OFF); + } + + /** + * Send a message to keyguard telling it the screen just turned on. + * @see #onScreenTurnedOn() + * @see #handleNotifyScreenOn + */ + private void notifyScreenOnLocked() { + if (DEBUG) Log.d(TAG, "notifyScreenOnLocked"); + mHandler.sendEmptyMessage(NOTIFY_SCREEN_ON); + } + + /** + * Send message to keyguard telling it about a wake key so it can adjust + * its state accordingly and then poke the wake lock when it is ready. + * @param keyCode The wake key. + * @see #handleWakeWhenReady + * @see #onWakeKeyWhenKeyguardShowingTq(int) + */ + private void wakeWhenReadyLocked(int keyCode) { + if (DBG_WAKE) Log.d(TAG, "wakeWhenReadyLocked(" + keyCode + ")"); + + /** + * acquire the handoff lock that will keep the cpu running. this will + * be released once the keyguard has set itself up and poked the other wakelock + * in {@link #handleWakeWhenReady(int)} + */ + mWakeAndHandOff.acquire(); + + Message msg = mHandler.obtainMessage(WAKE_WHEN_READY, keyCode, 0); + mHandler.sendMessage(msg); + } + + /** + * Send message to keyguard telling it to show itself + * @see #handleShow() + */ + private void showLocked() { + if (DEBUG) Log.d(TAG, "showLocked"); + // ensure we stay awake until we are finished displaying the keyguard + mShowKeyguardWakeLock.acquire(); + Message msg = mHandler.obtainMessage(SHOW); + mHandler.sendMessage(msg); + } + + /** + * Send message to keyguard telling it to hide itself + * @see #handleHide() + */ + private void hideLocked() { + if (DEBUG) Log.d(TAG, "hideLocked"); + Message msg = mHandler.obtainMessage(HIDE); + mHandler.sendMessage(msg); + } + + /** {@inheritDoc} */ + public void onSimStateChanged(IccCard.State simState) { + if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState); + + switch (simState) { + case ABSENT: + // only force lock screen in case of missing sim if user hasn't + // gone through setup wizard + if (!mUpdateMonitor.isDeviceProvisioned()) { + if (!isShowing()) { + if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_ABSENT and keygaurd isn't showing, we need " + + "to show the keyguard since the device isn't provisioned yet."); + doKeyguard(); + } else { + resetStateLocked(); + } + } + break; + case PIN_REQUIRED: + case PUK_REQUIRED: + if (!isShowing()) { + if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't showing, we need " + + "to show the keyguard so the user can enter their sim pin"); + doKeyguard(); + } else { + resetStateLocked(); + } + + break; + case READY: + if (isShowing()) { + resetStateLocked(); + } + break; + } + } + + public boolean isSecure() { + return mKeyguardViewProperties.isSecure(); + } + + private BroadcastReceiver mBroadCastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (action.equals(DELAYED_KEYGUARD_ACTION)) { + + int sequence = intent.getIntExtra("seq", 0); + + if (false) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = " + + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence); + + if (mDelayedShowingSequence == sequence) { + // Don't play lockscreen SFX if the screen went off due to + // timeout. + mSuppressNextLockSound = true; + + doKeyguard(); + } + } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) { + mPhoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE); + + if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState) // call ending + && !mScreenOn // screen off + && mExternallyEnabled) { // not disabled by any app + + // note: this is a way to gracefully reenable the keyguard when the call + // ends and the screen is off without always reenabling the keyguard + // each time the screen turns off while in call (and having an occasional ugly + // flicker while turning back on the screen and disabling the keyguard again). + if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the " + + "keyguard is showing"); + doKeyguard(); + } + } + } + }; + + + /** + * When a key is received when the screen is off and the keyguard is showing, + * we need to decide whether to actually turn on the screen, and if so, tell + * the keyguard to prepare itself and poke the wake lock when it is ready. + * + * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}. + * Be sure not to take any action that takes a long time; any significant + * action should be posted to a handler. + * + * @param keyCode The keycode of the key that woke the device + * @return Whether we poked the wake lock (and turned the screen on) + */ + public boolean onWakeKeyWhenKeyguardShowingTq(int keyCode) { + if (DEBUG) Log.d(TAG, "onWakeKeyWhenKeyguardShowing(" + keyCode + ")"); + + if (isWakeKeyWhenKeyguardShowing(keyCode)) { + // give the keyguard view manager a chance to adjust the state of the + // keyguard based on the key that woke the device before poking + // the wake lock + wakeWhenReadyLocked(keyCode); + return true; + } else { + return false; + } + } + + private boolean isWakeKeyWhenKeyguardShowing(int keyCode) { + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_MUTE: + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: + case KeyEvent.KEYCODE_CAMERA: + return false; + } + return true; + } + + /** + * Callbacks from {@link KeyguardViewManager}. + */ + + /** {@inheritDoc} */ + public void pokeWakelock() { + pokeWakelock(mKeyboardOpen ? + AWAKE_INTERVAL_DEFAULT_KEYBOARD_OPEN_MS : AWAKE_INTERVAL_DEFAULT_MS); + } + + /** {@inheritDoc} */ + public void pokeWakelock(int holdMs) { + synchronized (this) { + if (DBG_WAKE) Log.d(TAG, "pokeWakelock(" + holdMs + ")"); + mWakeLock.acquire(); + mHandler.removeMessages(TIMEOUT); + mWakelockSequence++; + Message msg = mHandler.obtainMessage(TIMEOUT, mWakelockSequence, 0); + mHandler.sendMessageDelayed(msg, holdMs); + } + } + + /** + * {@inheritDoc} + * + * @see #handleKeyguardDone + */ + public void keyguardDone(boolean authenticated) { + keyguardDone(authenticated, true); + } + + public void keyguardDone(boolean authenticated, boolean wakeup) { + synchronized (this) { + EventLog.writeEvent(70000, 2); + if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated + ")"); + Message msg = mHandler.obtainMessage(KEYGUARD_DONE); + msg.arg1 = wakeup ? 1 : 0; + mHandler.sendMessage(msg); + + if (authenticated) { + mUpdateMonitor.clearFailedAttempts(); + } + + if (mExitSecureCallback != null) { + mExitSecureCallback.onKeyguardExitResult(authenticated); + mExitSecureCallback = null; + + if (authenticated) { + // after succesfully exiting securely, no need to reshow + // the keyguard when they've released the lock + mExternallyEnabled = true; + mNeedToReshowWhenReenabled = false; + } + } + } + } + + /** + * {@inheritDoc} + * + * @see #handleKeyguardDoneDrawing + */ + public void keyguardDoneDrawing() { + mHandler.sendEmptyMessage(KEYGUARD_DONE_DRAWING); + } + + /** + * This handler will be associated with the policy thread, which will also + * be the UI thread of the keyguard. Since the apis of the policy, and therefore + * this class, can be called by other threads, any action that directly + * interacts with the keyguard ui should be posted to this handler, rather + * than called directly. + */ + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case TIMEOUT: + handleTimeout(msg.arg1); + return ; + case SHOW: + handleShow(); + return ; + case HIDE: + handleHide(); + return ; + case RESET: + handleReset(); + return ; + case VERIFY_UNLOCK: + handleVerifyUnlock(); + return; + case NOTIFY_SCREEN_OFF: + handleNotifyScreenOff(); + return; + case NOTIFY_SCREEN_ON: + handleNotifyScreenOn(); + return; + case WAKE_WHEN_READY: + handleWakeWhenReady(msg.arg1); + return; + case KEYGUARD_DONE: + handleKeyguardDone(msg.arg1 != 0); + return; + case KEYGUARD_DONE_DRAWING: + handleKeyguardDoneDrawing(); + return; + case KEYGUARD_DONE_AUTHENTICATING: + keyguardDone(true); + return; + case SET_HIDDEN: + handleSetHidden(msg.arg1 != 0); + break; + case KEYGUARD_TIMEOUT: + doKeyguard(); + break; + } + } + }; + + /** + * @see #keyguardDone + * @see #KEYGUARD_DONE + */ + private void handleKeyguardDone(boolean wakeup) { + if (DEBUG) Log.d(TAG, "handleKeyguardDone"); + handleHide(); + if (wakeup) { + mPM.userActivity(SystemClock.uptimeMillis(), true); + } + mWakeLock.release(); + mContext.sendBroadcast(mUserPresentIntent); + } + + /** + * @see #keyguardDoneDrawing + * @see #KEYGUARD_DONE_DRAWING + */ + private void handleKeyguardDoneDrawing() { + synchronized(this) { + if (false) Log.d(TAG, "handleKeyguardDoneDrawing"); + if (mWaitingUntilKeyguardVisible) { + if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing: notifying mWaitingUntilKeyguardVisible"); + mWaitingUntilKeyguardVisible = false; + notifyAll(); + + // there will usually be two of these sent, one as a timeout, and one + // as a result of the callback, so remove any remaining messages from + // the queue + mHandler.removeMessages(KEYGUARD_DONE_DRAWING); + } + } + } + + /** + * Handles the message sent by {@link #pokeWakelock} + * @param seq used to determine if anything has changed since the message + * was sent. + * @see #TIMEOUT + */ + private void handleTimeout(int seq) { + synchronized (KeyguardViewMediator.this) { + if (DEBUG) Log.d(TAG, "handleTimeout"); + if (seq == mWakelockSequence) { + mWakeLock.release(); + } + } + } + + private void playSounds(boolean locked) { + // User feedback for keyguard. + + if (mSuppressNextLockSound) { + mSuppressNextLockSound = false; + return; + } + + final ContentResolver cr = mContext.getContentResolver(); + if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) + { + final String whichSound = locked + ? Settings.System.LOCK_SOUND + : Settings.System.UNLOCK_SOUND; + final String soundPath = Settings.System.getString(cr, whichSound); + if (soundPath != null) { + final Uri soundUri = Uri.parse("file://" + soundPath); + if (soundUri != null) { + final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); + if (sfx != null) { + sfx.setStreamType(AudioManager.STREAM_SYSTEM); + sfx.play(); + } else { + Log.d(TAG, "playSounds: failed to load ringtone from uri: " + soundUri); + } + } else { + Log.d(TAG, "playSounds: could not parse Uri: " + soundPath); + } + } else { + Log.d(TAG, "playSounds: whichSound = " + whichSound + "; soundPath was null"); + } + } + } + + /** + * Handle message sent by {@link #showLocked}. + * @see #SHOW + */ + private void handleShow() { + synchronized (KeyguardViewMediator.this) { + if (DEBUG) Log.d(TAG, "handleShow"); + if (!mSystemReady) return; + + playSounds(true); + + mKeyguardViewManager.show(); + mShowing = true; + adjustUserActivityLocked(); + adjustStatusBarLocked(); + try { + ActivityManagerNative.getDefault().closeSystemDialogs("lock"); + } catch (RemoteException e) { + } + mShowKeyguardWakeLock.release(); + } + } + + /** + * Handle message sent by {@link #hideLocked()} + * @see #HIDE + */ + private void handleHide() { + synchronized (KeyguardViewMediator.this) { + if (DEBUG) Log.d(TAG, "handleHide"); + if (mWakeAndHandOff.isHeld()) { + Log.w(TAG, "attempt to hide the keyguard while waking, ignored"); + return; + } + + // only play "unlock" noises if not on a call (since the incall UI + // disables the keyguard) + if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) { + playSounds(false); + } + + mKeyguardViewManager.hide(); + mShowing = false; + adjustUserActivityLocked(); + adjustStatusBarLocked(); + } + } + + private void adjustUserActivityLocked() { + // disable user activity if we are shown and not hidden + if (DEBUG) Log.d(TAG, "adjustUserActivityLocked mShowing: " + mShowing + " mHidden: " + mHidden); + boolean enabled = !mShowing || mHidden; + mRealPowerManager.enableUserActivity(enabled); + if (!enabled && mScreenOn) { + // reinstate our short screen timeout policy + pokeWakelock(); + } + } + + private void adjustStatusBarLocked() { + if (mStatusBarManager == null) { + mStatusBarManager = (StatusBarManager) + mContext.getSystemService(Context.STATUS_BAR_SERVICE); + } + if (mStatusBarManager == null) { + Log.w(TAG, "Could not get status bar manager"); + } else { + if (mShowLockIcon) { + // Give feedback to user when secure keyguard is active and engaged + if (mShowing && isSecure()) { + if (mSecureLockIcon == null) { + mSecureLockIcon = mStatusBarManager.addIcon("secure", + com.android.internal.R.drawable.stat_sys_secure, 0); + } + } else { + if (mSecureLockIcon != null) { + mStatusBarManager.removeIcon(mSecureLockIcon); + mSecureLockIcon = null; + } + } + } + + // if the keyguard is shown, allow the status bar to open + // only if the keyguard is insecure and is covered by another window + boolean enable = !mShowing || (mHidden && !isSecure()); + mStatusBarManager.disable(enable ? + StatusBarManager.DISABLE_NONE : + StatusBarManager.DISABLE_EXPAND); + } + } + + /** + * Handle message sent by {@link #wakeWhenReadyLocked(int)} + * @param keyCode The key that woke the device. + * @see #WAKE_WHEN_READY + */ + private void handleWakeWhenReady(int keyCode) { + synchronized (KeyguardViewMediator.this) { + if (DBG_WAKE) Log.d(TAG, "handleWakeWhenReady(" + keyCode + ")"); + + // this should result in a call to 'poke wakelock' which will set a timeout + // on releasing the wakelock + if (!mKeyguardViewManager.wakeWhenReadyTq(keyCode)) { + // poke wakelock ourselves if keyguard is no longer active + Log.w(TAG, "mKeyguardViewManager.wakeWhenReadyTq did not poke wake lock, so poke it ourselves"); + pokeWakelock(); + } + + /** + * Now that the keyguard is ready and has poked the wake lock, we can + * release the handoff wakelock + */ + mWakeAndHandOff.release(); + + if (!mWakeLock.isHeld()) { + Log.w(TAG, "mWakeLock not held in mKeyguardViewManager.wakeWhenReadyTq"); + } + } + } + + /** + * Handle message sent by {@link #resetStateLocked()} + * @see #RESET + */ + private void handleReset() { + synchronized (KeyguardViewMediator.this) { + if (DEBUG) Log.d(TAG, "handleReset"); + mKeyguardViewManager.reset(); + } + } + + /** + * Handle message sent by {@link #verifyUnlock} + * @see #RESET + */ + private void handleVerifyUnlock() { + synchronized (KeyguardViewMediator.this) { + if (DEBUG) Log.d(TAG, "handleVerifyUnlock"); + mKeyguardViewManager.verifyUnlock(); + mShowing = true; + } + } + + /** + * Handle message sent by {@link #notifyScreenOffLocked()} + * @see #NOTIFY_SCREEN_OFF + */ + private void handleNotifyScreenOff() { + synchronized (KeyguardViewMediator.this) { + if (DEBUG) Log.d(TAG, "handleNotifyScreenOff"); + mKeyguardViewManager.onScreenTurnedOff(); + } + } + + /** + * Handle message sent by {@link #notifyScreenOnLocked()} + * @see #NOTIFY_SCREEN_ON + */ + private void handleNotifyScreenOn() { + synchronized (KeyguardViewMediator.this) { + if (DEBUG) Log.d(TAG, "handleNotifyScreenOn"); + mKeyguardViewManager.onScreenTurnedOn(); + } + } +} + + diff --git a/policy/com/android/internal/policy/impl/KeyguardViewProperties.java b/policy/com/android/internal/policy/impl/KeyguardViewProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..bda08eb4252e821420bae92eb12fdb7e3d4d063a --- /dev/null +++ b/policy/com/android/internal/policy/impl/KeyguardViewProperties.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +import android.content.Context; + +/** + * Defines operations necessary for showing a keyguard, including how to create + * it, and various properties that are useful to be able to query independant + * of whether the keyguard instance is around or not. + */ +public interface KeyguardViewProperties { + + /** + * Create a keyguard view. + * @param context the context to use when creating the view. + * @param updateMonitor configuration may be based on this. + * @param controller for talking back with the containing window. + * @return the view. + */ + KeyguardViewBase createKeyguardView(Context context, + KeyguardUpdateMonitor updateMonitor, + KeyguardWindowController controller); + + /** + * Would the keyguard be secure right now? + * @return Whether the keyguard is currently secure, meaning it will block + * the user from getting past it until the user enters some sort of PIN. + */ + boolean isSecure(); + +} diff --git a/media/libdrm/mobile2/include/Drm2CommonTypes.h b/policy/com/android/internal/policy/impl/KeyguardWindowController.java similarity index 56% rename from media/libdrm/mobile2/include/Drm2CommonTypes.h rename to policy/com/android/internal/policy/impl/KeyguardWindowController.java index 8ad3a731a38d26861d72fb6396b0d606225a1647..4ad48fb8e0070d3983acf42e6243123399346f23 100644 --- a/media/libdrm/mobile2/include/Drm2CommonTypes.h +++ b/policy/com/android/internal/policy/impl/KeyguardWindowController.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 The Android Open Source Project + * 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. @@ -13,16 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef _DRM2COMMONTYPES_H_ -#define _DRM2COMMONTYPES_H_ -#include -#ifdef DRM2_UT -#define PROTECTED public -#define PRIVATE public -#else -#define PROTECTED protected -#define PRIVATE private -#endif +package com.android.internal.policy.impl; -#endif +/** + * Interface passed to the keyguard view, for it to call up to control + * its containing window. + */ +public interface KeyguardWindowController { + /** + * Control whether the window needs input -- that is if it has + * text fields and thus should allow input method interaction. + */ + void setNeedsInput(boolean needsInput); +} diff --git a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java new file mode 100644 index 0000000000000000000000000000000000000000..27706eff298d7171f747b4b4df0989ea29a929bc --- /dev/null +++ b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -0,0 +1,790 @@ +/* + * 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. + */ + +package com.android.internal.policy.impl; + +import com.android.internal.R; +import com.android.internal.telephony.IccCard; +import com.android.internal.widget.LockPatternUtils; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.accounts.AccountManagerCallback; +import android.accounts.AccountManagerFuture; +import android.accounts.AuthenticatorException; +import android.accounts.OperationCanceledException; +import android.app.AlertDialog; +import android.app.admin.DevicePolicyManager; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.PixelFormat; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.SystemClock; +import android.os.SystemProperties; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.WindowManager; + +import java.io.IOException; + +/** + * The host view for all of the screens of the pattern unlock screen. There are + * two {@link Mode}s of operation, lock and unlock. This will show the appropriate + * screen, and listen for callbacks via + * {@link com.android.internal.policy.impl.KeyguardScreenCallback} + * from the current screen. + * + * This view, in turn, communicates back to + * {@link com.android.internal.policy.impl.KeyguardViewManager} + * via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate. + */ +public class LockPatternKeyguardView extends KeyguardViewBase { + + static final boolean DEBUG_CONFIGURATION = false; + + // time after launching EmergencyDialer before the screen goes blank. + private static final int EMERGENCY_CALL_TIMEOUT = 10000; + + // intent action for launching emergency dialer activity. + static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL"; + + private static final boolean DEBUG = false; + private static final String TAG = "LockPatternKeyguardView"; + + private final KeyguardUpdateMonitor mUpdateMonitor; + private final KeyguardWindowController mWindowController; + + private View mLockScreen; + private View mUnlockScreen; + + private boolean mScreenOn = false; + private boolean mEnableFallback = false; // assume no fallback UI until we know better + + /** + * The current {@link KeyguardScreen} will use this to communicate back to us. + */ + KeyguardScreenCallback mKeyguardScreenCallback; + + + private boolean mRequiresSim; + + + /** + * Either a lock screen (an informational keyguard screen), or an unlock + * screen (a means for unlocking the device) is shown at any given time. + */ + enum Mode { + LockScreen, + UnlockScreen + } + + /** + * The different types screens available for {@link Mode#UnlockScreen}. + * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode() + */ + enum UnlockMode { + + /** + * Unlock by drawing a pattern. + */ + Pattern, + + /** + * Unlock by entering a sim pin. + */ + SimPin, + + /** + * Unlock by entering an account's login and password. + */ + Account, + + /** + * Unlock by entering a password or PIN + */ + Password, + + /** + * Unknown (uninitialized) value + */ + Unknown + } + + /** + * The current mode. + */ + private Mode mMode = Mode.LockScreen; + + /** + * Keeps track of what mode the current unlock screen is (cached from most recent computation in + * {@link #getUnlockMode}). + */ + private UnlockMode mUnlockScreenMode; + + private boolean mForgotPattern; + + /** + * If true, it means we are in the process of verifying that the user + * can get past the lock screen per {@link #verifyUnlock()} + */ + private boolean mIsVerifyUnlockOnly = false; + + + /** + * Used to lookup the state of the lock pattern + */ + private final LockPatternUtils mLockPatternUtils; + + private UnlockMode mCurrentUnlockMode = UnlockMode.Unknown; + + /** + * The current configuration. + */ + private Configuration mConfiguration; + + /** + * @return Whether we are stuck on the lock screen because the sim is + * missing. + */ + private boolean stuckOnLockScreenBecauseSimMissing() { + return mRequiresSim + && (!mUpdateMonitor.isDeviceProvisioned()) + && (mUpdateMonitor.getSimState() == IccCard.State.ABSENT); + } + + /** + * @param context Used to inflate, and create views. + * @param updateMonitor Knows the state of the world, and passed along to each + * screen so they can use the knowledge, and also register for callbacks + * on dynamic information. + * @param lockPatternUtils Used to look up state of lock pattern. + */ + public LockPatternKeyguardView( + Context context, + KeyguardUpdateMonitor updateMonitor, + LockPatternUtils lockPatternUtils, + KeyguardWindowController controller) { + super(context); + + mConfiguration = context.getResources().getConfiguration(); + mEnableFallback = false; + + mRequiresSim = + TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim")); + + mUpdateMonitor = updateMonitor; + mLockPatternUtils = lockPatternUtils; + mWindowController = controller; + + mMode = getInitialMode(); + + mKeyguardScreenCallback = new KeyguardScreenCallback() { + + public void goToLockScreen() { + mForgotPattern = false; + if (mIsVerifyUnlockOnly) { + // navigating away from unlock screen during verify mode means + // we are done and the user failed to authenticate. + mIsVerifyUnlockOnly = false; + getCallback().keyguardDone(false); + } else { + updateScreen(Mode.LockScreen); + } + } + + public void goToUnlockScreen() { + final IccCard.State simState = mUpdateMonitor.getSimState(); + if (stuckOnLockScreenBecauseSimMissing() + || (simState == IccCard.State.PUK_REQUIRED)){ + // stuck on lock screen when sim missing or puk'd + return; + } + if (!isSecure()) { + getCallback().keyguardDone(true); + } else { + updateScreen(Mode.UnlockScreen); + } + } + + public void forgotPattern(boolean isForgotten) { + if (mEnableFallback) { + mForgotPattern = isForgotten; + updateScreen(Mode.UnlockScreen); + } + } + + public boolean isSecure() { + return LockPatternKeyguardView.this.isSecure(); + } + + public boolean isVerifyUnlockOnly() { + return mIsVerifyUnlockOnly; + } + + public void recreateMe(Configuration config) { + mConfiguration = config; + recreateScreens(); + } + + public void takeEmergencyCallAction() { + pokeWakelock(EMERGENCY_CALL_TIMEOUT); + if (TelephonyManager.getDefault().getCallState() + == TelephonyManager.CALL_STATE_OFFHOOK) { + mLockPatternUtils.resumeCall(); + } else { + Intent intent = new Intent(ACTION_EMERGENCY_DIAL); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + getContext().startActivity(intent); + } + } + + public void pokeWakelock() { + getCallback().pokeWakelock(); + } + + public void pokeWakelock(int millis) { + getCallback().pokeWakelock(millis); + } + + public void keyguardDone(boolean authenticated) { + getCallback().keyguardDone(authenticated); + } + + public void keyguardDoneDrawing() { + // irrelevant to keyguard screen, they shouldn't be calling this + } + + public void reportFailedUnlockAttempt() { + mUpdateMonitor.reportFailedAttempt(); + final int failedAttempts = mUpdateMonitor.getFailedAttempts(); + if (DEBUG) Log.d(TAG, + "reportFailedPatternAttempt: #" + failedAttempts + + " (enableFallback=" + mEnableFallback + ")"); + final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality() + == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; + if (usingLockPattern && mEnableFallback && failedAttempts == + (LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET + - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) { + showAlmostAtAccountLoginDialog(); + } else if (usingLockPattern && mEnableFallback + && failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) { + mLockPatternUtils.setPermanentlyLocked(true); + updateScreen(mMode); + } else if ((failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) + == 0) { + showTimeoutDialog(); + } + mLockPatternUtils.reportFailedPasswordAttempt(); + } + + public boolean doesFallbackUnlockScreenExist() { + return mEnableFallback; + } + + public void reportSuccessfulUnlockAttempt() { + mLockPatternUtils.reportSuccessfulPasswordAttempt(); + } + }; + + /** + * We'll get key events the current screen doesn't use. see + * {@link KeyguardViewBase#onKeyDown(int, android.view.KeyEvent)} + */ + setFocusableInTouchMode(true); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + + // create both the lock and unlock screen so they are quickly available + // when the screen turns on + mLockScreen = createLockScreen(); + addView(mLockScreen); + final UnlockMode unlockMode = getUnlockMode(); + if (DEBUG) Log.d(TAG, + "LockPatternKeyguardView ctor: about to createUnlockScreenFor; mEnableFallback=" + + mEnableFallback); + mUnlockScreen = createUnlockScreenFor(unlockMode); + mUnlockScreenMode = unlockMode; + + maybeEnableFallback(context); + + addView(mUnlockScreen); + updateScreen(mMode); + } + + private class AccountAnalyzer implements AccountManagerCallback { + private final AccountManager mAccountManager; + private final Account[] mAccounts; + private int mAccountIndex; + + private AccountAnalyzer(AccountManager accountManager) { + mAccountManager = accountManager; + mAccounts = accountManager.getAccountsByType("com.google"); + } + + private void next() { + // if we are ready to enable the fallback or if we depleted the list of accounts + // then finish and get out + if (mEnableFallback || mAccountIndex >= mAccounts.length) { + if (mUnlockScreen == null) { + Log.w(TAG, "no unlock screen when trying to enable fallback"); + } else if (mUnlockScreen instanceof PatternUnlockScreen) { + ((PatternUnlockScreen)mUnlockScreen).setEnableFallback(mEnableFallback); + } + return; + } + + // lookup the confirmCredentials intent for the current account + mAccountManager.confirmCredentials(mAccounts[mAccountIndex], null, null, this, null); + } + + public void start() { + mEnableFallback = false; + mAccountIndex = 0; + next(); + } + + public void run(AccountManagerFuture future) { + try { + Bundle result = future.getResult(); + if (result.getParcelable(AccountManager.KEY_INTENT) != null) { + mEnableFallback = true; + } + } catch (OperationCanceledException e) { + // just skip the account if we are unable to query it + } catch (IOException e) { + // just skip the account if we are unable to query it + } catch (AuthenticatorException e) { + // just skip the account if we are unable to query it + } finally { + mAccountIndex++; + next(); + } + } + } + + private void maybeEnableFallback(Context context) { + // Ask the account manager if we have an account that can be used as a + // fallback in case the user forgets his pattern. + AccountAnalyzer accountAnalyzer = new AccountAnalyzer(AccountManager.get(context)); + accountAnalyzer.start(); + } + + + // TODO: + // This overloaded method was added to workaround a race condition in the framework between + // notification for orientation changed, layout() and switching resources. This code attempts + // to avoid drawing the incorrect layout while things are in transition. The method can just + // be removed once the race condition is fixed. See bugs 2262578 and 2292713. + @Override + protected void dispatchDraw(Canvas canvas) { + if (DEBUG) Log.v(TAG, "*** dispatchDraw() time: " + SystemClock.elapsedRealtime()); + super.dispatchDraw(canvas); + } + + @Override + public void reset() { + mIsVerifyUnlockOnly = false; + mForgotPattern = false; + updateScreen(getInitialMode()); + } + + @Override + public void onScreenTurnedOff() { + mScreenOn = false; + mForgotPattern = false; + if (mMode == Mode.LockScreen) { + ((KeyguardScreen) mLockScreen).onPause(); + } else { + ((KeyguardScreen) mUnlockScreen).onPause(); + } + } + + @Override + public void onScreenTurnedOn() { + mScreenOn = true; + if (mMode == Mode.LockScreen) { + ((KeyguardScreen) mLockScreen).onResume(); + } else { + ((KeyguardScreen) mUnlockScreen).onResume(); + } + } + + private void recreateLockScreen() { + if (mLockScreen.getVisibility() == View.VISIBLE) { + ((KeyguardScreen) mLockScreen).onPause(); + } + ((KeyguardScreen) mLockScreen).cleanUp(); + removeView(mLockScreen); + + mLockScreen = createLockScreen(); + mLockScreen.setVisibility(View.INVISIBLE); + addView(mLockScreen); + } + + private void recreateUnlockScreen() { + if (mUnlockScreen.getVisibility() == View.VISIBLE) { + ((KeyguardScreen) mUnlockScreen).onPause(); + } + ((KeyguardScreen) mUnlockScreen).cleanUp(); + removeView(mUnlockScreen); + + final UnlockMode unlockMode = getUnlockMode(); + mUnlockScreen = createUnlockScreenFor(unlockMode); + mUnlockScreen.setVisibility(View.INVISIBLE); + mUnlockScreenMode = unlockMode; + addView(mUnlockScreen); + } + + private void recreateScreens() { + recreateLockScreen(); + recreateUnlockScreen(); + updateScreen(mMode); + } + + @Override + public void wakeWhenReadyTq(int keyCode) { + if (DEBUG) Log.d(TAG, "onWakeKey"); + if (keyCode == KeyEvent.KEYCODE_MENU && isSecure() && (mMode == Mode.LockScreen) + && (mUpdateMonitor.getSimState() != IccCard.State.PUK_REQUIRED)) { + if (DEBUG) Log.d(TAG, "switching screens to unlock screen because wake key was MENU"); + updateScreen(Mode.UnlockScreen); + getCallback().pokeWakelock(); + } else { + if (DEBUG) Log.d(TAG, "poking wake lock immediately"); + getCallback().pokeWakelock(); + } + } + + @Override + public void verifyUnlock() { + if (!isSecure()) { + // non-secure keyguard screens are successfull by default + getCallback().keyguardDone(true); + } else if (mUnlockScreenMode != UnlockMode.Pattern) { + // can only verify unlock when in pattern mode + getCallback().keyguardDone(false); + } else { + // otherwise, go to the unlock screen, see if they can verify it + mIsVerifyUnlockOnly = true; + updateScreen(Mode.UnlockScreen); + } + } + + @Override + public void cleanUp() { + ((KeyguardScreen) mLockScreen).onPause(); + ((KeyguardScreen) mLockScreen).cleanUp(); + ((KeyguardScreen) mUnlockScreen).onPause(); + ((KeyguardScreen) mUnlockScreen).cleanUp(); + } + + private boolean isSecure() { + UnlockMode unlockMode = getUnlockMode(); + boolean secure = false; + switch (unlockMode) { + case Pattern: + secure = mLockPatternUtils.isLockPatternEnabled(); + break; + case SimPin: + secure = mUpdateMonitor.getSimState() == IccCard.State.PIN_REQUIRED + || mUpdateMonitor.getSimState() == IccCard.State.PUK_REQUIRED; + break; + case Account: + secure = true; + break; + case Password: + secure = mLockPatternUtils.isLockPasswordEnabled(); + break; + default: + throw new IllegalStateException("unknown unlock mode " + unlockMode); + } + return secure; + } + + private void updateScreen(final Mode mode) { + + if (DEBUG_CONFIGURATION) Log.v(TAG, "**** UPDATE SCREEN: mode=" + mode + + " last mode=" + mMode, new RuntimeException()); + + mMode = mode; + + // Re-create the unlock screen if necessary. This is primarily required to properly handle + // SIM state changes. This typically happens when this method is called by reset() + if (mode == Mode.UnlockScreen && mCurrentUnlockMode != getUnlockMode()) { + recreateUnlockScreen(); + } + + final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : mLockScreen; + final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : mUnlockScreen; + + // do this before changing visibility so focus isn't requested before the input + // flag is set + mWindowController.setNeedsInput(((KeyguardScreen)visibleScreen).needsInput()); + + if (DEBUG_CONFIGURATION) { + Log.v(TAG, "Gone=" + goneScreen); + Log.v(TAG, "Visible=" + visibleScreen); + } + + if (mScreenOn) { + if (goneScreen.getVisibility() == View.VISIBLE) { + ((KeyguardScreen) goneScreen).onPause(); + } + if (visibleScreen.getVisibility() != View.VISIBLE) { + ((KeyguardScreen) visibleScreen).onResume(); + } + } + + goneScreen.setVisibility(View.GONE); + visibleScreen.setVisibility(View.VISIBLE); + requestLayout(); + + if (!visibleScreen.requestFocus()) { + throw new IllegalStateException("keyguard screen must be able to take " + + "focus when shown " + visibleScreen.getClass().getCanonicalName()); + } + } + + View createLockScreen() { + return new LockScreen( + mContext, + mConfiguration, + mLockPatternUtils, + mUpdateMonitor, + mKeyguardScreenCallback); + } + + View createUnlockScreenFor(UnlockMode unlockMode) { + View unlockView = null; + if (unlockMode == UnlockMode.Pattern) { + PatternUnlockScreen view = new PatternUnlockScreen( + mContext, + mConfiguration, + mLockPatternUtils, + mUpdateMonitor, + mKeyguardScreenCallback, + mUpdateMonitor.getFailedAttempts()); + if (DEBUG) Log.d(TAG, + "createUnlockScreenFor(" + unlockMode + "): mEnableFallback=" + mEnableFallback); + view.setEnableFallback(mEnableFallback); + unlockView = view; + } else if (unlockMode == UnlockMode.SimPin) { + unlockView = new SimUnlockScreen( + mContext, + mConfiguration, + mUpdateMonitor, + mKeyguardScreenCallback, + mLockPatternUtils); + } else if (unlockMode == UnlockMode.Account) { + try { + unlockView = new AccountUnlockScreen( + mContext, + mConfiguration, + mUpdateMonitor, + mKeyguardScreenCallback, + mLockPatternUtils); + } catch (IllegalStateException e) { + Log.i(TAG, "Couldn't instantiate AccountUnlockScreen" + + " (IAccountsService isn't available)"); + // TODO: Need a more general way to provide a + // platform-specific fallback UI here. + // For now, if we can't display the account login + // unlock UI, just bring back the regular "Pattern" unlock mode. + + // (We do this by simply returning a regular UnlockScreen + // here. This means that the user will still see the + // regular pattern unlock UI, regardless of the value of + // mUnlockScreenMode or whether or not we're in the + // "permanently locked" state.) + unlockView = createUnlockScreenFor(UnlockMode.Pattern); + } + } else if (unlockMode == UnlockMode.Password) { + unlockView = new PasswordUnlockScreen( + mContext, + mConfiguration, + mLockPatternUtils, + mUpdateMonitor, + mKeyguardScreenCallback); + } else { + throw new IllegalArgumentException("unknown unlock mode " + unlockMode); + } + mCurrentUnlockMode = unlockMode; + return unlockView; + } + + /** + * Given the current state of things, what should be the initial mode of + * the lock screen (lock or unlock). + */ + private Mode getInitialMode() { + final IccCard.State simState = mUpdateMonitor.getSimState(); + if (stuckOnLockScreenBecauseSimMissing() || (simState == IccCard.State.PUK_REQUIRED)) { + return Mode.LockScreen; + } else { + // Show LockScreen first for any screen other than Pattern unlock. + final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality() + == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; + if (isSecure() && usingLockPattern) { + return Mode.UnlockScreen; + } else { + return Mode.LockScreen; + } + } + } + + /** + * Given the current state of things, what should the unlock screen be? + */ + private UnlockMode getUnlockMode() { + final IccCard.State simState = mUpdateMonitor.getSimState(); + UnlockMode currentMode; + if (simState == IccCard.State.PIN_REQUIRED || simState == IccCard.State.PUK_REQUIRED) { + currentMode = UnlockMode.SimPin; + } else { + final int mode = mLockPatternUtils.getKeyguardStoredPasswordQuality(); + switch (mode) { + case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: + case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: + currentMode = UnlockMode.Password; + break; + case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: + case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: + // "forgot pattern" button is only available in the pattern mode... + if (mForgotPattern || mLockPatternUtils.isPermanentlyLocked()) { + currentMode = UnlockMode.Account; + } else { + currentMode = UnlockMode.Pattern; + } + break; + default: + throw new IllegalStateException("Unknown unlock mode:" + mode); + } + } + return currentMode; + } + + private void showTimeoutDialog() { + int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; + String message = mContext.getString( + R.string.lockscreen_too_many_failed_attempts_dialog_message, + mUpdateMonitor.getFailedAttempts(), + timeoutInSeconds); + final AlertDialog dialog = new AlertDialog.Builder(mContext) + .setTitle(null) + .setMessage(message) + .setNeutralButton(R.string.ok, null) + .create(); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + if (!mContext.getResources().getBoolean( + com.android.internal.R.bool.config_sf_slowBlur)) { + dialog.getWindow().setFlags( + WindowManager.LayoutParams.FLAG_BLUR_BEHIND, + WindowManager.LayoutParams.FLAG_BLUR_BEHIND); + } + dialog.show(); + } + + private void showAlmostAtAccountLoginDialog() { + int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; + String message = mContext.getString( + R.string.lockscreen_failed_attempts_almost_glogin, + LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET + - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, + LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, + timeoutInSeconds); + final AlertDialog dialog = new AlertDialog.Builder(mContext) + .setTitle(null) + .setMessage(message) + .setNeutralButton(R.string.ok, null) + .create(); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + if (!mContext.getResources().getBoolean( + com.android.internal.R.bool.config_sf_slowBlur)) { + dialog.getWindow().setFlags( + WindowManager.LayoutParams.FLAG_BLUR_BEHIND, + WindowManager.LayoutParams.FLAG_BLUR_BEHIND); + } + dialog.show(); + } + + /** + * Used to put wallpaper on the background of the lock screen. Centers it + * Horizontally and pins the bottom (assuming that the lock screen is aligned + * with the bottom, so the wallpaper should extend above the top into the + * status bar). + */ + static private class FastBitmapDrawable extends Drawable { + private Bitmap mBitmap; + private int mOpacity; + + private FastBitmapDrawable(Bitmap bitmap) { + mBitmap = bitmap; + mOpacity = mBitmap.hasAlpha() ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; + } + + @Override + public void draw(Canvas canvas) { + canvas.drawBitmap( + mBitmap, + (getBounds().width() - mBitmap.getWidth()) / 2, + (getBounds().height() - mBitmap.getHeight()), + null); + } + + @Override + public int getOpacity() { + return mOpacity; + } + + @Override + public void setAlpha(int alpha) { + } + + @Override + public void setColorFilter(ColorFilter cf) { + } + + @Override + public int getIntrinsicWidth() { + return mBitmap.getWidth(); + } + + @Override + public int getIntrinsicHeight() { + return mBitmap.getHeight(); + } + + @Override + public int getMinimumWidth() { + return mBitmap.getWidth(); + } + + @Override + public int getMinimumHeight() { + return mBitmap.getHeight(); + } + } +} + diff --git a/policy/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java b/policy/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..ed5a058b8315c1b3d01d5da67d4be6101a3fabdc --- /dev/null +++ b/policy/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +import com.android.internal.widget.LockPatternUtils; + +import android.content.Context; +import com.android.internal.telephony.IccCard; + +/** + * Knows how to create a lock pattern keyguard view, and answer questions about + * it (even if it hasn't been created, per the interface specs). + */ +public class LockPatternKeyguardViewProperties implements KeyguardViewProperties { + + private final LockPatternUtils mLockPatternUtils; + private final KeyguardUpdateMonitor mUpdateMonitor; + + /** + * @param lockPatternUtils Used to know whether the pattern enabled, and passed + * onto the keygaurd view when it is created. + * @param updateMonitor Used to know whether the sim pin is enabled, and passed + * onto the keyguard view when it is created. + */ + public LockPatternKeyguardViewProperties(LockPatternUtils lockPatternUtils, + KeyguardUpdateMonitor updateMonitor) { + mLockPatternUtils = lockPatternUtils; + mUpdateMonitor = updateMonitor; + } + + public KeyguardViewBase createKeyguardView(Context context, + KeyguardUpdateMonitor updateMonitor, + KeyguardWindowController controller) { + return new LockPatternKeyguardView(context, updateMonitor, + mLockPatternUtils, controller); + } + + public boolean isSecure() { + return mLockPatternUtils.isSecure() || isSimPinSecure(); + } + + private boolean isSimPinSecure() { + final IccCard.State simState = mUpdateMonitor.getSimState(); + return (simState == IccCard.State.PIN_REQUIRED || simState == IccCard.State.PUK_REQUIRED + || simState == IccCard.State.ABSENT); + } + +} diff --git a/policy/com/android/internal/policy/impl/LockScreen.java b/policy/com/android/internal/policy/impl/LockScreen.java new file mode 100644 index 0000000000000000000000000000000000000000..a5ef1fab389f31eec3245835531247a3fcfb759c --- /dev/null +++ b/policy/com/android/internal/policy/impl/LockScreen.java @@ -0,0 +1,681 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +import com.android.internal.R; +import com.android.internal.telephony.IccCard; +import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.SlidingTab; + +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.ColorStateList; +import android.text.format.DateFormat; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.*; +import android.graphics.drawable.Drawable; +import android.util.Log; +import android.media.AudioManager; +import android.os.SystemClock; +import android.os.SystemProperties; +import android.provider.Settings; + +import java.util.Date; +import java.io.File; + +/** + * The screen within {@link LockPatternKeyguardView} that shows general + * information about the device depending on its state, and how to get + * past it, as applicable. + */ +class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateMonitor.InfoCallback, + KeyguardUpdateMonitor.SimStateCallback, SlidingTab.OnTriggerListener { + + private static final boolean DBG = false; + private static final String TAG = "LockScreen"; + private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key"; + + private Status mStatus = Status.Normal; + + private final LockPatternUtils mLockPatternUtils; + private final KeyguardUpdateMonitor mUpdateMonitor; + private final KeyguardScreenCallback mCallback; + + private TextView mCarrier; + private SlidingTab mSelector; + private TextView mTime; + private TextView mDate; + private TextView mStatus1; + private TextView mStatus2; + private TextView mScreenLocked; + private TextView mEmergencyCallText; + private Button mEmergencyCallButton; + + // current configuration state of keyboard and display + private int mKeyboardHidden; + private int mCreationOrientation; + + // are we showing battery information? + private boolean mShowingBatteryInfo = false; + + // last known plugged in state + private boolean mPluggedIn = false; + + // last known battery level + private int mBatteryLevel = 100; + + private String mNextAlarm = null; + private Drawable mAlarmIcon = null; + private String mCharging = null; + private Drawable mChargingIcon = null; + + private boolean mSilentMode; + private AudioManager mAudioManager; + private String mDateFormatString; + private java.text.DateFormat mTimeFormat; + private boolean mEnableMenuKeyInLockScreen; + + /** + * The status of this lock screen. + */ + enum Status { + /** + * Normal case (sim card present, it's not locked) + */ + Normal(true), + + /** + * The sim card is 'network locked'. + */ + NetworkLocked(true), + + /** + * The sim card is missing. + */ + SimMissing(false), + + /** + * The sim card is missing, and this is the device isn't provisioned, so we don't let + * them get past the screen. + */ + SimMissingLocked(false), + + /** + * The sim card is PUK locked, meaning they've entered the wrong sim unlock code too many + * times. + */ + SimPukLocked(false), + + /** + * The sim card is locked. + */ + SimLocked(true); + + private final boolean mShowStatusLines; + + Status(boolean mShowStatusLines) { + this.mShowStatusLines = mShowStatusLines; + } + + /** + * @return Whether the status lines (battery level and / or next alarm) are shown while + * in this state. Mostly dictated by whether this is room for them. + */ + public boolean showStatusLines() { + return mShowStatusLines; + } + } + + /** + * In general, we enable unlocking the insecure key guard with the menu key. However, there are + * some cases where we wish to disable it, notably when the menu button placement or technology + * is prone to false positives. + * + * @return true if the menu key should be enabled + */ + private boolean shouldEnableMenuKey() { + final Resources res = getResources(); + final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen); + final boolean isMonkey = SystemProperties.getBoolean("ro.monkey", false); + final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists(); + return !configDisabled || isMonkey || fileOverride; + } + + /** + * @param context Used to setup the view. + * @param configuration The current configuration. Used to use when selecting layout, etc. + * @param lockPatternUtils Used to know the state of the lock pattern settings. + * @param updateMonitor Used to register for updates on various keyguard related + * state, and query the initial state at setup. + * @param callback Used to communicate back to the host keyguard view. + */ + LockScreen(Context context, Configuration configuration, LockPatternUtils lockPatternUtils, + KeyguardUpdateMonitor updateMonitor, + KeyguardScreenCallback callback) { + super(context); + mLockPatternUtils = lockPatternUtils; + mUpdateMonitor = updateMonitor; + mCallback = callback; + + mEnableMenuKeyInLockScreen = shouldEnableMenuKey(); + + mCreationOrientation = configuration.orientation; + + mKeyboardHidden = configuration.hardKeyboardHidden; + + if (LockPatternKeyguardView.DEBUG_CONFIGURATION) { + Log.v(TAG, "***** CREATING LOCK SCREEN", new RuntimeException()); + Log.v(TAG, "Cur orient=" + mCreationOrientation + + " res orient=" + context.getResources().getConfiguration().orientation); + } + + final LayoutInflater inflater = LayoutInflater.from(context); + if (DBG) Log.v(TAG, "Creation orientation = " + mCreationOrientation); + if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) { + inflater.inflate(R.layout.keyguard_screen_tab_unlock, this, true); + } else { + inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true); + } + + mCarrier = (TextView) findViewById(R.id.carrier); + // Required for Marquee to work + mCarrier.setSelected(true); + mCarrier.setTextColor(0xffffffff); + + mDate = (TextView) findViewById(R.id.date); + mStatus1 = (TextView) findViewById(R.id.status1); + mStatus2 = (TextView) findViewById(R.id.status2); + + mScreenLocked = (TextView) findViewById(R.id.screenLocked); + mSelector = (SlidingTab) findViewById(R.id.tab_selector); + mSelector.setHoldAfterTrigger(true, false); + mSelector.setLeftHintText(R.string.lockscreen_unlock_label); + + mEmergencyCallText = (TextView) findViewById(R.id.emergencyCallText); + mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton); + mEmergencyCallButton.setText(R.string.lockscreen_emergency_call); + + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); + mEmergencyCallButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + mCallback.takeEmergencyCallAction(); + } + }); + + + setFocusable(true); + setFocusableInTouchMode(true); + setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); + + updateMonitor.registerInfoCallback(this); + updateMonitor.registerSimStateCallback(this); + + mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); + mSilentMode = isSilentMode(); + + mSelector.setLeftTabResources( + R.drawable.ic_jog_dial_unlock, + R.drawable.jog_tab_target_green, + R.drawable.jog_tab_bar_left_unlock, + R.drawable.jog_tab_left_unlock); + + updateRightTabResources(); + + mSelector.setOnTriggerListener(this); + + resetStatusInfo(updateMonitor); + } + + private boolean isSilentMode() { + return mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL; + } + + private void updateRightTabResources() { + boolean vibe = mSilentMode + && (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE); + + mSelector.setRightTabResources( + mSilentMode ? ( vibe ? R.drawable.ic_jog_dial_vibrate_on + : R.drawable.ic_jog_dial_sound_off ) + : R.drawable.ic_jog_dial_sound_on, + mSilentMode ? R.drawable.jog_tab_target_yellow + : R.drawable.jog_tab_target_gray, + mSilentMode ? R.drawable.jog_tab_bar_right_sound_on + : R.drawable.jog_tab_bar_right_sound_off, + mSilentMode ? R.drawable.jog_tab_right_sound_on + : R.drawable.jog_tab_right_sound_off); + } + + private void resetStatusInfo(KeyguardUpdateMonitor updateMonitor) { + mShowingBatteryInfo = updateMonitor.shouldShowBatteryInfo(); + mPluggedIn = updateMonitor.isDevicePluggedIn(); + mBatteryLevel = updateMonitor.getBatteryLevel(); + + mStatus = getCurrentStatus(updateMonitor.getSimState()); + updateLayout(mStatus); + + refreshBatteryStringAndIcon(); + refreshAlarmDisplay(); + + mTimeFormat = DateFormat.getTimeFormat(getContext()); + mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year); + refreshTimeAndDateDisplay(); + updateStatusLines(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_MENU && mEnableMenuKeyInLockScreen) { + mCallback.goToUnlockScreen(); + } + return false; + } + + /** {@inheritDoc} */ + public void onTrigger(View v, int whichHandle) { + if (whichHandle == SlidingTab.OnTriggerListener.LEFT_HANDLE) { + mCallback.goToUnlockScreen(); + } else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) { + // toggle silent mode + mSilentMode = !mSilentMode; + if (mSilentMode) { + final boolean vibe = (Settings.System.getInt( + getContext().getContentResolver(), + Settings.System.VIBRATE_IN_SILENT, 1) == 1); + + mAudioManager.setRingerMode(vibe + ? AudioManager.RINGER_MODE_VIBRATE + : AudioManager.RINGER_MODE_SILENT); + } else { + mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); + } + + updateRightTabResources(); + + String message = mSilentMode ? + getContext().getString(R.string.global_action_silent_mode_on_status) : + getContext().getString(R.string.global_action_silent_mode_off_status); + + final int toastIcon = mSilentMode + ? R.drawable.ic_lock_ringer_off + : R.drawable.ic_lock_ringer_on; + + final int toastColor = mSilentMode + ? getContext().getResources().getColor(R.color.keyguard_text_color_soundoff) + : getContext().getResources().getColor(R.color.keyguard_text_color_soundon); + toastMessage(mScreenLocked, message, toastColor, toastIcon); + mCallback.pokeWakelock(); + } + } + + /** {@inheritDoc} */ + public void onGrabbedStateChange(View v, int grabbedState) { + if (grabbedState == SlidingTab.OnTriggerListener.RIGHT_HANDLE) { + mSilentMode = isSilentMode(); + mSelector.setRightHintText(mSilentMode ? R.string.lockscreen_sound_on_label + : R.string.lockscreen_sound_off_label); + } + mCallback.pokeWakelock(); + } + + /** + * Displays a message in a text view and then restores the previous text. + * @param textView The text view. + * @param text The text. + * @param color The color to apply to the text, or 0 if the existing color should be used. + * @param iconResourceId The left hand icon. + */ + private void toastMessage(final TextView textView, final String text, final int color, final int iconResourceId) { + if (mPendingR1 != null) { + textView.removeCallbacks(mPendingR1); + mPendingR1 = null; + } + if (mPendingR2 != null) { + mPendingR2.run(); // fire immediately, restoring non-toasted appearance + textView.removeCallbacks(mPendingR2); + mPendingR2 = null; + } + + final String oldText = textView.getText().toString(); + final ColorStateList oldColors = textView.getTextColors(); + + mPendingR1 = new Runnable() { + public void run() { + textView.setText(text); + if (color != 0) { + textView.setTextColor(color); + } + textView.setCompoundDrawablesWithIntrinsicBounds(iconResourceId, 0, 0, 0); + } + }; + + textView.postDelayed(mPendingR1, 0); + mPendingR2 = new Runnable() { + public void run() { + textView.setText(oldText); + textView.setTextColor(oldColors); + textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + }; + textView.postDelayed(mPendingR2, 3500); + } + private Runnable mPendingR1; + private Runnable mPendingR2; + + private void refreshAlarmDisplay() { + mNextAlarm = mLockPatternUtils.getNextAlarm(); + if (mNextAlarm != null) { + mAlarmIcon = getContext().getResources().getDrawable(R.drawable.ic_lock_idle_alarm); + } + updateStatusLines(); + } + + /** {@inheritDoc} */ + public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, + int batteryLevel) { + if (DBG) Log.d(TAG, "onRefreshBatteryInfo(" + showBatteryInfo + ", " + pluggedIn + ")"); + mShowingBatteryInfo = showBatteryInfo; + mPluggedIn = pluggedIn; + mBatteryLevel = batteryLevel; + + refreshBatteryStringAndIcon(); + updateStatusLines(); + } + + private void refreshBatteryStringAndIcon() { + if (!mShowingBatteryInfo) { + mCharging = null; + return; + } + + if (mChargingIcon == null) { + mChargingIcon = + getContext().getResources().getDrawable(R.drawable.ic_lock_idle_charging); + } + + if (mPluggedIn) { + if (mBatteryLevel >= 100) { + mCharging = getContext().getString(R.string.lockscreen_charged); + } else { + mCharging = getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel); + } + } else { + mCharging = getContext().getString(R.string.lockscreen_low_battery); + } + } + + /** {@inheritDoc} */ + public void onTimeChanged() { + refreshTimeAndDateDisplay(); + } + + private void refreshTimeAndDateDisplay() { + mDate.setText(DateFormat.format(mDateFormatString, new Date())); + } + + private void updateStatusLines() { + if (!mStatus.showStatusLines() + || (mCharging == null && mNextAlarm == null)) { + mStatus1.setVisibility(View.INVISIBLE); + mStatus2.setVisibility(View.INVISIBLE); + } else if (mCharging != null && mNextAlarm == null) { + // charging only + mStatus1.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.INVISIBLE); + + mStatus1.setText(mCharging); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(mChargingIcon, null, null, null); + } else if (mNextAlarm != null && mCharging == null) { + // next alarm only + mStatus1.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.INVISIBLE); + + mStatus1.setText(mNextAlarm); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(mAlarmIcon, null, null, null); + } else if (mCharging != null && mNextAlarm != null) { + // both charging and next alarm + mStatus1.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.VISIBLE); + + mStatus1.setText(mCharging); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(mChargingIcon, null, null, null); + mStatus2.setText(mNextAlarm); + mStatus2.setCompoundDrawablesWithIntrinsicBounds(mAlarmIcon, null, null, null); + } + } + + /** {@inheritDoc} */ + public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { + if (DBG) Log.d(TAG, "onRefreshCarrierInfo(" + plmn + ", " + spn + ")"); + updateLayout(mStatus); + } + + /** + * Determine the current status of the lock screen given the sim state and other stuff. + */ + private Status getCurrentStatus(IccCard.State simState) { + boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned() + && simState == IccCard.State.ABSENT); + if (missingAndNotProvisioned) { + return Status.SimMissingLocked; + } + + switch (simState) { + case ABSENT: + return Status.SimMissing; + case NETWORK_LOCKED: + return Status.SimMissingLocked; + case NOT_READY: + return Status.SimMissing; + case PIN_REQUIRED: + return Status.SimLocked; + case PUK_REQUIRED: + return Status.SimPukLocked; + case READY: + return Status.Normal; + case UNKNOWN: + return Status.SimMissing; + } + return Status.SimMissing; + } + + /** + * Update the layout to match the current status. + */ + private void updateLayout(Status status) { + // The emergency call button no longer appears on this screen. + if (DBG) Log.d(TAG, "updateLayout: status=" + status); + + mEmergencyCallButton.setVisibility(View.GONE); // in almost all cases + + switch (status) { + case Normal: + // text + mCarrier.setText( + getCarrierString( + mUpdateMonitor.getTelephonyPlmn(), + mUpdateMonitor.getTelephonySpn())); + + // Empty now, but used for sliding tab feedback + mScreenLocked.setText(""); + + // layout + mScreenLocked.setVisibility(View.VISIBLE); + mSelector.setVisibility(View.VISIBLE); + mEmergencyCallText.setVisibility(View.GONE); + break; + case NetworkLocked: + // The carrier string shows both sim card status (i.e. No Sim Card) and + // carrier's name and/or "Emergency Calls Only" status + mCarrier.setText( + getCarrierString( + mUpdateMonitor.getTelephonyPlmn(), + getContext().getText(R.string.lockscreen_network_locked_message))); + mScreenLocked.setText(R.string.lockscreen_instructions_when_pattern_disabled); + + // layout + mScreenLocked.setVisibility(View.VISIBLE); + mSelector.setVisibility(View.VISIBLE); + mEmergencyCallText.setVisibility(View.GONE); + break; + case SimMissing: + // text + mCarrier.setText(R.string.lockscreen_missing_sim_message_short); + mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions); + + // layout + mScreenLocked.setVisibility(View.VISIBLE); + mSelector.setVisibility(View.VISIBLE); + mEmergencyCallText.setVisibility(View.VISIBLE); + // do not need to show the e-call button; user may unlock + break; + case SimMissingLocked: + // text + mCarrier.setText( + getCarrierString( + mUpdateMonitor.getTelephonyPlmn(), + getContext().getText(R.string.lockscreen_missing_sim_message_short))); + mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions); + + // layout + mScreenLocked.setVisibility(View.VISIBLE); + mSelector.setVisibility(View.GONE); // cannot unlock + mEmergencyCallText.setVisibility(View.VISIBLE); + mEmergencyCallButton.setVisibility(View.VISIBLE); + break; + case SimLocked: + // text + mCarrier.setText( + getCarrierString( + mUpdateMonitor.getTelephonyPlmn(), + getContext().getText(R.string.lockscreen_sim_locked_message))); + + // layout + mScreenLocked.setVisibility(View.INVISIBLE); + mSelector.setVisibility(View.VISIBLE); + mEmergencyCallText.setVisibility(View.GONE); + break; + case SimPukLocked: + // text + mCarrier.setText( + getCarrierString( + mUpdateMonitor.getTelephonyPlmn(), + getContext().getText(R.string.lockscreen_sim_puk_locked_message))); + mScreenLocked.setText(R.string.lockscreen_sim_puk_locked_instructions); + + // layout + mScreenLocked.setVisibility(View.VISIBLE); + mSelector.setVisibility(View.GONE); // cannot unlock + mEmergencyCallText.setVisibility(View.VISIBLE); + mEmergencyCallButton.setVisibility(View.VISIBLE); + break; + } + } + + static CharSequence getCarrierString(CharSequence telephonyPlmn, CharSequence telephonySpn) { + if (telephonyPlmn != null && telephonySpn == null) { + return telephonyPlmn; + } else if (telephonyPlmn != null && telephonySpn != null) { + return telephonyPlmn + "|" + telephonySpn; + } else if (telephonyPlmn == null && telephonySpn != null) { + return telephonySpn; + } else { + return ""; + } + } + + public void onSimStateChanged(IccCard.State simState) { + if (DBG) Log.d(TAG, "onSimStateChanged(" + simState + ")"); + mStatus = getCurrentStatus(simState); + updateLayout(mStatus); + updateStatusLines(); + } + + void updateConfiguration() { + Configuration newConfig = getResources().getConfiguration(); + if (newConfig.orientation != mCreationOrientation) { + mCallback.recreateMe(newConfig); + } else if (newConfig.hardKeyboardHidden != mKeyboardHidden) { + mKeyboardHidden = newConfig.hardKeyboardHidden; + final boolean isKeyboardOpen = mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO; + if (mUpdateMonitor.isKeyguardBypassEnabled() && isKeyboardOpen) { + mCallback.goToUnlockScreen(); + } + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (LockPatternKeyguardView.DEBUG_CONFIGURATION) { + Log.v(TAG, "***** LOCK ATTACHED TO WINDOW"); + Log.v(TAG, "Cur orient=" + mCreationOrientation + + ", new config=" + getResources().getConfiguration()); + } + updateConfiguration(); + } + + /** {@inheritDoc} */ + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (LockPatternKeyguardView.DEBUG_CONFIGURATION) { + Log.w(TAG, "***** LOCK CONFIG CHANGING", new RuntimeException()); + Log.v(TAG, "Cur orient=" + mCreationOrientation + + ", new config=" + newConfig); + } + updateConfiguration(); + } + + /** {@inheritDoc} */ + public boolean needsInput() { + return false; + } + + /** {@inheritDoc} */ + public void onPause() { + + } + + /** {@inheritDoc} */ + public void onResume() { + resetStatusInfo(mUpdateMonitor); + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); + } + + /** {@inheritDoc} */ + public void cleanUp() { + mUpdateMonitor.removeCallback(this); + } + + /** {@inheritDoc} */ + public void onRingerModeChanged(int state) { + boolean silent = AudioManager.RINGER_MODE_NORMAL != state; + if (silent != mSilentMode) { + mSilentMode = silent; + updateRightTabResources(); + } + } + + public void onPhoneStateChanged(String newState) { + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); + } +} diff --git a/policy/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/com/android/internal/policy/impl/PasswordUnlockScreen.java new file mode 100644 index 0000000000000000000000000000000000000000..39f2917a945b00f3241cdcdfc9dda1de167d4b1b --- /dev/null +++ b/policy/com/android/internal/policy/impl/PasswordUnlockScreen.java @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2010 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. + */ + +package com.android.internal.policy.impl; + +import android.app.admin.DevicePolicyManager; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Rect; + +import com.android.internal.policy.impl.PatternUnlockScreen.FooterMode; +import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.PasswordEntryKeyboardView; + +import android.os.CountDownTimer; +import android.os.SystemClock; +import android.telephony.TelephonyManager; +import android.text.method.DigitsKeyListener; +import android.text.method.TextKeyListener; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; + +import com.android.internal.R; +import com.android.internal.widget.PasswordEntryKeyboardHelper; + +/** + * Displays a dialer-like interface or alphanumeric (latin-1) key entry for the user to enter + * an unlock password + */ +public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen, + View.OnClickListener, KeyguardUpdateMonitor.InfoCallback, OnEditorActionListener { + + private final KeyguardUpdateMonitor mUpdateMonitor; + private final KeyguardScreenCallback mCallback; + + private EditText mPasswordEntry; + private Button mEmergencyCallButton; + private LockPatternUtils mLockPatternUtils; + private PasswordEntryKeyboardView mKeyboardView; + private PasswordEntryKeyboardHelper mKeyboardHelper; + + private int mCreationOrientation; + private int mCreationHardKeyboardHidden; + private CountDownTimer mCountdownTimer; + private TextView mTitle; + + // To avoid accidental lockout due to events while the device in in the pocket, ignore + // any passwords with length less than or equal to this length. + private static final int MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT = 3; + + public PasswordUnlockScreen(Context context, Configuration configuration, + LockPatternUtils lockPatternUtils, KeyguardUpdateMonitor updateMonitor, + KeyguardScreenCallback callback) { + super(context); + + mCreationHardKeyboardHidden = configuration.hardKeyboardHidden; + mCreationOrientation = configuration.orientation; + mUpdateMonitor = updateMonitor; + mCallback = callback; + mLockPatternUtils = lockPatternUtils; + + LayoutInflater layoutInflater = LayoutInflater.from(context); + if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) { + layoutInflater.inflate(R.layout.keyguard_screen_password_portrait, this, true); + } else { + layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true); + } + + final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality(); + final boolean isAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality + || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality; + + mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard); + mPasswordEntry = (EditText) findViewById(R.id.passwordEntry); + mPasswordEntry.setOnEditorActionListener(this); + mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall); + mEmergencyCallButton.setOnClickListener(this); + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); + mTitle = (TextView) findViewById(R.id.enter_password_label); + + mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this); + mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA + : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC); + + mKeyboardView.setVisibility(mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO + ? View.INVISIBLE : View.VISIBLE); + mPasswordEntry.requestFocus(); + + // This allows keyboards with overlapping qwerty/numeric keys to choose just the + // numeric keys. + if (isAlpha) { + mPasswordEntry.setKeyListener(TextKeyListener.getInstance()); + } else { + mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance()); + } + + mKeyboardHelper.setVibratePattern(mLockPatternUtils.isTactileFeedbackEnabled() ? + com.android.internal.R.array.config_virtualKeyVibePattern : 0); + } + + @Override + protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { + // send focus to the password field + return mPasswordEntry.requestFocus(direction, previouslyFocusedRect); + } + + /** {@inheritDoc} */ + public boolean needsInput() { + return false; + } + + /** {@inheritDoc} */ + public void onPause() { + + } + + /** {@inheritDoc} */ + public void onResume() { + // start fresh + mPasswordEntry.setText(""); + mPasswordEntry.requestFocus(); + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); + + // if the user is currently locked out, enforce it. + long deadline = mLockPatternUtils.getLockoutAttemptDeadline(); + if (deadline != 0) { + handleAttemptLockout(deadline); + } + } + + /** {@inheritDoc} */ + public void cleanUp() { + mUpdateMonitor.removeCallback(this); + } + + public void onClick(View v) { + if (v == mEmergencyCallButton) { + mCallback.takeEmergencyCallAction(); + } + mCallback.pokeWakelock(); + } + + private void verifyPasswordAndUnlock() { + String entry = mPasswordEntry.getText().toString(); + if (mLockPatternUtils.checkPassword(entry)) { + mCallback.keyguardDone(true); + mCallback.reportSuccessfulUnlockAttempt(); + } else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) { + // to avoid accidental lockout, only count attempts that are long enough to be a + // real password. This may require some tweaking. + mCallback.reportFailedUnlockAttempt(); + if (0 == (mUpdateMonitor.getFailedAttempts() + % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) { + long deadline = mLockPatternUtils.setLockoutAttemptDeadline(); + handleAttemptLockout(deadline); + } + } + mPasswordEntry.setText(""); + } + + // Prevent user from using the PIN/Password entry until scheduled deadline. + private void handleAttemptLockout(long elapsedRealtimeDeadline) { + mPasswordEntry.setEnabled(false); + mKeyboardView.setEnabled(false); + long elapsedRealtime = SystemClock.elapsedRealtime(); + mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) { + + @Override + public void onTick(long millisUntilFinished) { + int secondsRemaining = (int) (millisUntilFinished / 1000); + String instructions = getContext().getString( + R.string.lockscreen_too_many_failed_attempts_countdown, + secondsRemaining); + mTitle.setText(instructions); + } + + @Override + public void onFinish() { + mPasswordEntry.setEnabled(true); + mTitle.setText(R.string.keyguard_password_enter_password_code); + mKeyboardView.setEnabled(true); + } + }.start(); + } + + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + mCallback.pokeWakelock(); + return false; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + Configuration config = getResources().getConfiguration(); + if (config.orientation != mCreationOrientation + || config.hardKeyboardHidden != mCreationHardKeyboardHidden) { + mCallback.recreateMe(config); + } + } + + /** {@inheritDoc} */ + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (newConfig.orientation != mCreationOrientation + || newConfig.hardKeyboardHidden != mCreationHardKeyboardHidden) { + mCallback.recreateMe(newConfig); + } + } + + public void onKeyboardChange(boolean isKeyboardOpen) { + // Don't show the soft keyboard when the real keyboard is open + mKeyboardView.setVisibility(isKeyboardOpen ? View.INVISIBLE : View.VISIBLE); + } + + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + // Check if this was the result of hitting the enter key + if (actionId == EditorInfo.IME_NULL) { + verifyPasswordAndUnlock(); + return true; + } + return false; + } + + public void onPhoneStateChanged(String newState) { + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); + } + + public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { + + } + + public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { + + } + + public void onRingerModeChanged(int state) { + + } + + public void onTimeChanged() { + + } + +} diff --git a/policy/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/com/android/internal/policy/impl/PatternUnlockScreen.java new file mode 100644 index 0000000000000000000000000000000000000000..418e243922795cf985c3b35b414bb76566122847 --- /dev/null +++ b/policy/com/android/internal/policy/impl/PatternUnlockScreen.java @@ -0,0 +1,580 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +import android.content.Context; +import android.content.res.Configuration; +import android.os.CountDownTimer; +import android.os.SystemClock; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.MotionEvent; +import android.widget.Button; +import android.widget.TextView; +import android.text.format.DateFormat; +import android.text.TextUtils; +import android.util.Log; +import com.android.internal.R; +import com.android.internal.telephony.IccCard; +import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient; +import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.LockPatternView; +import com.android.internal.widget.LockPatternView.Cell; + +import java.util.List; +import java.util.Date; + +/** + * This is the screen that shows the 9 circle unlock widget and instructs + * the user how to unlock their device, or make an emergency call. + */ +class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient + implements KeyguardScreen, KeyguardUpdateMonitor.InfoCallback, + KeyguardUpdateMonitor.SimStateCallback { + + private static final boolean DEBUG = false; + private static final String TAG = "UnlockScreen"; + + // how long before we clear the wrong pattern + private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000; + + // how long we stay awake after each key beyond MIN_PATTERN_BEFORE_POKE_WAKELOCK + private static final int UNLOCK_PATTERN_WAKE_INTERVAL_MS = 7000; + + // how long we stay awake after the user hits the first dot. + private static final int UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS = 2000; + + // how many cells the user has to cross before we poke the wakelock + private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2; + + private int mFailedPatternAttemptsSinceLastTimeout = 0; + private int mTotalFailedPatternAttempts = 0; + private CountDownTimer mCountdownTimer = null; + + private final LockPatternUtils mLockPatternUtils; + private final KeyguardUpdateMonitor mUpdateMonitor; + private final KeyguardScreenCallback mCallback; + + /** + * whether there is a fallback option available when the pattern is forgotten. + */ + private boolean mEnableFallback; + + private String mDateFormatString; + + private TextView mCarrier; + private TextView mDate; + + // are we showing battery information? + private boolean mShowingBatteryInfo = false; + + // last known plugged in state + private boolean mPluggedIn = false; + + // last known battery level + private int mBatteryLevel = 100; + + private String mNextAlarm = null; + + private String mInstructions = null; + private TextView mStatus1; + private TextView mStatusSep; + private TextView mStatus2; + + + private LockPatternView mLockPatternView; + + private ViewGroup mFooterNormal; + private ViewGroup mFooterForgotPattern; + + /** + * Keeps track of the last time we poked the wake lock during dispatching + * of the touch event, initalized to something gauranteed to make us + * poke it when the user starts drawing the pattern. + * @see #dispatchTouchEvent(android.view.MotionEvent) + */ + private long mLastPokeTime = -UNLOCK_PATTERN_WAKE_INTERVAL_MS; + + /** + * Useful for clearing out the wrong pattern after a delay + */ + private Runnable mCancelPatternRunnable = new Runnable() { + public void run() { + mLockPatternView.clearPattern(); + } + }; + + private Button mForgotPatternButton; + private Button mEmergencyAlone; + private Button mEmergencyTogether; + private int mCreationOrientation; + + enum FooterMode { + Normal, + ForgotLockPattern, + VerifyUnlocked + } + + private void updateFooter(FooterMode mode) { + switch (mode) { + case Normal: + mFooterNormal.setVisibility(View.VISIBLE); + mFooterForgotPattern.setVisibility(View.GONE); + break; + case ForgotLockPattern: + mFooterNormal.setVisibility(View.GONE); + mFooterForgotPattern.setVisibility(View.VISIBLE); + mForgotPatternButton.setVisibility(View.VISIBLE); + break; + case VerifyUnlocked: + mFooterNormal.setVisibility(View.GONE); + mFooterForgotPattern.setVisibility(View.GONE); + } + } + + /** + * @param context The context. + * @param configuration + * @param lockPatternUtils Used to lookup lock pattern settings. + * @param updateMonitor Used to lookup state affecting keyguard. + * @param callback Used to notify the manager when we're done, etc. + * @param totalFailedAttempts The current number of failed attempts. + * @param enableFallback True if a backup unlock option is available when the user has forgotten + * their pattern (e.g they have a google account so we can show them the account based + * backup option). + */ + PatternUnlockScreen(Context context, + Configuration configuration, LockPatternUtils lockPatternUtils, + KeyguardUpdateMonitor updateMonitor, + KeyguardScreenCallback callback, + int totalFailedAttempts) { + super(context); + mLockPatternUtils = lockPatternUtils; + mUpdateMonitor = updateMonitor; + mCallback = callback; + mTotalFailedPatternAttempts = totalFailedAttempts; + mFailedPatternAttemptsSinceLastTimeout = + totalFailedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT; + + if (DEBUG) Log.d(TAG, + "UnlockScreen() ctor: totalFailedAttempts=" + + totalFailedAttempts + ", mFailedPat...=" + + mFailedPatternAttemptsSinceLastTimeout + ); + + mCreationOrientation = configuration.orientation; + + LayoutInflater inflater = LayoutInflater.from(context); + if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) { + inflater.inflate(R.layout.keyguard_screen_unlock_portrait, this, true); + } else { + inflater.inflate(R.layout.keyguard_screen_unlock_landscape, this, true); + } + + mCarrier = (TextView) findViewById(R.id.carrier); + mDate = (TextView) findViewById(R.id.date); + + mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year); + refreshTimeAndDateDisplay(); + + mStatus1 = (TextView) findViewById(R.id.status1); + mStatusSep = (TextView) findViewById(R.id.statusSep); + mStatus2 = (TextView) findViewById(R.id.status2); + + resetStatusInfo(); + + + mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern); + + mFooterNormal = (ViewGroup) findViewById(R.id.footerNormal); + mFooterForgotPattern = (ViewGroup) findViewById(R.id.footerForgotPattern); + + // emergency call buttons + final OnClickListener emergencyClick = new OnClickListener() { + public void onClick(View v) { + mCallback.takeEmergencyCallAction(); + } + }; + + mEmergencyAlone = (Button) findViewById(R.id.emergencyCallAlone); + mEmergencyAlone.setFocusable(false); // touch only! + mEmergencyAlone.setOnClickListener(emergencyClick); + mEmergencyTogether = (Button) findViewById(R.id.emergencyCallTogether); + mEmergencyTogether.setFocusable(false); + mEmergencyTogether.setOnClickListener(emergencyClick); + refreshEmergencyButtonText(); + + mForgotPatternButton = (Button) findViewById(R.id.forgotPattern); + mForgotPatternButton.setText(R.string.lockscreen_forgot_pattern_button_text); + mForgotPatternButton.setOnClickListener(new OnClickListener() { + + public void onClick(View v) { + mCallback.forgotPattern(true); + } + }); + + // make it so unhandled touch events within the unlock screen go to the + // lock pattern view. + setDefaultTouchRecepient(mLockPatternView); + + mLockPatternView.setSaveEnabled(false); + mLockPatternView.setFocusable(false); + mLockPatternView.setOnPatternListener(new UnlockPatternListener()); + + // stealth mode will be the same for the life of this screen + mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled()); + + // vibrate mode will be the same for the life of this screen + mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled()); + + // assume normal footer mode for now + updateFooter(FooterMode.Normal); + + updateMonitor.registerInfoCallback(this); + updateMonitor.registerSimStateCallback(this); + setFocusableInTouchMode(true); + + // Required to get Marquee to work. + mCarrier.setSelected(true); + mCarrier.setTextColor(0xffffffff); + + // until we get an update... + mCarrier.setText( + LockScreen.getCarrierString( + mUpdateMonitor.getTelephonyPlmn(), + mUpdateMonitor.getTelephonySpn())); + } + + private void refreshEmergencyButtonText() { + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyAlone); + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyTogether); + } + + public void setEnableFallback(boolean state) { + if (DEBUG) Log.d(TAG, "setEnableFallback(" + state + ")"); + mEnableFallback = state; + } + + private void resetStatusInfo() { + mInstructions = null; + mShowingBatteryInfo = mUpdateMonitor.shouldShowBatteryInfo(); + mPluggedIn = mUpdateMonitor.isDevicePluggedIn(); + mBatteryLevel = mUpdateMonitor.getBatteryLevel(); + mNextAlarm = mLockPatternUtils.getNextAlarm(); + updateStatusLines(); + } + + private void updateStatusLines() { + if (mInstructions != null) { + // instructions only + mStatus1.setText(mInstructions); + if (TextUtils.isEmpty(mInstructions)) { + mStatus1.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } else { + mStatus1.setCompoundDrawablesWithIntrinsicBounds( + R.drawable.ic_lock_idle_lock, 0, 0, 0); + } + + mStatus1.setVisibility(View.VISIBLE); + mStatusSep.setVisibility(View.GONE); + mStatus2.setVisibility(View.GONE); + } else if (mShowingBatteryInfo && mNextAlarm == null) { + // battery only + if (mPluggedIn) { + if (mBatteryLevel >= 100) { + mStatus1.setText(getContext().getString(R.string.lockscreen_charged)); + } else { + mStatus1.setText(getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel)); + } + } else { + mStatus1.setText(getContext().getString(R.string.lockscreen_low_battery)); + } + mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_charging, 0, 0, 0); + + mStatus1.setVisibility(View.VISIBLE); + mStatusSep.setVisibility(View.GONE); + mStatus2.setVisibility(View.GONE); + + } else if (mNextAlarm != null && !mShowingBatteryInfo) { + // alarm only + mStatus1.setText(mNextAlarm); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_alarm, 0, 0, 0); + + mStatus1.setVisibility(View.VISIBLE); + mStatusSep.setVisibility(View.GONE); + mStatus2.setVisibility(View.GONE); + } else if (mNextAlarm != null && mShowingBatteryInfo) { + // both battery and next alarm + mStatus1.setText(mNextAlarm); + mStatusSep.setText("|"); + mStatus2.setText(getContext().getString( + R.string.lockscreen_battery_short, + Math.min(100, mBatteryLevel))); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_alarm, 0, 0, 0); + if (mPluggedIn) { + mStatus2.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_charging, 0, 0, 0); + } else { + mStatus2.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + + mStatus1.setVisibility(View.VISIBLE); + mStatusSep.setVisibility(View.VISIBLE); + mStatus2.setVisibility(View.VISIBLE); + } else { + // nothing specific to show; show general instructions + mStatus1.setText(R.string.lockscreen_pattern_instructions); + mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_lock, 0, 0, 0); + + mStatus1.setVisibility(View.VISIBLE); + mStatusSep.setVisibility(View.GONE); + mStatus2.setVisibility(View.GONE); + } + } + + + private void refreshTimeAndDateDisplay() { + mDate.setText(DateFormat.format(mDateFormatString, new Date())); + } + + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + // as long as the user is entering a pattern (i.e sending a touch + // event that was handled by this screen), keep poking the + // wake lock so that the screen will stay on. + final boolean result = super.dispatchTouchEvent(ev); + if (result && + ((SystemClock.elapsedRealtime() - mLastPokeTime) + > (UNLOCK_PATTERN_WAKE_INTERVAL_MS - 100))) { + mLastPokeTime = SystemClock.elapsedRealtime(); + } + return result; + } + + + // ---------- InfoCallback + + /** {@inheritDoc} */ + public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { + mShowingBatteryInfo = showBatteryInfo; + mPluggedIn = pluggedIn; + mBatteryLevel = batteryLevel; + updateStatusLines(); + } + + /** {@inheritDoc} */ + public void onTimeChanged() { + refreshTimeAndDateDisplay(); + } + + /** {@inheritDoc} */ + public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { + mCarrier.setText(LockScreen.getCarrierString(plmn, spn)); + } + + /** {@inheritDoc} */ + public void onRingerModeChanged(int state) { + // not currently used + } + + // ---------- SimStateCallback + + /** {@inheritDoc} */ + public void onSimStateChanged(IccCard.State simState) { + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (LockPatternKeyguardView.DEBUG_CONFIGURATION) { + Log.v(TAG, "***** PATTERN ATTACHED TO WINDOW"); + Log.v(TAG, "Cur orient=" + mCreationOrientation + + ", new config=" + getResources().getConfiguration()); + } + if (getResources().getConfiguration().orientation != mCreationOrientation) { + mCallback.recreateMe(getResources().getConfiguration()); + } + } + + + /** {@inheritDoc} */ + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (LockPatternKeyguardView.DEBUG_CONFIGURATION) { + Log.v(TAG, "***** PATTERN CONFIGURATION CHANGED"); + Log.v(TAG, "Cur orient=" + mCreationOrientation + + ", new config=" + getResources().getConfiguration()); + } + if (newConfig.orientation != mCreationOrientation) { + mCallback.recreateMe(newConfig); + } + } + + /** {@inheritDoc} */ + public void onKeyboardChange(boolean isKeyboardOpen) {} + + /** {@inheritDoc} */ + public boolean needsInput() { + return false; + } + + /** {@inheritDoc} */ + public void onPause() { + if (mCountdownTimer != null) { + mCountdownTimer.cancel(); + mCountdownTimer = null; + } + } + + /** {@inheritDoc} */ + public void onResume() { + // reset header + resetStatusInfo(); + + // reset lock pattern + mLockPatternView.enableInput(); + mLockPatternView.setEnabled(true); + mLockPatternView.clearPattern(); + + // show "forgot pattern?" button if we have an alternate authentication method + mForgotPatternButton.setVisibility(mCallback.doesFallbackUnlockScreenExist() + ? View.VISIBLE : View.INVISIBLE); + + // if the user is currently locked out, enforce it. + long deadline = mLockPatternUtils.getLockoutAttemptDeadline(); + if (deadline != 0) { + handleAttemptLockout(deadline); + } + + // the footer depends on how many total attempts the user has failed + if (mCallback.isVerifyUnlockOnly()) { + updateFooter(FooterMode.VerifyUnlocked); + } else if (mEnableFallback && + (mTotalFailedPatternAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) { + updateFooter(FooterMode.ForgotLockPattern); + } else { + updateFooter(FooterMode.Normal); + } + + refreshEmergencyButtonText(); + } + + /** {@inheritDoc} */ + public void cleanUp() { + mUpdateMonitor.removeCallback(this); + } + + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + if (hasWindowFocus) { + // when timeout dialog closes we want to update our state + onResume(); + } + } + + private class UnlockPatternListener + implements LockPatternView.OnPatternListener { + + public void onPatternStart() { + mLockPatternView.removeCallbacks(mCancelPatternRunnable); + } + + public void onPatternCleared() { + } + + public void onPatternCellAdded(List pattern) { + // To guard against accidental poking of the wakelock, look for + // the user actually trying to draw a pattern of some minimal length. + if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) { + mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS); + } else { + // Give just a little extra time if they hit one of the first few dots + mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS); + } + } + + public void onPatternDetected(List pattern) { + if (mLockPatternUtils.checkPattern(pattern)) { + mLockPatternView + .setDisplayMode(LockPatternView.DisplayMode.Correct); + mInstructions = ""; + updateStatusLines(); + mCallback.keyguardDone(true); + mCallback.reportSuccessfulUnlockAttempt(); + } else { + if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) { + mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS); + } + mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong); + if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) { + mTotalFailedPatternAttempts++; + mFailedPatternAttemptsSinceLastTimeout++; + mCallback.reportFailedUnlockAttempt(); + } + if (mFailedPatternAttemptsSinceLastTimeout >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) { + long deadline = mLockPatternUtils.setLockoutAttemptDeadline(); + handleAttemptLockout(deadline); + } else { + // TODO mUnlockIcon.setVisibility(View.VISIBLE); + mInstructions = getContext().getString(R.string.lockscreen_pattern_wrong); + updateStatusLines(); + mLockPatternView.postDelayed( + mCancelPatternRunnable, + PATTERN_CLEAR_TIMEOUT_MS); + } + } + } + } + + private void handleAttemptLockout(long elapsedRealtimeDeadline) { + mLockPatternView.clearPattern(); + mLockPatternView.setEnabled(false); + long elapsedRealtime = SystemClock.elapsedRealtime(); + mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) { + + @Override + public void onTick(long millisUntilFinished) { + int secondsRemaining = (int) (millisUntilFinished / 1000); + mInstructions = getContext().getString( + R.string.lockscreen_too_many_failed_attempts_countdown, + secondsRemaining); + updateStatusLines(); + } + + @Override + public void onFinish() { + mLockPatternView.setEnabled(true); + mInstructions = getContext().getString(R.string.lockscreen_pattern_instructions); + updateStatusLines(); + // TODO mUnlockIcon.setVisibility(View.VISIBLE); + mFailedPatternAttemptsSinceLastTimeout = 0; + if (mEnableFallback) { + updateFooter(FooterMode.ForgotLockPattern); + } else { + updateFooter(FooterMode.Normal); + } + } + }.start(); + } + + public void onPhoneStateChanged(String newState) { + refreshEmergencyButtonText(); + } +} diff --git a/policy/com/android/internal/policy/impl/PhoneLayoutInflater.java b/policy/com/android/internal/policy/impl/PhoneLayoutInflater.java new file mode 100644 index 0000000000000000000000000000000000000000..6bf4beb0ea574621979cd33dd7bb9852918a64ee --- /dev/null +++ b/policy/com/android/internal/policy/impl/PhoneLayoutInflater.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2006 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. + */ + +package com.android.internal.policy.impl; + +import java.util.Map; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.LayoutInflater; + +public class PhoneLayoutInflater extends LayoutInflater { + private static final String[] sClassPrefixList = { + "android.widget.", + "android.webkit." + }; + + /** + * Instead of instantiating directly, you should retrieve an instance + * through {@link Context#getSystemService} + * + * @param context The Context in which in which to find resources and other + * application-specific things. + * + * @see Context#getSystemService + */ + public PhoneLayoutInflater(Context context) { + super(context); + } + + protected PhoneLayoutInflater(LayoutInflater original, Context newContext) { + super(original, newContext); + } + + /** Override onCreateView to instantiate names that correspond to the + widgets known to the Widget factory. If we don't find a match, + call through to our super class. + */ + @Override protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException { + for (String prefix : sClassPrefixList) { + try { + View view = createView(name, prefix, attrs); + if (view != null) { + return view; + } + } catch (ClassNotFoundException e) { + // In this case we want to let the base class take a crack + // at it. + } + } + + return super.onCreateView(name, attrs); + } + + public LayoutInflater cloneInContext(Context newContext) { + return new PhoneLayoutInflater(this, newContext); + } +} + diff --git a/policy/com/android/internal/policy/impl/PhoneWindow.java b/policy/com/android/internal/policy/impl/PhoneWindow.java new file mode 100644 index 0000000000000000000000000000000000000000..0cb0efc2a094e45675856ba1fd87e5868e903495 --- /dev/null +++ b/policy/com/android/internal/policy/impl/PhoneWindow.java @@ -0,0 +1,2799 @@ +/* + * + * 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. + */ + +package com.android.internal.policy.impl; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; +import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; + +import com.android.internal.view.BaseSurfaceHolder; +import com.android.internal.view.RootViewSurfaceTaker; +import com.android.internal.view.menu.ContextMenuBuilder; +import com.android.internal.view.menu.MenuBuilder; +import com.android.internal.view.menu.MenuDialogHelper; +import com.android.internal.view.menu.MenuView; +import com.android.internal.view.menu.SubMenuBuilder; + +import android.app.KeyguardManager; +import android.app.SearchManager; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.media.AudioManager; +import android.net.Uri; +import android.os.Bundle; +import android.os.Message; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.telephony.TelephonyManager; +import android.util.AndroidRuntimeException; +import android.util.Config; +import android.util.EventLog; +import android.util.Log; +import android.util.SparseArray; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewManager; +import android.view.VolumePanel; +import android.view.Window; +import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.inputmethod.InputMethodManager; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; + +/** + * Android-specific Window. + *

    + * todo: need to pull the generic functionality out into a base class + * in android.widget. + */ +public class PhoneWindow extends Window implements MenuBuilder.Callback { + + private final static String TAG = "PhoneWindow"; + + private final static boolean SWEEP_OPEN_MENU = false; + + /** + * Simple callback used by the context menu and its submenus. The options + * menu submenus do not use this (their behavior is more complex). + */ + ContextMenuCallback mContextMenuCallback = new ContextMenuCallback(FEATURE_CONTEXT_MENU); + + // This is the top-level view of the window, containing the window decor. + private DecorView mDecor; + + // This is the view in which the window contents are placed. It is either + // mDecor itself, or a child of mDecor where the contents go. + private ViewGroup mContentParent; + + SurfaceHolder.Callback mTakeSurfaceCallback; + BaseSurfaceHolder mSurfaceHolder; + + private boolean mIsFloating; + + private LayoutInflater mLayoutInflater; + + private TextView mTitleView; + + private DrawableFeatureState[] mDrawables; + + private PanelFeatureState[] mPanels; + + /** + * The panel that is prepared or opened (the most recent one if there are + * multiple panels). Shortcuts will go to this panel. It gets set in + * {@link #preparePanel} and cleared in {@link #closePanel}. + */ + private PanelFeatureState mPreparedPanel; + + /** + * The keycode that is currently held down (as a modifier) for chording. If + * this is 0, there is no key held down. + */ + private int mPanelChordingKey; + private boolean mPanelMayLongPress; + + private ImageView mLeftIconView; + + private ImageView mRightIconView; + + private ProgressBar mCircularProgressBar; + + private ProgressBar mHorizontalProgressBar; + + private int mBackgroundResource = 0; + + private Drawable mBackgroundDrawable; + + private int mFrameResource = 0; + + private int mTextColor = 0; + + private CharSequence mTitle = null; + + private int mTitleColor = 0; + + private ContextMenuBuilder mContextMenu; + private MenuDialogHelper mContextMenuHelper; + + private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE; + private long mVolumeKeyUpTime; + + private KeyguardManager mKeyguardManager = null; + + private SearchManager mSearchManager = null; + + private TelephonyManager mTelephonyManager = null; + + public PhoneWindow(Context context) { + super(context); + mLayoutInflater = LayoutInflater.from(context); + } + + @Override + public final void setContainer(Window container) { + super.setContainer(container); + } + + @Override + public boolean requestFeature(int featureId) { + if (mContentParent != null) { + throw new AndroidRuntimeException("requestFeature() must be called before adding content"); + } + final int features = getFeatures(); + if ((features != DEFAULT_FEATURES) && (featureId == FEATURE_CUSTOM_TITLE)) { + + /* Another feature is enabled and the user is trying to enable the custom title feature */ + throw new AndroidRuntimeException("You cannot combine custom titles with other title features"); + } + if (((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) && (featureId != FEATURE_CUSTOM_TITLE)) { + + /* Custom title feature is enabled and the user is trying to enable another feature */ + throw new AndroidRuntimeException("You cannot combine custom titles with other title features"); + } + if (featureId == FEATURE_OPENGL) { + getAttributes().memoryType = WindowManager.LayoutParams.MEMORY_TYPE_GPU; + } + return super.requestFeature(featureId); + } + + @Override + public void setContentView(int layoutResID) { + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + mLayoutInflater.inflate(layoutResID, mContentParent); + final Callback cb = getCallback(); + if (cb != null) { + cb.onContentChanged(); + } + } + + @Override + public void setContentView(View view) { + setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); + } + + @Override + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + mContentParent.addView(view, params); + final Callback cb = getCallback(); + if (cb != null) { + cb.onContentChanged(); + } + } + + @Override + public void addContentView(View view, ViewGroup.LayoutParams params) { + if (mContentParent == null) { + installDecor(); + } + mContentParent.addView(view, params); + final Callback cb = getCallback(); + if (cb != null) { + cb.onContentChanged(); + } + } + + @Override + public View getCurrentFocus() { + return mDecor != null ? mDecor.findFocus() : null; + } + + @Override + public void takeSurface(SurfaceHolder.Callback callback) { + mTakeSurfaceCallback = callback; + } + + @Override + public boolean isFloating() { + return mIsFloating; + } + + /** + * Return a LayoutInflater instance that can be used to inflate XML view layout + * resources for use in this Window. + * + * @return LayoutInflater The shared LayoutInflater. + */ + @Override + public LayoutInflater getLayoutInflater() { + return mLayoutInflater; + } + + @Override + public void setTitle(CharSequence title) { + if (mTitleView != null) { + mTitleView.setText(title); + } + mTitle = title; + } + + @Override + public void setTitleColor(int textColor) { + if (mTitleView != null) { + mTitleView.setTextColor(textColor); + } + mTitleColor = textColor; + } + + /** + * Prepares the panel to either be opened or chorded. This creates the Menu + * instance for the panel and populates it via the Activity callbacks. + * + * @param st The panel state to prepare. + * @param event The event that triggered the preparing of the panel. + * @return Whether the panel was prepared. If the panel should not be shown, + * returns false. + */ + public final boolean preparePanel(PanelFeatureState st, KeyEvent event) { + // Already prepared (isPrepared will be reset to false later) + if (st.isPrepared) + return true; + + if ((mPreparedPanel != null) && (mPreparedPanel != st)) { + // Another Panel is prepared and possibly open, so close it + closePanel(mPreparedPanel, false); + } + + final Callback cb = getCallback(); + + if (cb != null) { + st.createdPanelView = cb.onCreatePanelView(st.featureId); + } + + if (st.createdPanelView == null) { + // Init the panel state's menu--return false if init failed + if (st.menu == null) { + if (!initializePanelMenu(st) || (st.menu == null)) { + return false; + } + // Call callback, and return if it doesn't want to display menu + if ((cb == null) || !cb.onCreatePanelMenu(st.featureId, st.menu)) { + // Ditch the menu created above + st.menu = null; + + return false; + } + } + + // Callback and return if the callback does not want to show the menu + if (!cb.onPreparePanel(st.featureId, st.createdPanelView, st.menu)) { + return false; + } + + // Set the proper keymap + KeyCharacterMap kmap = KeyCharacterMap.load(event != null ? event.getDeviceId() : 0); + st.qwertyMode = kmap.getKeyboardType() != KeyCharacterMap.NUMERIC; + st.menu.setQwertyMode(st.qwertyMode); + } + + // Set other state + st.isPrepared = true; + st.isHandled = false; + mPreparedPanel = st; + + return true; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false); + if ((st != null) && (st.menu != null)) { + final MenuBuilder menuBuilder = (MenuBuilder) st.menu; + + if (st.isOpen) { + // Freeze state + final Bundle state = new Bundle(); + menuBuilder.saveHierarchyState(state); + + // Remove the menu views since they need to be recreated + // according to the new configuration + clearMenuViews(st); + + // Re-open the same menu + reopenMenu(false); + + // Restore state + menuBuilder.restoreHierarchyState(state); + + } else { + // Clear menu views so on next menu opening, it will use + // the proper layout + clearMenuViews(st); + } + } + + } + + private static void clearMenuViews(PanelFeatureState st) { + + // This can be called on config changes, so we should make sure + // the views will be reconstructed based on the new orientation, etc. + + // Allow the callback to create a new panel view + st.createdPanelView = null; + + // Causes the decor view to be recreated + st.refreshDecorView = true; + + ((MenuBuilder) st.menu).clearMenuViews(); + } + + @Override + public final void openPanel(int featureId, KeyEvent event) { + openPanel(getPanelState(featureId, true), event); + } + + private void openPanel(PanelFeatureState st, KeyEvent event) { + // System.out.println("Open panel: isOpen=" + st.isOpen); + + // Already open, return + if (st.isOpen) { + return; + } + + Callback cb = getCallback(); + if ((cb != null) && (!cb.onMenuOpened(st.featureId, st.menu))) { + // Callback doesn't want the menu to open, reset any state + closePanel(st, true); + return; + } + + final WindowManager wm = getWindowManager(); + if (wm == null) { + return; + } + + // Prepare panel (should have been done before, but just in case) + if (!preparePanel(st, event)) { + return; + } + + if (st.decorView == null || st.refreshDecorView) { + if (st.decorView == null) { + // Initialize the panel decor, this will populate st.decorView + if (!initializePanelDecor(st) || (st.decorView == null)) + return; + } else if (st.refreshDecorView && (st.decorView.getChildCount() > 0)) { + // Decor needs refreshing, so remove its views + st.decorView.removeAllViews(); + } + + // This will populate st.shownPanelView + if (!initializePanelContent(st) || (st.shownPanelView == null)) { + return; + } + + ViewGroup.LayoutParams lp = st.shownPanelView.getLayoutParams(); + if (lp == null) { + lp = new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + } + + int backgroundResId; + if (lp.width == ViewGroup.LayoutParams.MATCH_PARENT) { + // If the contents is fill parent for the width, set the + // corresponding background + backgroundResId = st.fullBackground; + } else { + // Otherwise, set the normal panel background + backgroundResId = st.background; + } + st.decorView.setWindowBackground(getContext().getResources().getDrawable( + backgroundResId)); + + + st.decorView.addView(st.shownPanelView, lp); + + /* + * Give focus to the view, if it or one of its children does not + * already have it. + */ + if (!st.shownPanelView.hasFocus()) { + st.shownPanelView.requestFocus(); + } + } + + st.isOpen = true; + st.isHandled = false; + + WindowManager.LayoutParams lp = new WindowManager.LayoutParams( + WRAP_CONTENT, WRAP_CONTENT, + st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG, + WindowManager.LayoutParams.FLAG_DITHER + | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, + st.decorView.mDefaultOpacity); + + lp.gravity = st.gravity; + lp.windowAnimations = st.windowAnimations; + + wm.addView(st.decorView, lp); + // Log.v(TAG, "Adding main menu to window manager."); + } + + @Override + public final void closePanel(int featureId) { + if (featureId == FEATURE_CONTEXT_MENU) { + closeContextMenu(); + } else { + closePanel(getPanelState(featureId, true), true); + } + } + + /** + * Closes the given panel. + * + * @param st The panel to be closed. + * @param doCallback Whether to notify the callback that the panel was + * closed. If the panel is in the process of re-opening or + * opening another panel (e.g., menu opening a sub menu), the + * callback should not happen and this variable should be false. + * In addition, this method internally will only perform the + * callback if the panel is open. + */ + public final void closePanel(PanelFeatureState st, boolean doCallback) { + // System.out.println("Close panel: isOpen=" + st.isOpen); + final ViewManager wm = getWindowManager(); + if ((wm != null) && st.isOpen) { + if (st.decorView != null) { + wm.removeView(st.decorView); + // Log.v(TAG, "Removing main menu from window manager."); + } + + if (doCallback) { + callOnPanelClosed(st.featureId, st, null); + } + } + st.isPrepared = false; + st.isHandled = false; + st.isOpen = false; + + // This view is no longer shown, so null it out + st.shownPanelView = null; + + if (st.isInExpandedMode) { + // Next time the menu opens, it should not be in expanded mode, so + // force a refresh of the decor + st.refreshDecorView = true; + st.isInExpandedMode = false; + } + + if (mPreparedPanel == st) { + mPreparedPanel = null; + mPanelChordingKey = 0; + } + } + + @Override + public final void togglePanel(int featureId, KeyEvent event) { + PanelFeatureState st = getPanelState(featureId, true); + if (st.isOpen) { + closePanel(st, true); + } else { + openPanel(st, event); + } + } + + /** + * Called when the panel key is pushed down. + * @param featureId The feature ID of the relevant panel (defaults to FEATURE_OPTIONS_PANEL}. + * @param event The key event. + * @return Whether the key was handled. + */ + public final boolean onKeyDownPanel(int featureId, KeyEvent event) { + final int keyCode = event.getKeyCode(); + + if (event.getRepeatCount() == 0) { + // The panel key was pushed, so set the chording key + mPanelChordingKey = keyCode; + mPanelMayLongPress = false; + + PanelFeatureState st = getPanelState(featureId, true); + if (!st.isOpen) { + if (getContext().getResources().getConfiguration().keyboard + == Configuration.KEYBOARD_NOKEYS) { + mPanelMayLongPress = true; + } + return preparePanel(st, event); + } + + } else if (mPanelMayLongPress && mPanelChordingKey == keyCode + && (event.getFlags()&KeyEvent.FLAG_LONG_PRESS) != 0) { + // We have had a long press while in a state where this + // should be executed... do it! + mPanelChordingKey = 0; + mPanelMayLongPress = false; + InputMethodManager imm = (InputMethodManager) + getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm != null) { + mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } + + } + + return false; + } + + /** + * Called when the panel key is released. + * @param featureId The feature ID of the relevant panel (defaults to FEATURE_OPTIONS_PANEL}. + * @param event The key event. + */ + public final void onKeyUpPanel(int featureId, KeyEvent event) { + // The panel key was released, so clear the chording key + if (mPanelChordingKey != 0) { + mPanelChordingKey = 0; + mPanelMayLongPress = false; + + if (event.isCanceled()) { + return; + } + + boolean playSoundEffect = false; + PanelFeatureState st = getPanelState(featureId, true); + if (st.isOpen || st.isHandled) { + + // Play the sound effect if the user closed an open menu (and not if + // they just released a menu shortcut) + playSoundEffect = st.isOpen; + + // Close menu + closePanel(st, true); + + } else if (st.isPrepared) { + + // Write 'menu opened' to event log + EventLog.writeEvent(50001, 0); + + // Show menu + openPanel(st, event); + + playSoundEffect = true; + } + + if (playSoundEffect) { + AudioManager audioManager = (AudioManager) getContext().getSystemService( + Context.AUDIO_SERVICE); + if (audioManager != null) { + audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK); + } else { + Log.w(TAG, "Couldn't get audio manager"); + } + } + } + } + + @Override + public final void closeAllPanels() { + final ViewManager wm = getWindowManager(); + if (wm == null) { + return; + } + + final PanelFeatureState[] panels = mPanels; + final int N = panels != null ? panels.length : 0; + for (int i = 0; i < N; i++) { + final PanelFeatureState panel = panels[i]; + if (panel != null) { + closePanel(panel, true); + } + } + + closeContextMenu(); + } + + /** + * Closes the context menu. This notifies the menu logic of the close, along + * with dismissing it from the UI. + */ + private synchronized void closeContextMenu() { + if (mContextMenu != null) { + mContextMenu.close(); + dismissContextMenu(); + } + } + + /** + * Dismisses just the context menu UI. To close the context menu, use + * {@link #closeContextMenu()}. + */ + private synchronized void dismissContextMenu() { + mContextMenu = null; + + if (mContextMenuHelper != null) { + mContextMenuHelper.dismiss(); + mContextMenuHelper = null; + } + } + + @Override + public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) { + return performPanelShortcut(getPanelState(featureId, true), keyCode, event, flags); + } + + private boolean performPanelShortcut(PanelFeatureState st, int keyCode, KeyEvent event, + int flags) { + if (event.isSystem() || (st == null)) { + return false; + } + + boolean handled = false; + + // Only try to perform menu shortcuts if preparePanel returned true (possible false + // return value from application not wanting to show the menu). + if ((st.isPrepared || preparePanel(st, event)) && st.menu != null) { + // The menu is prepared now, perform the shortcut on it + handled = st.menu.performShortcut(keyCode, event, flags); + } + + if (handled) { + // Mark as handled + st.isHandled = true; + + if ((flags & Menu.FLAG_PERFORM_NO_CLOSE) == 0) { + closePanel(st, true); + } + } + + return handled; + } + + @Override + public boolean performPanelIdentifierAction(int featureId, int id, int flags) { + + PanelFeatureState st = getPanelState(featureId, true); + if (!preparePanel(st, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU))) { + return false; + } + if (st.menu == null) { + return false; + } + + boolean res = st.menu.performIdentifierAction(id, flags); + + closePanel(st, true); + + return res; + } + + public PanelFeatureState findMenuPanel(Menu menu) { + final PanelFeatureState[] panels = mPanels; + final int N = panels != null ? panels.length : 0; + for (int i = 0; i < N; i++) { + final PanelFeatureState panel = panels[i]; + if (panel != null && panel.menu == menu) { + return panel; + } + } + return null; + } + + public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { + final Callback cb = getCallback(); + if (cb != null) { + final PanelFeatureState panel = findMenuPanel(menu.getRootMenu()); + if (panel != null) { + return cb.onMenuItemSelected(panel.featureId, item); + } + } + return false; + } + + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + final PanelFeatureState panel = findMenuPanel(menu); + if (panel != null) { + // Close the panel and only do the callback if the menu is being + // closed + // completely, not if opening a sub menu + closePanel(panel, allMenusAreClosing); + } + } + + public void onCloseSubMenu(SubMenuBuilder subMenu) { + final Menu parentMenu = subMenu.getRootMenu(); + final PanelFeatureState panel = findMenuPanel(parentMenu); + + // Callback + if (panel != null) { + callOnPanelClosed(panel.featureId, panel, parentMenu); + closePanel(panel, true); + } + } + + public boolean onSubMenuSelected(final SubMenuBuilder subMenu) { + if (!subMenu.hasVisibleItems()) { + return true; + } + + // The window manager will give us a valid window token + new MenuDialogHelper(subMenu).show(null); + + return true; + } + + public void onMenuModeChange(MenuBuilder menu) { + reopenMenu(true); + } + + private void reopenMenu(boolean toggleMenuMode) { + PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); + + // Save the future expanded mode state since closePanel will reset it + boolean newExpandedMode = toggleMenuMode ? !st.isInExpandedMode : st.isInExpandedMode; + + st.refreshDecorView = true; + closePanel(st, false); + + // Set the expanded mode state + st.isInExpandedMode = newExpandedMode; + + openPanel(st, null); + } + + /** + * Initializes the menu associated with the given panel feature state. You + * must at the very least set PanelFeatureState.menu to the Menu to be + * associated with the given panel state. The default implementation creates + * a new menu for the panel state. + * + * @param st The panel whose menu is being initialized. + * @return Whether the initialization was successful. + */ + protected boolean initializePanelMenu(final PanelFeatureState st) { + final MenuBuilder menu = new MenuBuilder(getContext()); + + menu.setCallback(this); + st.setMenu(menu); + + return true; + } + + /** + * Perform initial setup of a panel. This should at the very least set the + * style information in the PanelFeatureState and must set + * PanelFeatureState.decor to the panel's window decor view. + * + * @param st The panel being initialized. + */ + protected boolean initializePanelDecor(PanelFeatureState st) { + st.decorView = new DecorView(getContext(), st.featureId); + st.gravity = Gravity.CENTER | Gravity.BOTTOM; + st.setStyle(getContext()); + + return true; + } + + /** + * Initializes the panel associated with the panel feature state. You must + * at the very least set PanelFeatureState.panel to the View implementing + * its contents. The default implementation gets the panel from the menu. + * + * @param st The panel state being initialized. + * @return Whether the initialization was successful. + */ + protected boolean initializePanelContent(PanelFeatureState st) { + + if (st.createdPanelView != null) { + st.shownPanelView = st.createdPanelView; + return true; + } + + final MenuBuilder menu = (MenuBuilder)st.menu; + if (menu == null) { + return false; + } + + st.shownPanelView = menu.getMenuView((st.isInExpandedMode) ? MenuBuilder.TYPE_EXPANDED + : MenuBuilder.TYPE_ICON, st.decorView); + + if (st.shownPanelView != null) { + // Use the menu View's default animations if it has any + final int defaultAnimations = ((MenuView) st.shownPanelView).getWindowAnimations(); + if (defaultAnimations != 0) { + st.windowAnimations = defaultAnimations; + } + return true; + } else { + return false; + } + } + + @Override + public boolean performContextMenuIdentifierAction(int id, int flags) { + return (mContextMenu != null) ? mContextMenu.performIdentifierAction(id, flags) : false; + } + + @Override + public final void setBackgroundDrawable(Drawable drawable) { + if (drawable != mBackgroundDrawable || mBackgroundResource != 0) { + mBackgroundResource = 0; + mBackgroundDrawable = drawable; + if (mDecor != null) { + mDecor.setWindowBackground(drawable); + } + } + } + + @Override + public final void setFeatureDrawableResource(int featureId, int resId) { + if (resId != 0) { + DrawableFeatureState st = getDrawableState(featureId, true); + if (st.resid != resId) { + st.resid = resId; + st.uri = null; + st.local = getContext().getResources().getDrawable(resId); + updateDrawable(featureId, st, false); + } + } else { + setFeatureDrawable(featureId, null); + } + } + + @Override + public final void setFeatureDrawableUri(int featureId, Uri uri) { + if (uri != null) { + DrawableFeatureState st = getDrawableState(featureId, true); + if (st.uri == null || !st.uri.equals(uri)) { + st.resid = 0; + st.uri = uri; + st.local = loadImageURI(uri); + updateDrawable(featureId, st, false); + } + } else { + setFeatureDrawable(featureId, null); + } + } + + @Override + public final void setFeatureDrawable(int featureId, Drawable drawable) { + DrawableFeatureState st = getDrawableState(featureId, true); + st.resid = 0; + st.uri = null; + if (st.local != drawable) { + st.local = drawable; + updateDrawable(featureId, st, false); + } + } + + @Override + public void setFeatureDrawableAlpha(int featureId, int alpha) { + DrawableFeatureState st = getDrawableState(featureId, true); + if (st.alpha != alpha) { + st.alpha = alpha; + updateDrawable(featureId, st, false); + } + } + + protected final void setFeatureDefaultDrawable(int featureId, Drawable drawable) { + DrawableFeatureState st = getDrawableState(featureId, true); + if (st.def != drawable) { + st.def = drawable; + updateDrawable(featureId, st, false); + } + } + + @Override + public final void setFeatureInt(int featureId, int value) { + // XXX Should do more management (as with drawable features) to + // deal with interactions between multiple window policies. + updateInt(featureId, value, false); + } + + /** + * Update the state of a drawable feature. This should be called, for every + * drawable feature supported, as part of onActive(), to make sure that the + * contents of a containing window is properly updated. + * + * @see #onActive + * @param featureId The desired drawable feature to change. + * @param fromActive Always true when called from onActive(). + */ + protected final void updateDrawable(int featureId, boolean fromActive) { + final DrawableFeatureState st = getDrawableState(featureId, false); + if (st != null) { + updateDrawable(featureId, st, fromActive); + } + } + + /** + * Called when a Drawable feature changes, for the window to update its + * graphics. + * + * @param featureId The feature being changed. + * @param drawable The new Drawable to show, or null if none. + * @param alpha The new alpha blending of the Drawable. + */ + protected void onDrawableChanged(int featureId, Drawable drawable, int alpha) { + ImageView view; + if (featureId == FEATURE_LEFT_ICON) { + view = getLeftIconView(); + } else if (featureId == FEATURE_RIGHT_ICON) { + view = getRightIconView(); + } else { + return; + } + + if (drawable != null) { + drawable.setAlpha(alpha); + view.setImageDrawable(drawable); + view.setVisibility(View.VISIBLE); + } else { + view.setVisibility(View.GONE); + } + } + + /** + * Called when an int feature changes, for the window to update its + * graphics. + * + * @param featureId The feature being changed. + * @param value The new integer value. + */ + protected void onIntChanged(int featureId, int value) { + if (featureId == FEATURE_PROGRESS || featureId == FEATURE_INDETERMINATE_PROGRESS) { + updateProgressBars(value); + } else if (featureId == FEATURE_CUSTOM_TITLE) { + FrameLayout titleContainer = (FrameLayout) findViewById(com.android.internal.R.id.title_container); + if (titleContainer != null) { + mLayoutInflater.inflate(value, titleContainer); + } + } + } + + /** + * Updates the progress bars that are shown in the title bar. + * + * @param value Can be one of {@link Window#PROGRESS_VISIBILITY_ON}, + * {@link Window#PROGRESS_VISIBILITY_OFF}, + * {@link Window#PROGRESS_INDETERMINATE_ON}, + * {@link Window#PROGRESS_INDETERMINATE_OFF}, or a value + * starting at {@link Window#PROGRESS_START} through + * {@link Window#PROGRESS_END} for setting the default + * progress (if {@link Window#PROGRESS_END} is given, + * the progress bar widgets in the title will be hidden after an + * animation), a value between + * {@link Window#PROGRESS_SECONDARY_START} - + * {@link Window#PROGRESS_SECONDARY_END} for the + * secondary progress (if + * {@link Window#PROGRESS_SECONDARY_END} is given, the + * progress bar widgets will still be shown with the secondary + * progress bar will be completely filled in.) + */ + private void updateProgressBars(int value) { + ProgressBar circularProgressBar = getCircularProgressBar(true); + ProgressBar horizontalProgressBar = getHorizontalProgressBar(true); + + final int features = getLocalFeatures(); + if (value == PROGRESS_VISIBILITY_ON) { + if ((features & (1 << FEATURE_PROGRESS)) != 0) { + int level = horizontalProgressBar.getProgress(); + int visibility = (horizontalProgressBar.isIndeterminate() || level < 10000) ? + View.VISIBLE : View.INVISIBLE; + horizontalProgressBar.setVisibility(visibility); + } + if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) { + circularProgressBar.setVisibility(View.VISIBLE); + } + } else if (value == PROGRESS_VISIBILITY_OFF) { + if ((features & (1 << FEATURE_PROGRESS)) != 0) { + horizontalProgressBar.setVisibility(View.GONE); + } + if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) { + circularProgressBar.setVisibility(View.GONE); + } + } else if (value == PROGRESS_INDETERMINATE_ON) { + horizontalProgressBar.setIndeterminate(true); + } else if (value == PROGRESS_INDETERMINATE_OFF) { + horizontalProgressBar.setIndeterminate(false); + } else if (PROGRESS_START <= value && value <= PROGRESS_END) { + // We want to set the progress value before testing for visibility + // so that when the progress bar becomes visible again, it has the + // correct level. + horizontalProgressBar.setProgress(value - PROGRESS_START); + + if (value < PROGRESS_END) { + showProgressBars(horizontalProgressBar, circularProgressBar); + } else { + hideProgressBars(horizontalProgressBar, circularProgressBar); + } + } else if (PROGRESS_SECONDARY_START <= value && value <= PROGRESS_SECONDARY_END) { + horizontalProgressBar.setSecondaryProgress(value - PROGRESS_SECONDARY_START); + + showProgressBars(horizontalProgressBar, circularProgressBar); + } + + } + + private void showProgressBars(ProgressBar horizontalProgressBar, ProgressBar spinnyProgressBar) { + final int features = getLocalFeatures(); + if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0 && + spinnyProgressBar.getVisibility() == View.INVISIBLE) { + spinnyProgressBar.setVisibility(View.VISIBLE); + } + // Only show the progress bars if the primary progress is not complete + if ((features & (1 << FEATURE_PROGRESS)) != 0 && + horizontalProgressBar.getProgress() < 10000) { + horizontalProgressBar.setVisibility(View.VISIBLE); + } + } + + private void hideProgressBars(ProgressBar horizontalProgressBar, ProgressBar spinnyProgressBar) { + final int features = getLocalFeatures(); + Animation anim = AnimationUtils.loadAnimation(getContext(), com.android.internal.R.anim.fade_out); + anim.setDuration(1000); + if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0 && + spinnyProgressBar.getVisibility() == View.VISIBLE) { + spinnyProgressBar.startAnimation(anim); + spinnyProgressBar.setVisibility(View.INVISIBLE); + } + if ((features & (1 << FEATURE_PROGRESS)) != 0 && + horizontalProgressBar.getVisibility() == View.VISIBLE) { + horizontalProgressBar.startAnimation(anim); + horizontalProgressBar.setVisibility(View.INVISIBLE); + } + } + + /** + * Request that key events come to this activity. Use this if your activity + * has no views with focus, but the activity still wants a chance to process + * key events. + */ + @Override + public void takeKeyEvents(boolean get) { + mDecor.setFocusable(get); + } + + @Override + public boolean superDispatchKeyEvent(KeyEvent event) { + return mDecor.superDispatchKeyEvent(event); + } + + @Override + public boolean superDispatchTouchEvent(MotionEvent event) { + return mDecor.superDispatchTouchEvent(event); + } + + @Override + public boolean superDispatchTrackballEvent(MotionEvent event) { + return mDecor.superDispatchTrackballEvent(event); + } + + /** + * A key was pressed down and not handled by anything else in the window. + * + * @see #onKeyUp + * @see android.view.KeyEvent + */ + protected boolean onKeyDown(int featureId, int keyCode, KeyEvent event) { + final KeyEvent.DispatcherState dispatcher = + mDecor != null ? mDecor.getKeyDispatcherState() : null; + //Log.i(TAG, "Key down: repeat=" + event.getRepeatCount() + // + " flags=0x" + Integer.toHexString(event.getFlags())); + + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_DOWN: { + AudioManager audioManager = (AudioManager) getContext().getSystemService( + Context.AUDIO_SERVICE); + if (audioManager != null) { + /* + * Adjust the volume in on key down since it is more + * responsive to the user. + */ + audioManager.adjustSuggestedStreamVolume( + keyCode == KeyEvent.KEYCODE_VOLUME_UP + ? AudioManager.ADJUST_RAISE + : AudioManager.ADJUST_LOWER, + mVolumeControlStreamType, + AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE); + } + return true; + } + + + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + /* Suppress PLAYPAUSE toggle when phone is ringing or in-call + * to avoid music playback */ + if (mTelephonyManager == null) { + mTelephonyManager = (TelephonyManager) getContext().getSystemService( + Context.TELEPHONY_SERVICE); + } + if (mTelephonyManager != null && + mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { + return true; // suppress key event + } + case KeyEvent.KEYCODE_MUTE: + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { + Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); + intent.putExtra(Intent.EXTRA_KEY_EVENT, event); + getContext().sendOrderedBroadcast(intent, null); + return true; + } + + case KeyEvent.KEYCODE_CAMERA: { + if (getKeyguardManager().inKeyguardRestrictedInputMode() + || dispatcher == null) { + break; + } + if (event.getRepeatCount() == 0) { + dispatcher.startTracking(event, this); + } else if (event.isLongPress() && dispatcher.isTracking(event)) { + dispatcher.performedLongPress(event); + mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + sendCloseSystemWindows(); + // Broadcast an intent that the Camera button was longpressed + Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); + intent.putExtra(Intent.EXTRA_KEY_EVENT, event); + getContext().sendOrderedBroadcast(intent, null); + } + return true; + } + + case KeyEvent.KEYCODE_MENU: { + onKeyDownPanel((featureId < 0) ? FEATURE_OPTIONS_PANEL : featureId, event); + return true; + } + + case KeyEvent.KEYCODE_BACK: { + if (event.getRepeatCount() > 0) break; + if (featureId < 0) break; + // Currently don't do anything with long press. + dispatcher.startTracking(event, this); + return true; + } + + case KeyEvent.KEYCODE_CALL: { + if (getKeyguardManager().inKeyguardRestrictedInputMode() + || dispatcher == null) { + break; + } + if (event.getRepeatCount() == 0) { + dispatcher.startTracking(event, this); + } else if (event.isLongPress() && dispatcher.isTracking(event)) { + dispatcher.performedLongPress(event); + mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + // launch the VoiceDialer + Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + try { + sendCloseSystemWindows(); + getContext().startActivity(intent); + } catch (ActivityNotFoundException e) { + startCallActivity(); + } + } + return true; + } + + case KeyEvent.KEYCODE_SEARCH: { + if (getKeyguardManager().inKeyguardRestrictedInputMode() + || dispatcher == null) { + break; + } + if (event.getRepeatCount() == 0) { + dispatcher.startTracking(event, this); + } else if (event.isLongPress() && dispatcher.isTracking(event)) { + Configuration config = getContext().getResources().getConfiguration(); + if (config.keyboard == Configuration.KEYBOARD_NOKEYS + || config.hardKeyboardHidden + == Configuration.HARDKEYBOARDHIDDEN_YES) { + // launch the search activity + Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + try { + mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + sendCloseSystemWindows(); + getSearchManager().stopSearch(); + getContext().startActivity(intent); + // Only clear this if we successfully start the + // activity; otherwise we will allow the normal short + // press action to be performed. + dispatcher.performedLongPress(event); + return true; + } catch (ActivityNotFoundException e) { + // Ignore + } + } + } + break; + } + } + + return false; + } + + /** + * @return A handle to the keyguard manager. + */ + private KeyguardManager getKeyguardManager() { + if (mKeyguardManager == null) { + mKeyguardManager = (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE); + } + return mKeyguardManager; + } + + /** + * @return A handle to the search manager. + */ + private SearchManager getSearchManager() { + if (mSearchManager == null) { + mSearchManager = (SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE); + } + return mSearchManager; + } + + /** + * A key was released and not handled by anything else in the window. + * + * @see #onKeyDown + * @see android.view.KeyEvent + */ + protected boolean onKeyUp(int featureId, int keyCode, KeyEvent event) { + final KeyEvent.DispatcherState dispatcher = + mDecor != null ? mDecor.getKeyDispatcherState() : null; + if (dispatcher != null) { + dispatcher.handleUpEvent(event); + } + //Log.i(TAG, "Key up: repeat=" + event.getRepeatCount() + // + " flags=0x" + Integer.toHexString(event.getFlags())); + + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_DOWN: { + AudioManager audioManager = (AudioManager) getContext().getSystemService( + Context.AUDIO_SERVICE); + if (audioManager != null) { + /* + * Play a sound. This is done on key up since we don't want the + * sound to play when a user holds down volume down to mute. + */ + audioManager.adjustSuggestedStreamVolume( + AudioManager.ADJUST_SAME, + mVolumeControlStreamType, + AudioManager.FLAG_PLAY_SOUND); + mVolumeKeyUpTime = SystemClock.uptimeMillis(); + } + return true; + } + + case KeyEvent.KEYCODE_MENU: { + onKeyUpPanel(featureId < 0 ? FEATURE_OPTIONS_PANEL : featureId, + event); + return true; + } + + case KeyEvent.KEYCODE_BACK: { + if (featureId < 0) break; + if (event.isTracking() && !event.isCanceled()) { + if (featureId == FEATURE_OPTIONS_PANEL) { + PanelFeatureState st = getPanelState(featureId, false); + if (st != null && st.isInExpandedMode) { + // If the user is in an expanded menu and hits back, it + // should go back to the icon menu + reopenMenu(true); + return true; + } + } + closePanel(featureId); + return true; + } + break; + } + + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { + Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); + intent.putExtra(Intent.EXTRA_KEY_EVENT, event); + getContext().sendOrderedBroadcast(intent, null); + return true; + } + + case KeyEvent.KEYCODE_CAMERA: { + if (getKeyguardManager().inKeyguardRestrictedInputMode()) { + break; + } + if (event.isTracking() && !event.isCanceled()) { + // Add short press behavior here if desired + } + return true; + } + + case KeyEvent.KEYCODE_CALL: { + if (getKeyguardManager().inKeyguardRestrictedInputMode()) { + break; + } + if (event.isTracking() && !event.isCanceled()) { + startCallActivity(); + } + return true; + } + + case KeyEvent.KEYCODE_SEARCH: { + /* + * Do this in onKeyUp since the Search key is also used for + * chording quick launch shortcuts. + */ + if (getKeyguardManager().inKeyguardRestrictedInputMode()) { + break; + } + if (event.isTracking() && !event.isCanceled()) { + launchDefaultSearch(); + } + return true; + } + } + + return false; + } + + private void startCallActivity() { + sendCloseSystemWindows(); + Intent intent = new Intent(Intent.ACTION_CALL_BUTTON); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + getContext().startActivity(intent); + } + + @Override + protected void onActive() { + } + + @Override + public final View getDecorView() { + if (mDecor == null) { + installDecor(); + } + return mDecor; + } + + @Override + public final View peekDecorView() { + return mDecor; + } + + static private final String FOCUSED_ID_TAG = "android:focusedViewId"; + static private final String VIEWS_TAG = "android:views"; + static private final String PANELS_TAG = "android:Panels"; + + /** {@inheritDoc} */ + @Override + public Bundle saveHierarchyState() { + Bundle outState = new Bundle(); + if (mContentParent == null) { + return outState; + } + + SparseArray states = new SparseArray(); + mContentParent.saveHierarchyState(states); + outState.putSparseParcelableArray(VIEWS_TAG, states); + + // save the focused view id + View focusedView = mContentParent.findFocus(); + if (focusedView != null) { + if (focusedView.getId() != View.NO_ID) { + outState.putInt(FOCUSED_ID_TAG, focusedView.getId()); + } else { + if (Config.LOGD) { + Log.d(TAG, "couldn't save which view has focus because the focused view " + + focusedView + " has no id."); + } + } + } + + // save the panels + SparseArray panelStates = new SparseArray(); + savePanelState(panelStates); + if (panelStates.size() > 0) { + outState.putSparseParcelableArray(PANELS_TAG, panelStates); + } + + return outState; + } + + /** {@inheritDoc} */ + @Override + public void restoreHierarchyState(Bundle savedInstanceState) { + if (mContentParent == null) { + return; + } + + SparseArray savedStates + = savedInstanceState.getSparseParcelableArray(VIEWS_TAG); + if (savedStates != null) { + mContentParent.restoreHierarchyState(savedStates); + } + + // restore the focused view + int focusedViewId = savedInstanceState.getInt(FOCUSED_ID_TAG, View.NO_ID); + if (focusedViewId != View.NO_ID) { + View needsFocus = mContentParent.findViewById(focusedViewId); + if (needsFocus != null) { + needsFocus.requestFocus(); + } else { + Log.w(TAG, + "Previously focused view reported id " + focusedViewId + + " during save, but can't be found during restore."); + } + } + + // restore the panels + SparseArray panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG); + if (panelStates != null) { + restorePanelState(panelStates); + } + } + + /** + * Invoked when the panels should freeze their state. + * + * @param icicles Save state into this. This is usually indexed by the + * featureId. This will be given to {@link #restorePanelState} in the + * future. + */ + private void savePanelState(SparseArray icicles) { + PanelFeatureState[] panels = mPanels; + if (panels == null) { + return; + } + + for (int curFeatureId = panels.length - 1; curFeatureId >= 0; curFeatureId--) { + if (panels[curFeatureId] != null) { + icicles.put(curFeatureId, panels[curFeatureId].onSaveInstanceState()); + } + } + } + + /** + * Invoked when the panels should thaw their state from a previously frozen state. + * + * @param icicles The state saved by {@link #savePanelState} that needs to be thawed. + */ + private void restorePanelState(SparseArray icicles) { + PanelFeatureState st; + for (int curFeatureId = icicles.size() - 1; curFeatureId >= 0; curFeatureId--) { + st = getPanelState(curFeatureId, false /* required */); + if (st == null) { + // The panel must not have been required, and is currently not around, skip it + continue; + } + + st.onRestoreInstanceState(icicles.get(curFeatureId)); + } + + /* + * Implementation note: call openPanelsAfterRestore later to actually open the + * restored panels. + */ + } + + /** + * Opens the panels that have had their state restored. This should be + * called sometime after {@link #restorePanelState} when it is safe to add + * to the window manager. + */ + private void openPanelsAfterRestore() { + PanelFeatureState[] panels = mPanels; + + if (panels == null) { + return; + } + + PanelFeatureState st; + for (int i = panels.length - 1; i >= 0; i--) { + st = panels[i]; + // We restore the panel if it was last open; we skip it if it + // now is open, to avoid a race condition if the user immediately + // opens it when we are resuming. + if ((st != null) && !st.isOpen && st.wasLastOpen) { + st.isInExpandedMode = st.wasLastExpanded; + openPanel(st, null); + } + } + } + + private final class DecorView extends FrameLayout implements RootViewSurfaceTaker { + /* package */int mDefaultOpacity = PixelFormat.OPAQUE; + + /** The feature ID of the panel, or -1 if this is the application's DecorView */ + private final int mFeatureId; + + private final Rect mDrawingBounds = new Rect(); + + private final Rect mBackgroundPadding = new Rect(); + + private final Rect mFramePadding = new Rect(); + + private final Rect mFrameOffsets = new Rect(); + + private boolean mChanging; + + private Drawable mMenuBackground; + private boolean mWatchingForMenu; + private int mDownY; + + public DecorView(Context context, int featureId) { + super(context); + mFeatureId = featureId; + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + final int keyCode = event.getKeyCode(); + final boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN; + + /* + * If the user hits another key within the play sound delay, then + * cancel the sound + */ + if (keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_UP + && mVolumeKeyUpTime + VolumePanel.PLAY_SOUND_DELAY + > SystemClock.uptimeMillis()) { + /* + * The user has hit another key during the delay (e.g., 300ms) + * since the last volume key up, so cancel any sounds. + */ + AudioManager audioManager = (AudioManager) getContext().getSystemService( + Context.AUDIO_SERVICE); + if (audioManager != null) { + audioManager.adjustSuggestedStreamVolume(AudioManager.ADJUST_SAME, + mVolumeControlStreamType, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); + } + } + + if (isDown && (event.getRepeatCount() == 0)) { + // First handle chording of panel key: if a panel key is held + // but not released, try to execute a shortcut in it. + if ((mPanelChordingKey > 0) && (mPanelChordingKey != keyCode)) { + // Perform the shortcut (mPreparedPanel can be null since + // global shortcuts (such as search) don't rely on a + // prepared panel or menu). + boolean handled = performPanelShortcut(mPreparedPanel, keyCode, event, + Menu.FLAG_PERFORM_NO_CLOSE); + + if (!handled) { + /* + * If not handled, then pass it to the view hierarchy + * and anyone else that may be interested. + */ + handled = dispatchKeyShortcutEvent(event); + + if (handled && mPreparedPanel != null) { + mPreparedPanel.isHandled = true; + } + } + + if (handled) { + return true; + } + } + + // If a panel is open, perform a shortcut on it without the + // chorded panel key + if ((mPreparedPanel != null) && mPreparedPanel.isOpen) { + if (performPanelShortcut(mPreparedPanel, keyCode, event, 0)) { + return true; + } + } + } + + final Callback cb = getCallback(); + final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event) + : super.dispatchKeyEvent(event); + if (handled) { + return true; + } + return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event) + : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + final Callback cb = getCallback(); + return cb != null && mFeatureId < 0 ? cb.dispatchTouchEvent(ev) : super + .dispatchTouchEvent(ev); + } + + @Override + public boolean dispatchTrackballEvent(MotionEvent ev) { + final Callback cb = getCallback(); + return cb != null && mFeatureId < 0 ? cb.dispatchTrackballEvent(ev) : super + .dispatchTrackballEvent(ev); + } + + public boolean superDispatchKeyEvent(KeyEvent event) { + return super.dispatchKeyEvent(event); + } + + public boolean superDispatchTouchEvent(MotionEvent event) { + return super.dispatchTouchEvent(event); + } + + public boolean superDispatchTrackballEvent(MotionEvent event) { + return super.dispatchTrackballEvent(event); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return onInterceptTouchEvent(event); + } + + private boolean isOutOfBounds(int x, int y) { + return x < -5 || y < -5 || x > (getWidth() + 5) + || y > (getHeight() + 5); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + int action = event.getAction(); + if (mFeatureId >= 0) { + if (action == MotionEvent.ACTION_DOWN) { + int x = (int)event.getX(); + int y = (int)event.getY(); + if (isOutOfBounds(x, y)) { + closePanel(mFeatureId); + return true; + } + } + } + + if (!SWEEP_OPEN_MENU) { + return false; + } + + if (mFeatureId >= 0) { + if (action == MotionEvent.ACTION_DOWN) { + Log.i(TAG, "Watchiing!"); + mWatchingForMenu = true; + mDownY = (int) event.getY(); + return false; + } + + if (!mWatchingForMenu) { + return false; + } + + int y = (int)event.getY(); + if (action == MotionEvent.ACTION_MOVE) { + if (y > (mDownY+30)) { + Log.i(TAG, "Closing!"); + closePanel(mFeatureId); + mWatchingForMenu = false; + return true; + } + } else if (action == MotionEvent.ACTION_UP) { + mWatchingForMenu = false; + } + + return false; + } + + //Log.i(TAG, "Intercept: action=" + action + " y=" + event.getY() + // + " (in " + getHeight() + ")"); + + if (action == MotionEvent.ACTION_DOWN) { + int y = (int)event.getY(); + if (y >= (getHeight()-5) && !hasChildren()) { + Log.i(TAG, "Watchiing!"); + mWatchingForMenu = true; + } + return false; + } + + if (!mWatchingForMenu) { + return false; + } + + int y = (int)event.getY(); + if (action == MotionEvent.ACTION_MOVE) { + if (y < (getHeight()-30)) { + Log.i(TAG, "Opening!"); + openPanel(FEATURE_OPTIONS_PANEL, new KeyEvent( + KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU)); + mWatchingForMenu = false; + return true; + } + } else if (action == MotionEvent.ACTION_UP) { + mWatchingForMenu = false; + } + + return false; + } + + @Override + public void sendAccessibilityEvent(int eventType) { + if (!AccessibilityManager.getInstance(mContext).isEnabled()) { + return; + } + + // if we are showing a feature that should be announced and one child + // make this child the event source since this is the feature itself + // otherwise the callback will take over and announce its client + if ((mFeatureId == FEATURE_OPTIONS_PANEL || + mFeatureId == FEATURE_CONTEXT_MENU || + mFeatureId == FEATURE_PROGRESS || + mFeatureId == FEATURE_INDETERMINATE_PROGRESS) + && getChildCount() == 1) { + getChildAt(0).sendAccessibilityEvent(eventType); + } else { + super.sendAccessibilityEvent(eventType); + } + } + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + final Callback cb = getCallback(); + if (cb != null) { + if (cb.dispatchPopulateAccessibilityEvent(event)) { + return true; + } + } + return super.dispatchPopulateAccessibilityEvent(event); + } + + @Override + protected boolean setFrame(int l, int t, int r, int b) { + boolean changed = super.setFrame(l, t, r, b); + if (changed) { + final Rect drawingBounds = mDrawingBounds; + getDrawingRect(drawingBounds); + + Drawable fg = getForeground(); + if (fg != null) { + final Rect frameOffsets = mFrameOffsets; + drawingBounds.left += frameOffsets.left; + drawingBounds.top += frameOffsets.top; + drawingBounds.right -= frameOffsets.right; + drawingBounds.bottom -= frameOffsets.bottom; + fg.setBounds(drawingBounds); + final Rect framePadding = mFramePadding; + drawingBounds.left += framePadding.left - frameOffsets.left; + drawingBounds.top += framePadding.top - frameOffsets.top; + drawingBounds.right -= framePadding.right - frameOffsets.right; + drawingBounds.bottom -= framePadding.bottom - frameOffsets.bottom; + } + + Drawable bg = getBackground(); + if (bg != null) { + bg.setBounds(drawingBounds); + } + + if (SWEEP_OPEN_MENU) { + if (mMenuBackground == null && mFeatureId < 0 + && getAttributes().height + == WindowManager.LayoutParams.MATCH_PARENT) { + mMenuBackground = getContext().getResources().getDrawable( + com.android.internal.R.drawable.menu_background); + } + if (mMenuBackground != null) { + mMenuBackground.setBounds(drawingBounds.left, + drawingBounds.bottom-6, drawingBounds.right, + drawingBounds.bottom+20); + } + } + } + return changed; + } + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + + if (mMenuBackground != null) { + mMenuBackground.draw(canvas); + } + } + + + @Override + public boolean showContextMenuForChild(View originalView) { + // Reuse the context menu builder + if (mContextMenu == null) { + mContextMenu = new ContextMenuBuilder(getContext()); + mContextMenu.setCallback(mContextMenuCallback); + } else { + mContextMenu.clearAll(); + } + + mContextMenuHelper = mContextMenu.show(originalView, originalView.getWindowToken()); + return mContextMenuHelper != null; + } + + public void startChanging() { + mChanging = true; + } + + public void finishChanging() { + mChanging = false; + drawableChanged(); + } + + public void setWindowBackground(Drawable drawable) { + if (getBackground() != drawable) { + setBackgroundDrawable(drawable); + if (drawable != null) { + drawable.getPadding(mBackgroundPadding); + } else { + mBackgroundPadding.setEmpty(); + } + drawableChanged(); + } + } + + public void setWindowFrame(Drawable drawable) { + if (getForeground() != drawable) { + setForeground(drawable); + if (drawable != null) { + drawable.getPadding(mFramePadding); + } else { + mFramePadding.setEmpty(); + } + drawableChanged(); + } + } + + @Override + protected boolean fitSystemWindows(Rect insets) { + mFrameOffsets.set(insets); + if (getForeground() != null) { + drawableChanged(); + } + return super.fitSystemWindows(insets); + } + + private void drawableChanged() { + if (mChanging) { + return; + } + + setPadding(mFramePadding.left + mBackgroundPadding.left, mFramePadding.top + + mBackgroundPadding.top, mFramePadding.right + mBackgroundPadding.right, + mFramePadding.bottom + mBackgroundPadding.bottom); + requestLayout(); + invalidate(); + + int opacity = PixelFormat.OPAQUE; + + // Note: if there is no background, we will assume opaque. The + // common case seems to be that an application sets there to be + // no background so it can draw everything itself. For that, + // we would like to assume OPAQUE and let the app force it to + // the slower TRANSLUCENT mode if that is really what it wants. + Drawable bg = getBackground(); + Drawable fg = getForeground(); + if (bg != null) { + if (fg == null) { + opacity = bg.getOpacity(); + } else if (mFramePadding.left <= 0 && mFramePadding.top <= 0 + && mFramePadding.right <= 0 && mFramePadding.bottom <= 0) { + // If the frame padding is zero, then we can be opaque + // if either the frame -or- the background is opaque. + int fop = fg.getOpacity(); + int bop = bg.getOpacity(); + if (Config.LOGV) + Log.v(TAG, "Background opacity: " + bop + ", Frame opacity: " + fop); + if (fop == PixelFormat.OPAQUE || bop == PixelFormat.OPAQUE) { + opacity = PixelFormat.OPAQUE; + } else if (fop == PixelFormat.UNKNOWN) { + opacity = bop; + } else if (bop == PixelFormat.UNKNOWN) { + opacity = fop; + } else { + opacity = Drawable.resolveOpacity(fop, bop); + } + } else { + // For now we have to assume translucent if there is a + // frame with padding... there is no way to tell if the + // frame and background together will draw all pixels. + if (Config.LOGV) + Log.v(TAG, "Padding: " + mFramePadding); + opacity = PixelFormat.TRANSLUCENT; + } + } + + if (Config.LOGV) + Log.v(TAG, "Background: " + bg + ", Frame: " + fg); + if (Config.LOGV) + Log.v(TAG, "Selected default opacity: " + opacity); + + mDefaultOpacity = opacity; + if (mFeatureId < 0) { + setDefaultWindowFormat(opacity); + } + } + + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + + mPanelMayLongPress = false; + + // If the user is chording a menu shortcut, release the chord since + // this window lost focus + if (!hasWindowFocus && mPanelChordingKey != 0) { + closePanel(FEATURE_OPTIONS_PANEL); + } + + final Callback cb = getCallback(); + if (cb != null && mFeatureId < 0) { + cb.onWindowFocusChanged(hasWindowFocus); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + final Callback cb = getCallback(); + if (cb != null && mFeatureId < 0) { + cb.onAttachedToWindow(); + } + + if (mFeatureId == -1) { + /* + * The main window has been attached, try to restore any panels + * that may have been open before. This is called in cases where + * an activity is being killed for configuration change and the + * menu was open. When the activity is recreated, the menu + * should be shown again. + */ + openPanelsAfterRestore(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + final Callback cb = getCallback(); + if (cb != null && mFeatureId < 0) { + cb.onDetachedFromWindow(); + } + } + + @Override + public void onCloseSystemDialogs(String reason) { + if (mFeatureId >= 0) { + closeAllPanels(); + } + } + + public android.view.SurfaceHolder.Callback willYouTakeTheSurface() { + return mFeatureId < 0 ? mTakeSurfaceCallback : null; + } + + public void setSurfaceType(int type) { + PhoneWindow.this.setType(type); + } + + public void setSurfaceFormat(int format) { + PhoneWindow.this.setFormat(format); + } + + public void setSurfaceKeepScreenOn(boolean keepOn) { + if (keepOn) PhoneWindow.this.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + else PhoneWindow.this.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + } + + protected DecorView generateDecor() { + return new DecorView(getContext(), -1); + } + + protected void setFeatureFromAttrs(int featureId, TypedArray attrs, + int drawableAttr, int alphaAttr) { + Drawable d = attrs.getDrawable(drawableAttr); + if (d != null) { + requestFeature(featureId); + setFeatureDefaultDrawable(featureId, d); + } + if ((getFeatures() & (1 << featureId)) != 0) { + int alpha = attrs.getInt(alphaAttr, -1); + if (alpha >= 0) { + setFeatureDrawableAlpha(featureId, alpha); + } + } + } + + protected ViewGroup generateLayout(DecorView decor) { + // Apply data from current theme. + + TypedArray a = getWindowStyle(); + + if (false) { + System.out.println("From style:"); + String s = "Attrs:"; + for (int i = 0; i < com.android.internal.R.styleable.Window.length; i++) { + s = s + " " + Integer.toHexString(com.android.internal.R.styleable.Window[i]) + "=" + + a.getString(i); + } + System.out.println(s); + } + + mIsFloating = a.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false); + int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR) + & (~getForcedWindowFlags()); + if (mIsFloating) { + setLayout(WRAP_CONTENT, WRAP_CONTENT); + setFlags(0, flagsToUpdate); + } else { + setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate); + } + + if (a.getBoolean(com.android.internal.R.styleable.Window_windowNoTitle, false)) { + requestFeature(FEATURE_NO_TITLE); + } + + if (a.getBoolean(com.android.internal.R.styleable.Window_windowFullscreen, false)) { + setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN&(~getForcedWindowFlags())); + } + + if (a.getBoolean(com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { + setFlags(FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER&(~getForcedWindowFlags())); + } + + WindowManager.LayoutParams params = getAttributes(); + + if (!hasSoftInputMode()) { + params.softInputMode = a.getInt( + com.android.internal.R.styleable.Window_windowSoftInputMode, + params.softInputMode); + } + + if (a.getBoolean(com.android.internal.R.styleable.Window_backgroundDimEnabled, + mIsFloating)) { + /* All dialogs should have the window dimmed */ + if ((getForcedWindowFlags()&WindowManager.LayoutParams.FLAG_DIM_BEHIND) == 0) { + params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND; + } + params.dimAmount = a.getFloat( + android.R.styleable.Window_backgroundDimAmount, 0.5f); + } + + if (params.windowAnimations == 0) { + params.windowAnimations = a.getResourceId( + com.android.internal.R.styleable.Window_windowAnimationStyle, 0); + } + + // The rest are only done if this window is not embedded; otherwise, + // the values are inherited from our container. + if (getContainer() == null) { + if (mBackgroundDrawable == null) { + if (mBackgroundResource == 0) { + mBackgroundResource = a.getResourceId( + com.android.internal.R.styleable.Window_windowBackground, 0); + } + if (mFrameResource == 0) { + mFrameResource = a.getResourceId(com.android.internal.R.styleable.Window_windowFrame, 0); + } + if (false) { + System.out.println("Background: " + + Integer.toHexString(mBackgroundResource) + " Frame: " + + Integer.toHexString(mFrameResource)); + } + } + mTextColor = a.getColor(com.android.internal.R.styleable.Window_textColor, 0xFF000000); + } + + // Inflate the window decor. + + int layoutResource; + int features = getLocalFeatures(); + // System.out.println("Features: 0x" + Integer.toHexString(features)); + if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) { + if (mIsFloating) { + layoutResource = com.android.internal.R.layout.dialog_title_icons; + } else { + layoutResource = com.android.internal.R.layout.screen_title_icons; + } + // System.out.println("Title Icons!"); + } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0) { + // Special case for a window with only a progress bar (and title). + // XXX Need to have a no-title version of embedded windows. + layoutResource = com.android.internal.R.layout.screen_progress; + // System.out.println("Progress!"); + } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) { + // Special case for a window with a custom title. + // If the window is floating, we need a dialog layout + if (mIsFloating) { + layoutResource = com.android.internal.R.layout.dialog_custom_title; + } else { + layoutResource = com.android.internal.R.layout.screen_custom_title; + } + } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) { + // If no other features and not embedded, only need a title. + // If the window is floating, we need a dialog layout + if (mIsFloating) { + layoutResource = com.android.internal.R.layout.dialog_title; + } else { + layoutResource = com.android.internal.R.layout.screen_title; + } + // System.out.println("Title!"); + } else { + // Embedded, so no decoration is needed. + layoutResource = com.android.internal.R.layout.screen_simple; + // System.out.println("Simple!"); + } + + mDecor.startChanging(); + + View in = mLayoutInflater.inflate(layoutResource, null); + decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); + + ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); + if (contentParent == null) { + throw new RuntimeException("Window couldn't find content container view"); + } + + if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) { + ProgressBar progress = getCircularProgressBar(false); + if (progress != null) { + progress.setIndeterminate(true); + } + } + + // Remaining setup -- of background and title -- that only applies + // to top-level windows. + if (getContainer() == null) { + Drawable drawable = mBackgroundDrawable; + if (mBackgroundResource != 0) { + drawable = getContext().getResources().getDrawable(mBackgroundResource); + } + mDecor.setWindowBackground(drawable); + drawable = null; + if (mFrameResource != 0) { + drawable = getContext().getResources().getDrawable(mFrameResource); + } + mDecor.setWindowFrame(drawable); + + // System.out.println("Text=" + Integer.toHexString(mTextColor) + + // " Sel=" + Integer.toHexString(mTextSelectedColor) + + // " Title=" + Integer.toHexString(mTitleColor)); + + if (mTitleColor == 0) { + mTitleColor = mTextColor; + } + + if (mTitle != null) { + setTitle(mTitle); + } + setTitleColor(mTitleColor); + } + + mDecor.finishChanging(); + + return contentParent; + } + + private void installDecor() { + if (mDecor == null) { + mDecor = generateDecor(); + mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); + mDecor.setIsRootNamespace(true); + } + if (mContentParent == null) { + mContentParent = generateLayout(mDecor); + + mTitleView = (TextView)findViewById(com.android.internal.R.id.title); + if (mTitleView != null) { + if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) { + View titleContainer = findViewById(com.android.internal.R.id.title_container); + if (titleContainer != null) { + titleContainer.setVisibility(View.GONE); + } else { + mTitleView.setVisibility(View.GONE); + } + if (mContentParent instanceof FrameLayout) { + ((FrameLayout)mContentParent).setForeground(null); + } + } else { + mTitleView.setText(mTitle); + } + } + } + } + + private Drawable loadImageURI(Uri uri) { + try { + return Drawable.createFromStream( + getContext().getContentResolver().openInputStream(uri), null); + } catch (Exception e) { + Log.w(TAG, "Unable to open content: " + uri); + } + return null; + } + + private DrawableFeatureState getDrawableState(int featureId, boolean required) { + if ((getFeatures() & (1 << featureId)) == 0) { + if (!required) { + return null; + } + throw new RuntimeException("The feature has not been requested"); + } + + DrawableFeatureState[] ar; + if ((ar = mDrawables) == null || ar.length <= featureId) { + DrawableFeatureState[] nar = new DrawableFeatureState[featureId + 1]; + if (ar != null) { + System.arraycopy(ar, 0, nar, 0, ar.length); + } + mDrawables = ar = nar; + } + + DrawableFeatureState st = ar[featureId]; + if (st == null) { + ar[featureId] = st = new DrawableFeatureState(featureId); + } + return st; + } + + /** + * Gets a panel's state based on its feature ID. + * + * @param featureId The feature ID of the panel. + * @param required Whether the panel is required (if it is required and it + * isn't in our features, this throws an exception). + * @return The panel state. + */ + private PanelFeatureState getPanelState(int featureId, boolean required) { + return getPanelState(featureId, required, null); + } + + /** + * Gets a panel's state based on its feature ID. + * + * @param featureId The feature ID of the panel. + * @param required Whether the panel is required (if it is required and it + * isn't in our features, this throws an exception). + * @param convertPanelState Optional: If the panel state does not exist, use + * this as the panel state. + * @return The panel state. + */ + private PanelFeatureState getPanelState(int featureId, boolean required, + PanelFeatureState convertPanelState) { + if ((getFeatures() & (1 << featureId)) == 0) { + if (!required) { + return null; + } + throw new RuntimeException("The feature has not been requested"); + } + + PanelFeatureState[] ar; + if ((ar = mPanels) == null || ar.length <= featureId) { + PanelFeatureState[] nar = new PanelFeatureState[featureId + 1]; + if (ar != null) { + System.arraycopy(ar, 0, nar, 0, ar.length); + } + mPanels = ar = nar; + } + + PanelFeatureState st = ar[featureId]; + if (st == null) { + ar[featureId] = st = (convertPanelState != null) + ? convertPanelState + : new PanelFeatureState(featureId); + } + return st; + } + + @Override + public final void setChildDrawable(int featureId, Drawable drawable) { + DrawableFeatureState st = getDrawableState(featureId, true); + st.child = drawable; + updateDrawable(featureId, st, false); + } + + @Override + public final void setChildInt(int featureId, int value) { + updateInt(featureId, value, false); + } + + @Override + public boolean isShortcutKey(int keyCode, KeyEvent event) { + PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); + return st.menu != null && st.menu.isShortcutKey(keyCode, event); + } + + private void updateDrawable(int featureId, DrawableFeatureState st, boolean fromResume) { + // Do nothing if the decor is not yet installed... an update will + // need to be forced when we eventually become active. + if (mContentParent == null) { + return; + } + + final int featureMask = 1 << featureId; + + if ((getFeatures() & featureMask) == 0 && !fromResume) { + return; + } + + Drawable drawable = null; + if (st != null) { + drawable = st.child; + if (drawable == null) + drawable = st.local; + if (drawable == null) + drawable = st.def; + } + if ((getLocalFeatures() & featureMask) == 0) { + if (getContainer() != null) { + if (isActive() || fromResume) { + getContainer().setChildDrawable(featureId, drawable); + } + } + } else if (st != null && (st.cur != drawable || st.curAlpha != st.alpha)) { + // System.out.println("Drawable changed: old=" + st.cur + // + ", new=" + drawable); + st.cur = drawable; + st.curAlpha = st.alpha; + onDrawableChanged(featureId, drawable, st.alpha); + } + } + + private void updateInt(int featureId, int value, boolean fromResume) { + + // Do nothing if the decor is not yet installed... an update will + // need to be forced when we eventually become active. + if (mContentParent == null) { + return; + } + + final int featureMask = 1 << featureId; + + if ((getFeatures() & featureMask) == 0 && !fromResume) { + return; + } + + if ((getLocalFeatures() & featureMask) == 0) { + if (getContainer() != null) { + getContainer().setChildInt(featureId, value); + } + } else { + onIntChanged(featureId, value); + } + } + + private ImageView getLeftIconView() { + if (mLeftIconView != null) { + return mLeftIconView; + } + if (mContentParent == null) { + installDecor(); + } + return (mLeftIconView = (ImageView)findViewById(com.android.internal.R.id.left_icon)); + } + + private ProgressBar getCircularProgressBar(boolean shouldInstallDecor) { + if (mCircularProgressBar != null) { + return mCircularProgressBar; + } + if (mContentParent == null && shouldInstallDecor) { + installDecor(); + } + mCircularProgressBar = (ProgressBar)findViewById(com.android.internal.R.id.progress_circular); + mCircularProgressBar.setVisibility(View.INVISIBLE); + return mCircularProgressBar; + } + + private ProgressBar getHorizontalProgressBar(boolean shouldInstallDecor) { + if (mHorizontalProgressBar != null) { + return mHorizontalProgressBar; + } + if (mContentParent == null && shouldInstallDecor) { + installDecor(); + } + mHorizontalProgressBar = (ProgressBar)findViewById(com.android.internal.R.id.progress_horizontal); + mHorizontalProgressBar.setVisibility(View.INVISIBLE); + return mHorizontalProgressBar; + } + + private ImageView getRightIconView() { + if (mRightIconView != null) { + return mRightIconView; + } + if (mContentParent == null) { + installDecor(); + } + return (mRightIconView = (ImageView)findViewById(com.android.internal.R.id.right_icon)); + } + + /** + * Helper method for calling the {@link Callback#onPanelClosed(int, Menu)} + * callback. This method will grab whatever extra state is needed for the + * callback that isn't given in the parameters. If the panel is not open, + * this will not perform the callback. + * + * @param featureId Feature ID of the panel that was closed. Must be given. + * @param panel Panel that was closed. Optional but useful if there is no + * menu given. + * @param menu The menu that was closed. Optional, but give if you have. + */ + private void callOnPanelClosed(int featureId, PanelFeatureState panel, Menu menu) { + final Callback cb = getCallback(); + if (cb == null) + return; + + // Try to get a menu + if (menu == null) { + // Need a panel to grab the menu, so try to get that + if (panel == null) { + if ((featureId >= 0) && (featureId < mPanels.length)) { + panel = mPanels[featureId]; + } + } + + if (panel != null) { + // menu still may be null, which is okay--we tried our best + menu = panel.menu; + } + } + + // If the panel is not open, do not callback + if ((panel != null) && (!panel.isOpen)) + return; + + cb.onPanelClosed(featureId, menu); + } + + /** + * Helper method for adding launch-search to most applications. Opens the + * search window using default settings. + * + * @return true if search window opened + */ + private boolean launchDefaultSearch() { + final Callback cb = getCallback(); + if (cb == null) { + return false; + } else { + sendCloseSystemWindows("search"); + return cb.onSearchRequested(); + } + } + + @Override + public void setVolumeControlStream(int streamType) { + mVolumeControlStreamType = streamType; + } + + @Override + public int getVolumeControlStream() { + return mVolumeControlStreamType; + } + + private static final class DrawableFeatureState { + DrawableFeatureState(int _featureId) { + featureId = _featureId; + } + + final int featureId; + + int resid; + + Uri uri; + + Drawable local; + + Drawable child; + + Drawable def; + + Drawable cur; + + int alpha = 255; + + int curAlpha = 255; + } + + private static final class PanelFeatureState { + + /** Feature ID for this panel. */ + int featureId; + + // Information pulled from the style for this panel. + + int background; + + /** The background when the panel spans the entire available width. */ + int fullBackground; + + int gravity; + + int x; + + int y; + + int windowAnimations; + + /** Dynamic state of the panel. */ + DecorView decorView; + + /** The panel that was returned by onCreatePanelView(). */ + View createdPanelView; + + /** The panel that we are actually showing. */ + View shownPanelView; + + /** Use {@link #setMenu} to set this. */ + Menu menu; + + /** + * Whether the panel has been prepared (see + * {@link PhoneWindow#preparePanel}). + */ + boolean isPrepared; + + /** + * Whether an item's action has been performed. This happens in obvious + * scenarios (user clicks on menu item), but can also happen with + * chording menu+(shortcut key). + */ + boolean isHandled; + + boolean isOpen; + + /** + * True if the menu is in expanded mode, false if the menu is in icon + * mode + */ + boolean isInExpandedMode; + + public boolean qwertyMode; + + boolean refreshDecorView; + + boolean wasLastOpen; + + boolean wasLastExpanded; + + /** + * Contains the state of the menu when told to freeze. + */ + Bundle frozenMenuState; + + PanelFeatureState(int featureId) { + this.featureId = featureId; + + refreshDecorView = false; + } + + void setStyle(Context context) { + TypedArray a = context.obtainStyledAttributes(com.android.internal.R.styleable.Theme); + background = a.getResourceId( + com.android.internal.R.styleable.Theme_panelBackground, 0); + fullBackground = a.getResourceId( + com.android.internal.R.styleable.Theme_panelFullBackground, 0); + windowAnimations = a.getResourceId( + com.android.internal.R.styleable.Theme_windowAnimationStyle, 0); + a.recycle(); + } + + void setMenu(Menu menu) { + this.menu = menu; + + if (frozenMenuState != null) { + ((MenuBuilder) menu).restoreHierarchyState(frozenMenuState); + frozenMenuState = null; + } + } + + Parcelable onSaveInstanceState() { + SavedState savedState = new SavedState(); + savedState.featureId = featureId; + savedState.isOpen = isOpen; + savedState.isInExpandedMode = isInExpandedMode; + + if (menu != null) { + savedState.menuState = new Bundle(); + ((MenuBuilder) menu).saveHierarchyState(savedState.menuState); + } + + return savedState; + } + + void onRestoreInstanceState(Parcelable state) { + SavedState savedState = (SavedState) state; + featureId = savedState.featureId; + wasLastOpen = savedState.isOpen; + wasLastExpanded = savedState.isInExpandedMode; + frozenMenuState = savedState.menuState; + + /* + * A LocalActivityManager keeps the same instance of this class around. + * The first time the menu is being shown after restoring, the + * Activity.onCreateOptionsMenu should be called. But, if it is the + * same instance then menu != null and we won't call that method. + * So, clear this. Also clear any cached views. + */ + menu = null; + createdPanelView = null; + shownPanelView = null; + decorView = null; + } + + private static class SavedState implements Parcelable { + int featureId; + boolean isOpen; + boolean isInExpandedMode; + Bundle menuState; + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(featureId); + dest.writeInt(isOpen ? 1 : 0); + dest.writeInt(isInExpandedMode ? 1 : 0); + + if (isOpen) { + dest.writeBundle(menuState); + } + } + + private static SavedState readFromParcel(Parcel source) { + SavedState savedState = new SavedState(); + savedState.featureId = source.readInt(); + savedState.isOpen = source.readInt() == 1; + savedState.isInExpandedMode = source.readInt() == 1; + + if (savedState.isOpen) { + savedState.menuState = source.readBundle(); + } + + return savedState; + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public SavedState createFromParcel(Parcel in) { + return readFromParcel(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } + + } + + /** + * Simple implementation of MenuBuilder.Callback that: + *

  • Opens a submenu when selected. + *
  • Calls back to the callback's onMenuItemSelected when an item is + * selected. + */ + private final class ContextMenuCallback implements MenuBuilder.Callback { + private int mFeatureId; + private MenuDialogHelper mSubMenuHelper; + + public ContextMenuCallback(int featureId) { + mFeatureId = featureId; + } + + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + if (allMenusAreClosing) { + Callback callback = getCallback(); + if (callback != null) callback.onPanelClosed(mFeatureId, menu); + + if (menu == mContextMenu) { + dismissContextMenu(); + } + + // Dismiss the submenu, if it is showing + if (mSubMenuHelper != null) { + mSubMenuHelper.dismiss(); + mSubMenuHelper = null; + } + } + } + + public void onCloseSubMenu(SubMenuBuilder menu) { + Callback callback = getCallback(); + if (callback != null) callback.onPanelClosed(mFeatureId, menu.getRootMenu()); + } + + public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { + Callback callback = getCallback(); + return (callback != null) && callback.onMenuItemSelected(mFeatureId, item); + } + + public void onMenuModeChange(MenuBuilder menu) { + } + + public boolean onSubMenuSelected(SubMenuBuilder subMenu) { + // Set a simple callback for the submenu + subMenu.setCallback(this); + + // The window manager will give us a valid window token + mSubMenuHelper = new MenuDialogHelper(subMenu); + mSubMenuHelper.show(null); + + return true; + } + } + + void sendCloseSystemWindows() { + PhoneWindowManager.sendCloseSystemWindows(getContext(), null); + } + + void sendCloseSystemWindows(String reason) { + PhoneWindowManager.sendCloseSystemWindows(getContext(), reason); + } +} diff --git a/policy/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/com/android/internal/policy/impl/PhoneWindowManager.java new file mode 100755 index 0000000000000000000000000000000000000000..a7c278b0d301aff81d5090f5f2a3df4a41856b7d --- /dev/null +++ b/policy/com/android/internal/policy/impl/PhoneWindowManager.java @@ -0,0 +1,2412 @@ +/* + * Copyright (C) 2006 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. + */ + +package com.android.internal.policy.impl; + +import android.app.Activity; +import android.app.ActivityManagerNative; +import android.app.IActivityManager; +import android.app.IStatusBar; +import android.app.IUiModeManager; +import android.app.UiModeManager; +import android.content.ActivityNotFoundException; +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.database.ContentObserver; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.os.Handler; +import android.os.IBinder; +import android.os.LocalPowerManager; +import android.os.PowerManager; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.os.SystemProperties; +import android.os.Vibrator; +import android.provider.Settings; + +import com.android.internal.policy.PolicyManager; +import com.android.internal.telephony.ITelephony; +import com.android.internal.widget.PointerLocationView; + +import android.util.Config; +import android.util.EventLog; +import android.util.Log; +import android.view.Display; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.IWindowManager; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.WindowOrientationListener; +import android.view.RawInputEvent; +import android.view.Surface; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.Window; +import android.view.WindowManager; +import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; +import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN; +import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; +import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; +import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; +import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; +import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; +import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; +import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; +import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD; +import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; +import static android.view.WindowManager.LayoutParams.TYPE_PHONE; +import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE; +import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL; +import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; +import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; +import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; +import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; +import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; +import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; +import static android.view.WindowManager.LayoutParams.TYPE_TOAST; +import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import android.view.WindowManagerImpl; +import android.view.WindowManagerPolicy; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.media.IAudioService; +import android.media.AudioManager; + +import java.util.ArrayList; + +/** + * WindowManagerPolicy implementation for the Android phone UI. This + * introduces a new method suffix, Lp, for an internal lock of the + * PhoneWindowManager. This is used to protect some internal state, and + * can be acquired with either thw Lw and Li lock held, so has the restrictions + * of both of those when held. + */ +public class PhoneWindowManager implements WindowManagerPolicy { + static final String TAG = "WindowManager"; + static final boolean DEBUG = false; + static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; + static final boolean DEBUG_LAYOUT = false; + static final boolean SHOW_STARTING_ANIMATIONS = true; + static final boolean SHOW_PROCESSES_ON_ALT_MENU = false; + + // wallpaper is at the bottom, though the window manager may move it. + static final int WALLPAPER_LAYER = 2; + static final int APPLICATION_LAYER = 2; + static final int PHONE_LAYER = 3; + static final int SEARCH_BAR_LAYER = 4; + static final int STATUS_BAR_PANEL_LAYER = 5; + static final int SYSTEM_DIALOG_LAYER = 6; + // toasts and the plugged-in battery thing + static final int TOAST_LAYER = 7; + static final int STATUS_BAR_LAYER = 8; + // SIM errors and unlock. Not sure if this really should be in a high layer. + static final int PRIORITY_PHONE_LAYER = 9; + // like the ANR / app crashed dialogs + static final int SYSTEM_ALERT_LAYER = 10; + // system-level error dialogs + static final int SYSTEM_ERROR_LAYER = 11; + // on-screen keyboards and other such input method user interfaces go here. + static final int INPUT_METHOD_LAYER = 12; + // on-screen keyboards and other such input method user interfaces go here. + static final int INPUT_METHOD_DIALOG_LAYER = 13; + // the keyguard; nothing on top of these can take focus, since they are + // responsible for power management when displayed. + static final int KEYGUARD_LAYER = 14; + static final int KEYGUARD_DIALOG_LAYER = 15; + // things in here CAN NOT take focus, but are shown on top of everything else. + static final int SYSTEM_OVERLAY_LAYER = 16; + + static final int APPLICATION_MEDIA_SUBLAYER = -2; + static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1; + static final int APPLICATION_PANEL_SUBLAYER = 1; + static final int APPLICATION_SUB_PANEL_SUBLAYER = 2; + + static final float SLIDE_TOUCH_EVENT_SIZE_LIMIT = 0.6f; + + // Debugging: set this to have the system act like there is no hard keyboard. + static final boolean KEYBOARD_ALWAYS_HIDDEN = false; + + static public final String SYSTEM_DIALOG_REASON_KEY = "reason"; + static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions"; + static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; + static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; + + final Object mLock = new Object(); + + Context mContext; + IWindowManager mWindowManager; + LocalPowerManager mPowerManager; + Vibrator mVibrator; // Vibrator for giving feedback of orientation changes + + // Vibrator pattern for haptic feedback of a long press. + long[] mLongPressVibePattern; + + // Vibrator pattern for haptic feedback of virtual key press. + long[] mVirtualKeyVibePattern; + + // Vibrator pattern for a short vibration. + long[] mKeyboardTapVibePattern; + + // Vibrator pattern for haptic feedback during boot when safe mode is disabled. + long[] mSafeModeDisabledVibePattern; + + // Vibrator pattern for haptic feedback during boot when safe mode is enabled. + long[] mSafeModeEnabledVibePattern; + + /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */ + boolean mEnableShiftMenuBugReports = false; + + boolean mSafeMode; + WindowState mStatusBar = null; + final ArrayList mStatusBarPanels = new ArrayList(); + WindowState mKeyguard = null; + KeyguardViewMediator mKeyguardMediator; + GlobalActions mGlobalActions; + boolean mShouldTurnOffOnKeyUp; + RecentApplicationsDialog mRecentAppsDialog; + Handler mHandler; + + boolean mSystemReady; + boolean mLidOpen; + int mUiMode = Configuration.UI_MODE_TYPE_NORMAL; + int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED; + int mLidOpenRotation; + int mCarDockRotation; + int mDeskDockRotation; + boolean mCarDockEnablesAccelerometer; + boolean mDeskDockEnablesAccelerometer; + int mLidKeyboardAccessibility; + int mLidNavigationAccessibility; + boolean mScreenOn = false; + boolean mOrientationSensorEnabled = false; + int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; + static final int DEFAULT_ACCELEROMETER_ROTATION = 0; + int mAccelerometerDefault = DEFAULT_ACCELEROMETER_ROTATION; + boolean mHasSoftInput = false; + + int mPointerLocationMode = 0; + PointerLocationView mPointerLocationView = null; + + // The current size of the screen. + int mW, mH; + // During layout, the current screen borders with all outer decoration + // (status bar, input method dock) accounted for. + int mCurLeft, mCurTop, mCurRight, mCurBottom; + // During layout, the frame in which content should be displayed + // to the user, accounting for all screen decoration except for any + // space they deem as available for other content. This is usually + // the same as mCur*, but may be larger if the screen decor has supplied + // content insets. + int mContentLeft, mContentTop, mContentRight, mContentBottom; + // During layout, the current screen borders along with input method + // windows are placed. + int mDockLeft, mDockTop, mDockRight, mDockBottom; + // During layout, the layer at which the doc window is placed. + int mDockLayer; + + static final Rect mTmpParentFrame = new Rect(); + static final Rect mTmpDisplayFrame = new Rect(); + static final Rect mTmpContentFrame = new Rect(); + static final Rect mTmpVisibleFrame = new Rect(); + + WindowState mTopFullscreenOpaqueWindowState; + boolean mForceStatusBar; + boolean mHideLockScreen; + boolean mDismissKeyguard; + boolean mHomePressed; + Intent mHomeIntent; + Intent mCarDockIntent; + Intent mDeskDockIntent; + boolean mSearchKeyPressed; + boolean mConsumeSearchKeyUp; + + // support for activating the lock screen while the screen is on + boolean mAllowLockscreenWhenOn; + int mLockScreenTimeout; + boolean mLockScreenTimerActive; + + // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.) + int mEndcallBehavior; + + // Behavior of POWER button while in-call and screen on. + // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.) + int mIncallPowerBehavior; + + int mLandscapeRotation = -1; + int mPortraitRotation = -1; + + // Nothing to see here, move along... + int mFancyRotationAnimation; + + ShortcutManager mShortcutManager; + PowerManager.WakeLock mBroadcastWakeLock; + + class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + void observe() { + ContentResolver resolver = mContext.getContentResolver(); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.END_BUTTON_BEHAVIOR), false, this); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.ACCELEROMETER_ROTATION), false, this); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.SCREEN_OFF_TIMEOUT), false, this); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.POINTER_LOCATION), false, this); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.DEFAULT_INPUT_METHOD), false, this); + resolver.registerContentObserver(Settings.System.getUriFor( + "fancy_rotation_anim"), false, this); + updateSettings(); + } + + @Override public void onChange(boolean selfChange) { + updateSettings(); + try { + mWindowManager.setRotation(USE_LAST_ROTATION, false, + mFancyRotationAnimation); + } catch (RemoteException e) { + // Ignore + } + } + } + + class MyOrientationListener extends WindowOrientationListener { + MyOrientationListener(Context context) { + super(context); + } + + @Override + public void onOrientationChanged(int rotation) { + // Send updates based on orientation value + if (localLOGV) Log.v(TAG, "onOrientationChanged, rotation changed to " +rotation); + try { + mWindowManager.setRotation(rotation, false, + mFancyRotationAnimation); + } catch (RemoteException e) { + // Ignore + + } + } + } + MyOrientationListener mOrientationListener; + + boolean useSensorForOrientationLp(int appOrientation) { + // The app says use the sensor. + if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) { + return true; + } + // The user preference says we can rotate, and the app is willing to rotate. + if (mAccelerometerDefault != 0 && + (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER + || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) { + return true; + } + // We're in a dock that has a rotation affinity, an the app is willing to rotate. + if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) + || (mDeskDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_DESK)) { + // Note we override the nosensor flag here. + if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER + || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED + || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { + return true; + } + } + // Else, don't use the sensor. + return false; + } + + /* + * We always let the sensor be switched on by default except when + * the user has explicitly disabled sensor based rotation or when the + * screen is switched off. + */ + boolean needSensorRunningLp() { + if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) { + // If the application has explicitly requested to follow the + // orientation, then we need to turn the sensor or. + return true; + } + if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) || + (mDeskDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_DESK)) { + // enable accelerometer if we are docked in a dock that enables accelerometer + // orientation management, + return true; + } + if (mAccelerometerDefault == 0) { + // If the setting for using the sensor by default is enabled, then + // we will always leave it on. Note that the user could go to + // a window that forces an orientation that does not use the + // sensor and in theory we could turn it off... however, when next + // turning it on we won't have a good value for the current + // orientation for a little bit, which can cause orientation + // changes to lag, so we'd like to keep it always on. (It will + // still be turned off when the screen is off.) + return false; + } + return true; + } + + /* + * Various use cases for invoking this function + * screen turning off, should always disable listeners if already enabled + * screen turned on and current app has sensor based orientation, enable listeners + * if not already enabled + * screen turned on and current app does not have sensor orientation, disable listeners if + * already enabled + * screen turning on and current app has sensor based orientation, enable listeners if needed + * screen turning on and current app has nosensor based orientation, do nothing + */ + void updateOrientationListenerLp() { + if (!mOrientationListener.canDetectOrientation()) { + // If sensor is turned off or nonexistent for some reason + return; + } + //Could have been invoked due to screen turning on or off or + //change of the currently visible window's orientation + if (localLOGV) Log.v(TAG, "Screen status="+mScreenOn+ + ", current orientation="+mCurrentAppOrientation+ + ", SensorEnabled="+mOrientationSensorEnabled); + boolean disable = true; + if (mScreenOn) { + if (needSensorRunningLp()) { + disable = false; + //enable listener if not already enabled + if (!mOrientationSensorEnabled) { + mOrientationListener.enable(); + if(localLOGV) Log.v(TAG, "Enabling listeners"); + mOrientationSensorEnabled = true; + } + } + } + //check if sensors need to be disabled + if (disable && mOrientationSensorEnabled) { + mOrientationListener.disable(); + if(localLOGV) Log.v(TAG, "Disabling listeners"); + mOrientationSensorEnabled = false; + } + } + + Runnable mPowerLongPress = new Runnable() { + public void run() { + mShouldTurnOffOnKeyUp = false; + performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); + sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); + showGlobalActionsDialog(); + } + }; + + void showGlobalActionsDialog() { + if (mGlobalActions == null) { + mGlobalActions = new GlobalActions(mContext); + } + final boolean keyguardShowing = mKeyguardMediator.isShowingAndNotHidden(); + mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned()); + if (keyguardShowing) { + // since it took two seconds of long press to bring this up, + // poke the wake lock so they have some time to see the dialog. + mKeyguardMediator.pokeWakelock(); + } + } + + boolean isDeviceProvisioned() { + return Settings.Secure.getInt( + mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0; + } + + /** + * When a home-key longpress expires, close other system windows and launch the recent apps + */ + Runnable mHomeLongPress = new Runnable() { + public void run() { + /* + * Eat the longpress so it won't dismiss the recent apps dialog when + * the user lets go of the home key + */ + mHomePressed = false; + performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); + sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS); + showRecentAppsDialog(); + } + }; + + /** + * Create (if necessary) and launch the recent apps dialog + */ + void showRecentAppsDialog() { + if (mRecentAppsDialog == null) { + mRecentAppsDialog = new RecentApplicationsDialog(mContext); + } + mRecentAppsDialog.show(); + } + + /** {@inheritDoc} */ + public void init(Context context, IWindowManager windowManager, + LocalPowerManager powerManager) { + mContext = context; + mWindowManager = windowManager; + mPowerManager = powerManager; + mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager); + mHandler = new Handler(); + mOrientationListener = new MyOrientationListener(mContext); + SettingsObserver settingsObserver = new SettingsObserver(mHandler); + settingsObserver.observe(); + mShortcutManager = new ShortcutManager(context, mHandler); + mShortcutManager.observe(); + mHomeIntent = new Intent(Intent.ACTION_MAIN, null); + mHomeIntent.addCategory(Intent.CATEGORY_HOME); + mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + mCarDockIntent = new Intent(Intent.ACTION_MAIN, null); + mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK); + mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null); + mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK); + mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + mBroadcastWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + "PhoneWindowManager.mBroadcastWakeLock"); + mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable")); + mLidOpenRotation = readRotation( + com.android.internal.R.integer.config_lidOpenRotation); + mCarDockRotation = readRotation( + com.android.internal.R.integer.config_carDockRotation); + mDeskDockRotation = readRotation( + com.android.internal.R.integer.config_deskDockRotation); + mCarDockEnablesAccelerometer = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_carDockEnablesAccelerometer); + mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_deskDockEnablesAccelerometer); + mLidKeyboardAccessibility = mContext.getResources().getInteger( + com.android.internal.R.integer.config_lidKeyboardAccessibility); + mLidNavigationAccessibility = mContext.getResources().getInteger( + com.android.internal.R.integer.config_lidNavigationAccessibility); + // register for dock events + IntentFilter filter = new IntentFilter(); + filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE); + filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE); + filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE); + filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE); + filter.addAction(Intent.ACTION_DOCK_EVENT); + Intent intent = context.registerReceiver(mDockReceiver, filter); + if (intent != null) { + // Retrieve current sticky dock event broadcast. + mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, + Intent.EXTRA_DOCK_STATE_UNDOCKED); + } + mVibrator = new Vibrator(); + mLongPressVibePattern = getLongIntArray(mContext.getResources(), + com.android.internal.R.array.config_longPressVibePattern); + mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(), + com.android.internal.R.array.config_virtualKeyVibePattern); + mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(), + com.android.internal.R.array.config_keyboardTapVibePattern); + mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(), + com.android.internal.R.array.config_safeModeDisabledVibePattern); + mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(), + com.android.internal.R.array.config_safeModeEnabledVibePattern); + } + + public void updateSettings() { + ContentResolver resolver = mContext.getContentResolver(); + boolean updateRotation = false; + View addView = null; + View removeView = null; + synchronized (mLock) { + mEndcallBehavior = Settings.System.getInt(resolver, + Settings.System.END_BUTTON_BEHAVIOR, + Settings.System.END_BUTTON_BEHAVIOR_DEFAULT); + mIncallPowerBehavior = Settings.Secure.getInt(resolver, + Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, + Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT); + mFancyRotationAnimation = Settings.System.getInt(resolver, + "fancy_rotation_anim", 0) != 0 ? 0x80 : 0; + int accelerometerDefault = Settings.System.getInt(resolver, + Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION); + if (mAccelerometerDefault != accelerometerDefault) { + mAccelerometerDefault = accelerometerDefault; + updateOrientationListenerLp(); + } + if (mSystemReady) { + int pointerLocation = Settings.System.getInt(resolver, + Settings.System.POINTER_LOCATION, 0); + if (mPointerLocationMode != pointerLocation) { + mPointerLocationMode = pointerLocation; + if (pointerLocation != 0) { + if (mPointerLocationView == null) { + mPointerLocationView = new PointerLocationView(mContext); + mPointerLocationView.setPrintCoords(false); + addView = mPointerLocationView; + } + } else { + removeView = mPointerLocationView; + mPointerLocationView = null; + } + } + } + // use screen off timeout setting as the timeout for the lockscreen + mLockScreenTimeout = Settings.System.getInt(resolver, + Settings.System.SCREEN_OFF_TIMEOUT, 0); + String imId = Settings.Secure.getString(resolver, + Settings.Secure.DEFAULT_INPUT_METHOD); + boolean hasSoftInput = imId != null && imId.length() > 0; + if (mHasSoftInput != hasSoftInput) { + mHasSoftInput = hasSoftInput; + updateRotation = true; + } + } + if (updateRotation) { + updateRotation(0); + } + if (addView != null) { + WindowManager.LayoutParams lp = new WindowManager.LayoutParams( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT); + lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; + lp.flags = + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; + lp.format = PixelFormat.TRANSLUCENT; + lp.setTitle("PointerLocation"); + WindowManagerImpl wm = (WindowManagerImpl) + mContext.getSystemService(Context.WINDOW_SERVICE); + wm.addView(addView, lp); + } + if (removeView != null) { + WindowManagerImpl wm = (WindowManagerImpl) + mContext.getSystemService(Context.WINDOW_SERVICE); + wm.removeView(removeView); + } + } + + private int readRotation(int resID) { + try { + int rotation = mContext.getResources().getInteger(resID); + switch (rotation) { + case 0: + return Surface.ROTATION_0; + case 90: + return Surface.ROTATION_90; + case 180: + return Surface.ROTATION_180; + case 270: + return Surface.ROTATION_270; + } + } catch (Resources.NotFoundException e) { + // fall through + } + return -1; + } + + /** {@inheritDoc} */ + public int checkAddPermission(WindowManager.LayoutParams attrs) { + int type = attrs.type; + + if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW + || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) { + return WindowManagerImpl.ADD_OKAY; + } + String permission = null; + switch (type) { + case TYPE_TOAST: + // XXX right now the app process has complete control over + // this... should introduce a token to let the system + // monitor/control what they are doing. + break; + case TYPE_INPUT_METHOD: + case TYPE_WALLPAPER: + // The window manager will check these. + break; + case TYPE_PHONE: + case TYPE_PRIORITY_PHONE: + case TYPE_SYSTEM_ALERT: + case TYPE_SYSTEM_ERROR: + case TYPE_SYSTEM_OVERLAY: + permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW; + break; + default: + permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; + } + if (permission != null) { + if (mContext.checkCallingOrSelfPermission(permission) + != PackageManager.PERMISSION_GRANTED) { + return WindowManagerImpl.ADD_PERMISSION_DENIED; + } + } + return WindowManagerImpl.ADD_OKAY; + } + + public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) { + switch (attrs.type) { + case TYPE_SYSTEM_OVERLAY: + case TYPE_TOAST: + // These types of windows can't receive input events. + attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; + break; + } + } + + void readLidState() { + try { + int sw = mWindowManager.getSwitchState(RawInputEvent.SW_LID); + if (sw >= 0) { + mLidOpen = sw == 0; + } + } catch (RemoteException e) { + // Ignore + } + } + + private int determineHiddenState(boolean lidOpen, + int mode, int hiddenValue, int visibleValue) { + switch (mode) { + case 1: + return lidOpen ? visibleValue : hiddenValue; + case 2: + return lidOpen ? hiddenValue : visibleValue; + } + return visibleValue; + } + + /** {@inheritDoc} */ + public void adjustConfigurationLw(Configuration config) { + readLidState(); + final boolean lidOpen = !KEYBOARD_ALWAYS_HIDDEN && mLidOpen; + mPowerManager.setKeyboardVisibility(lidOpen); + config.hardKeyboardHidden = determineHiddenState(lidOpen, + mLidKeyboardAccessibility, Configuration.HARDKEYBOARDHIDDEN_YES, + Configuration.HARDKEYBOARDHIDDEN_NO); + config.navigationHidden = determineHiddenState(lidOpen, + mLidNavigationAccessibility, Configuration.NAVIGATIONHIDDEN_YES, + Configuration.NAVIGATIONHIDDEN_NO); + config.keyboardHidden = (config.hardKeyboardHidden + == Configuration.HARDKEYBOARDHIDDEN_NO || mHasSoftInput) + ? Configuration.KEYBOARDHIDDEN_NO + : Configuration.KEYBOARDHIDDEN_YES; + } + + public boolean isCheekPressedAgainstScreen(MotionEvent ev) { + if(ev.getSize() > SLIDE_TOUCH_EVENT_SIZE_LIMIT) { + return true; + } + int size = ev.getHistorySize(); + for(int i = 0; i < size; i++) { + if(ev.getHistoricalSize(i) > SLIDE_TOUCH_EVENT_SIZE_LIMIT) { + return true; + } + } + return false; + } + + public void dispatchedPointerEventLw(MotionEvent ev, int targetX, int targetY) { + if (mPointerLocationView == null) { + return; + } + synchronized (mLock) { + if (mPointerLocationView == null) { + return; + } + ev.offsetLocation(targetX, targetY); + mPointerLocationView.addTouchEvent(ev); + ev.offsetLocation(-targetX, -targetY); + } + } + + /** {@inheritDoc} */ + public int windowTypeToLayerLw(int type) { + if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { + return APPLICATION_LAYER; + } + switch (type) { + case TYPE_STATUS_BAR: + return STATUS_BAR_LAYER; + case TYPE_STATUS_BAR_PANEL: + return STATUS_BAR_PANEL_LAYER; + case TYPE_SYSTEM_DIALOG: + return SYSTEM_DIALOG_LAYER; + case TYPE_SEARCH_BAR: + return SEARCH_BAR_LAYER; + case TYPE_PHONE: + return PHONE_LAYER; + case TYPE_KEYGUARD: + return KEYGUARD_LAYER; + case TYPE_KEYGUARD_DIALOG: + return KEYGUARD_DIALOG_LAYER; + case TYPE_SYSTEM_ALERT: + return SYSTEM_ALERT_LAYER; + case TYPE_SYSTEM_ERROR: + return SYSTEM_ERROR_LAYER; + case TYPE_INPUT_METHOD: + return INPUT_METHOD_LAYER; + case TYPE_INPUT_METHOD_DIALOG: + return INPUT_METHOD_DIALOG_LAYER; + case TYPE_SYSTEM_OVERLAY: + return SYSTEM_OVERLAY_LAYER; + case TYPE_PRIORITY_PHONE: + return PRIORITY_PHONE_LAYER; + case TYPE_TOAST: + return TOAST_LAYER; + case TYPE_WALLPAPER: + return WALLPAPER_LAYER; + } + Log.e(TAG, "Unknown window type: " + type); + return APPLICATION_LAYER; + } + + /** {@inheritDoc} */ + public int subWindowTypeToLayerLw(int type) { + switch (type) { + case TYPE_APPLICATION_PANEL: + case TYPE_APPLICATION_ATTACHED_DIALOG: + return APPLICATION_PANEL_SUBLAYER; + case TYPE_APPLICATION_MEDIA: + return APPLICATION_MEDIA_SUBLAYER; + case TYPE_APPLICATION_MEDIA_OVERLAY: + return APPLICATION_MEDIA_OVERLAY_SUBLAYER; + case TYPE_APPLICATION_SUB_PANEL: + return APPLICATION_SUB_PANEL_SUBLAYER; + } + Log.e(TAG, "Unknown sub-window type: " + type); + return 0; + } + + public int getMaxWallpaperLayer() { + return STATUS_BAR_LAYER; + } + + public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) { + return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD; + } + + public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) { + return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR + && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER; + } + + /** {@inheritDoc} */ + public View addStartingWindow(IBinder appToken, String packageName, + int theme, CharSequence nonLocalizedLabel, + int labelRes, int icon) { + if (!SHOW_STARTING_ANIMATIONS) { + return null; + } + if (packageName == null) { + return null; + } + + try { + Context context = mContext; + boolean setTheme = false; + //Log.i(TAG, "addStartingWindow " + packageName + ": nonLocalizedLabel=" + // + nonLocalizedLabel + " theme=" + Integer.toHexString(theme)); + if (theme != 0 || labelRes != 0) { + try { + context = context.createPackageContext(packageName, 0); + if (theme != 0) { + context.setTheme(theme); + setTheme = true; + } + } catch (PackageManager.NameNotFoundException e) { + // Ignore + } + } + if (!setTheme) { + context.setTheme(com.android.internal.R.style.Theme); + } + + Window win = PolicyManager.makeNewWindow(context); + if (win.getWindowStyle().getBoolean( + com.android.internal.R.styleable.Window_windowDisablePreview, false)) { + return null; + } + + Resources r = context.getResources(); + win.setTitle(r.getText(labelRes, nonLocalizedLabel)); + + win.setType( + WindowManager.LayoutParams.TYPE_APPLICATION_STARTING); + // Force the window flags: this is a fake window, so it is not really + // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM + // flag because we do know that the next window will take input + // focus, so we want to get the IME window up on top of us right away. + win.setFlags( + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + + win.setLayout(WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT); + + final WindowManager.LayoutParams params = win.getAttributes(); + params.token = appToken; + params.packageName = packageName; + params.windowAnimations = win.getWindowStyle().getResourceId( + com.android.internal.R.styleable.Window_windowAnimationStyle, 0); + params.setTitle("Starting " + packageName); + + WindowManagerImpl wm = (WindowManagerImpl) + context.getSystemService(Context.WINDOW_SERVICE); + View view = win.getDecorView(); + + if (win.isFloating()) { + // Whoops, there is no way to display an animation/preview + // of such a thing! After all that work... let's skip it. + // (Note that we must do this here because it is in + // getDecorView() where the theme is evaluated... maybe + // we should peek the floating attribute from the theme + // earlier.) + return null; + } + + if (localLOGV) Log.v( + TAG, "Adding starting window for " + packageName + + " / " + appToken + ": " + + (view.getParent() != null ? view : null)); + + wm.addView(view, params); + + // Only return the view if it was successfully added to the + // window manager... which we can tell by it having a parent. + return view.getParent() != null ? view : null; + } catch (WindowManagerImpl.BadTokenException e) { + // ignore + Log.w(TAG, appToken + " already running, starting window not displayed"); + } catch (RuntimeException e) { + // don't crash if something else bad happens, for example a + // failure loading resources because we are loading from an app + // on external storage that has been unmounted. + Log.w(TAG, appToken + " failed creating starting window", e); + } + + return null; + } + + /** {@inheritDoc} */ + public void removeStartingWindow(IBinder appToken, View window) { + // RuntimeException e = new RuntimeException(); + // Log.i(TAG, "remove " + appToken + " " + window, e); + + if (localLOGV) Log.v( + TAG, "Removing starting window for " + appToken + ": " + window); + + if (window != null) { + WindowManagerImpl wm = (WindowManagerImpl) mContext.getSystemService(Context.WINDOW_SERVICE); + wm.removeView(window); + } + } + + /** + * Preflight adding a window to the system. + * + * Currently enforces that three window types are singletons: + *
      + *
    • STATUS_BAR_TYPE
    • + *
    • KEYGUARD_TYPE
    • + *
    + * + * @param win The window to be added + * @param attrs Information about the window to be added + * + * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON + */ + public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) { + switch (attrs.type) { + case TYPE_STATUS_BAR: + if (mStatusBar != null) { + return WindowManagerImpl.ADD_MULTIPLE_SINGLETON; + } + mStatusBar = win; + break; + case TYPE_STATUS_BAR_PANEL: + mStatusBarPanels.add(win); + break; + case TYPE_KEYGUARD: + if (mKeyguard != null) { + return WindowManagerImpl.ADD_MULTIPLE_SINGLETON; + } + mKeyguard = win; + break; + } + return WindowManagerImpl.ADD_OKAY; + } + + /** {@inheritDoc} */ + public void removeWindowLw(WindowState win) { + if (mStatusBar == win) { + mStatusBar = null; + } + else if (mKeyguard == win) { + mKeyguard = null; + } else { + mStatusBarPanels.remove(win); + } + } + + static final boolean PRINT_ANIM = false; + + /** {@inheritDoc} */ + public int selectAnimationLw(WindowState win, int transit) { + if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win + + ": transit=" + transit); + if (transit == TRANSIT_PREVIEW_DONE) { + if (win.hasAppShownWindows()) { + if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT"); + return com.android.internal.R.anim.app_starting_exit; + } + } + + return 0; + } + + public Animation createForceHideEnterAnimation() { + return AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.lock_screen_behind_enter); + } + + static ITelephony getPhoneInterface() { + return ITelephony.Stub.asInterface(ServiceManager.checkService(Context.TELEPHONY_SERVICE)); + } + + static IAudioService getAudioInterface() { + return IAudioService.Stub.asInterface(ServiceManager.checkService(Context.AUDIO_SERVICE)); + } + + boolean keyguardOn() { + return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode(); + } + + private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = { + WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, + WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, + }; + + /** {@inheritDoc} */ + public boolean interceptKeyTi(WindowState win, int code, int metaKeys, boolean down, + int repeatCount, int flags) { + boolean keyguardOn = keyguardOn(); + + if (false) { + Log.d(TAG, "interceptKeyTi code=" + code + " down=" + down + " repeatCount=" + + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed); + } + + // Clear a pending HOME longpress if the user releases Home + // TODO: This could probably be inside the next bit of logic, but that code + // turned out to be a bit fragile so I'm doing it here explicitly, for now. + if ((code == KeyEvent.KEYCODE_HOME) && !down) { + mHandler.removeCallbacks(mHomeLongPress); + } + + // If the HOME button is currently being held, then we do special + // chording with it. + if (mHomePressed) { + + // If we have released the home key, and didn't do anything else + // while it was pressed, then it is time to go home! + if (code == KeyEvent.KEYCODE_HOME) { + if (!down) { + mHomePressed = false; + + if ((flags&KeyEvent.FLAG_CANCELED) == 0) { + // If an incoming call is ringing, HOME is totally disabled. + // (The user is already on the InCallScreen at this point, + // and his ONLY options are to answer or reject the call.) + boolean incomingRinging = false; + try { + ITelephony phoneServ = getPhoneInterface(); + if (phoneServ != null) { + incomingRinging = phoneServ.isRinging(); + } else { + Log.w(TAG, "Unable to find ITelephony interface"); + } + } catch (RemoteException ex) { + Log.w(TAG, "RemoteException from getPhoneInterface()", ex); + } + + if (incomingRinging) { + Log.i(TAG, "Ignoring HOME; there's a ringing incoming call."); + } else { + launchHomeFromHotKey(); + } + } else { + Log.i(TAG, "Ignoring HOME; event canceled."); + } + } + } + + return true; + } + + // First we always handle the home key here, so applications + // can never break it, although if keyguard is on, we do let + // it handle it, because that gives us the correct 5 second + // timeout. + if (code == KeyEvent.KEYCODE_HOME) { + + // If a system window has focus, then it doesn't make sense + // right now to interact with applications. + WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; + if (attrs != null) { + final int type = attrs.type; + if (type == WindowManager.LayoutParams.TYPE_KEYGUARD + || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) { + // the "app" is keyguard, so give it the key + return false; + } + final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; + for (int i=0; i launch home action was detected. Take the appropriate action + * given the situation with the keyguard. + */ + void launchHomeFromHotKey() { + if (mKeyguardMediator.isShowingAndNotHidden()) { + // don't launch home if keyguard showing + } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) { + // when in keyguard restricted mode, must first verify unlock + // before launching home + mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() { + public void onKeyguardExitResult(boolean success) { + if (success) { + try { + ActivityManagerNative.getDefault().stopAppSwitches(); + } catch (RemoteException e) { + } + sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); + startDockOrHome(); + } + } + }); + } else { + // no keyguard stuff to worry about, just launch home! + try { + ActivityManagerNative.getDefault().stopAppSwitches(); + } catch (RemoteException e) { + } + sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); + startDockOrHome(); + } + } + + public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) { + final int fl = attrs.flags; + + if ((fl & + (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR)) + == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { + contentInset.set(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom); + } else { + contentInset.setEmpty(); + } + } + + /** {@inheritDoc} */ + public void beginLayoutLw(int displayWidth, int displayHeight) { + mW = displayWidth; + mH = displayHeight; + mDockLeft = mContentLeft = mCurLeft = 0; + mDockTop = mContentTop = mCurTop = 0; + mDockRight = mContentRight = mCurRight = displayWidth; + mDockBottom = mContentBottom = mCurBottom = displayHeight; + mDockLayer = 0x10000000; + + // decide where the status bar goes ahead of time + if (mStatusBar != null) { + final Rect pf = mTmpParentFrame; + final Rect df = mTmpDisplayFrame; + final Rect vf = mTmpVisibleFrame; + pf.left = df.left = vf.left = 0; + pf.top = df.top = vf.top = 0; + pf.right = df.right = vf.right = displayWidth; + pf.bottom = df.bottom = vf.bottom = displayHeight; + + mStatusBar.computeFrameLw(pf, df, vf, vf); + if (mStatusBar.isVisibleLw()) { + // If the status bar is hidden, we don't want to cause + // windows behind it to scroll. + mDockTop = mContentTop = mCurTop = mStatusBar.getFrameLw().bottom; + if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mDockBottom=" + + mDockBottom + " mContentBottom=" + + mContentBottom + " mCurBottom=" + mCurBottom); + } + } + } + + void setAttachedWindowFrames(WindowState win, int fl, int sim, + WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) { + if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) { + // Here's a special case: if this attached window is a panel that is + // above the dock window, and the window it is attached to is below + // the dock window, then the frames we computed for the window it is + // attached to can not be used because the dock is effectively part + // of the underlying window and the attached window is floating on top + // of the whole thing. So, we ignore the attached window and explicitly + // compute the frames that would be appropriate without the dock. + df.left = cf.left = vf.left = mDockLeft; + df.top = cf.top = vf.top = mDockTop; + df.right = cf.right = vf.right = mDockRight; + df.bottom = cf.bottom = vf.bottom = mDockBottom; + } else { + // The effective display frame of the attached window depends on + // whether it is taking care of insetting its content. If not, + // we need to use the parent's content frame so that the entire + // window is positioned within that content. Otherwise we can use + // the display frame and let the attached window take care of + // positioning its content appropriately. + if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) { + cf.set(attached.getDisplayFrameLw()); + } else { + // If the window is resizing, then we want to base the content + // frame on our attached content frame to resize... however, + // things can be tricky if the attached window is NOT in resize + // mode, in which case its content frame will be larger. + // Ungh. So to deal with that, make sure the content frame + // we end up using is not covering the IM dock. + cf.set(attached.getContentFrameLw()); + if (attached.getSurfaceLayer() < mDockLayer) { + if (cf.left < mContentLeft) cf.left = mContentLeft; + if (cf.top < mContentTop) cf.top = mContentTop; + if (cf.right > mContentRight) cf.right = mContentRight; + if (cf.bottom > mContentBottom) cf.bottom = mContentBottom; + } + } + df.set(insetDecors ? attached.getDisplayFrameLw() : cf); + vf.set(attached.getVisibleFrameLw()); + } + // The LAYOUT_IN_SCREEN flag is used to determine whether the attached + // window should be positioned relative to its parent or the entire + // screen. + pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 + ? attached.getFrameLw() : df); + } + + /** {@inheritDoc} */ + public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs, + WindowState attached) { + // we've already done the status bar + if (win == mStatusBar) { + return; + } + + if (false) { + if ("com.google.android.youtube".equals(attrs.packageName) + && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { + Log.i(TAG, "GOTCHA!"); + } + } + + final int fl = attrs.flags; + final int sim = attrs.softInputMode; + + final Rect pf = mTmpParentFrame; + final Rect df = mTmpDisplayFrame; + final Rect cf = mTmpContentFrame; + final Rect vf = mTmpVisibleFrame; + + if (attrs.type == TYPE_INPUT_METHOD) { + pf.left = df.left = cf.left = vf.left = mDockLeft; + pf.top = df.top = cf.top = vf.top = mDockTop; + pf.right = df.right = cf.right = vf.right = mDockRight; + pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom; + // IM dock windows always go to the bottom of the screen. + attrs.gravity = Gravity.BOTTOM; + mDockLayer = win.getSurfaceLayer(); + } else { + if ((fl & + (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR)) + == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { + // This is the case for a normal activity window: we want it + // to cover all of the screen space, and it can take care of + // moving its contents to account for screen decorations that + // intrude into that space. + if (attached != null) { + // If this window is attached to another, our display + // frame is the same as the one we are attached to. + setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf); + } else { + pf.left = df.left = 0; + pf.top = df.top = 0; + pf.right = df.right = mW; + pf.bottom = df.bottom = mH; + if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) { + cf.left = mDockLeft; + cf.top = mDockTop; + cf.right = mDockRight; + cf.bottom = mDockBottom; + } else { + cf.left = mContentLeft; + cf.top = mContentTop; + cf.right = mContentRight; + cf.bottom = mContentBottom; + } + vf.left = mCurLeft; + vf.top = mCurTop; + vf.right = mCurRight; + vf.bottom = mCurBottom; + } + } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) { + // A window that has requested to fill the entire screen just + // gets everything, period. + pf.left = df.left = cf.left = 0; + pf.top = df.top = cf.top = 0; + pf.right = df.right = cf.right = mW; + pf.bottom = df.bottom = cf.bottom = mH; + vf.left = mCurLeft; + vf.top = mCurTop; + vf.right = mCurRight; + vf.bottom = mCurBottom; + } else if (attached != null) { + // A child window should be placed inside of the same visible + // frame that its parent had. + setAttachedWindowFrames(win, fl, sim, attached, false, pf, df, cf, vf); + } else { + // Otherwise, a normal window must be placed inside the content + // of all screen decorations. + pf.left = mContentLeft; + pf.top = mContentTop; + pf.right = mContentRight; + pf.bottom = mContentBottom; + if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) { + df.left = cf.left = mDockLeft; + df.top = cf.top = mDockTop; + df.right = cf.right = mDockRight; + df.bottom = cf.bottom = mDockBottom; + } else { + df.left = cf.left = mContentLeft; + df.top = cf.top = mContentTop; + df.right = cf.right = mContentRight; + df.bottom = cf.bottom = mContentBottom; + } + vf.left = mCurLeft; + vf.top = mCurTop; + vf.right = mCurRight; + vf.bottom = mCurBottom; + } + } + + if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) { + df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000; + df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000; + } + + if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle() + + ": sim=#" + Integer.toHexString(sim) + + " pf=" + pf.toShortString() + " df=" + df.toShortString() + + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()); + + if (false) { + if ("com.google.android.youtube".equals(attrs.packageName) + && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { + if (true || localLOGV) Log.v(TAG, "Computing frame of " + win + + ": sim=#" + Integer.toHexString(sim) + + " pf=" + pf.toShortString() + " df=" + df.toShortString() + + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()); + } + } + + win.computeFrameLw(pf, df, cf, vf); + + // Dock windows carve out the bottom of the screen, so normal windows + // can't appear underneath them. + if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) { + int top = win.getContentFrameLw().top; + top += win.getGivenContentInsetsLw().top; + if (mContentBottom > top) { + mContentBottom = top; + } + top = win.getVisibleFrameLw().top; + top += win.getGivenVisibleInsetsLw().top; + if (mCurBottom > top) { + mCurBottom = top; + } + if (DEBUG_LAYOUT) Log.v(TAG, "Input method: mDockBottom=" + + mDockBottom + " mContentBottom=" + + mContentBottom + " mCurBottom=" + mCurBottom); + } + } + + /** {@inheritDoc} */ + public int finishLayoutLw() { + return 0; + } + + /** {@inheritDoc} */ + public void beginAnimationLw(int displayWidth, int displayHeight) { + mTopFullscreenOpaqueWindowState = null; + mForceStatusBar = false; + + mHideLockScreen = false; + mAllowLockscreenWhenOn = false; + mDismissKeyguard = false; + } + + /** {@inheritDoc} */ + public void animatingWindowLw(WindowState win, + WindowManager.LayoutParams attrs) { + if (mTopFullscreenOpaqueWindowState == null && + win.isVisibleOrBehindKeyguardLw()) { + if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) { + mForceStatusBar = true; + } + if (attrs.type >= FIRST_APPLICATION_WINDOW + && attrs.type <= LAST_APPLICATION_WINDOW + && win.fillsScreenLw(mW, mH, false, false)) { + if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win); + mTopFullscreenOpaqueWindowState = win; + if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) { + if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win); + mHideLockScreen = true; + } + if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) { + if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win); + mDismissKeyguard = true; + } + if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { + mAllowLockscreenWhenOn = true; + } + } + } + } + + /** {@inheritDoc} */ + public int finishAnimationLw() { + int changes = 0; + + boolean hiding = false; + if (mStatusBar != null) { + if (localLOGV) Log.i(TAG, "force=" + mForceStatusBar + + " top=" + mTopFullscreenOpaqueWindowState); + if (mForceStatusBar) { + if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar"); + if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; + } else if (mTopFullscreenOpaqueWindowState != null) { + //Log.i(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() + // + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw()); + //Log.i(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()); + WindowManager.LayoutParams lp = + mTopFullscreenOpaqueWindowState.getAttrs(); + boolean hideStatusBar = + (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; + if (hideStatusBar) { + if (DEBUG_LAYOUT) Log.v(TAG, "Hiding status bar"); + if (mStatusBar.hideLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; + hiding = true; + } else { + if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar"); + if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; + } + } + } + + if (changes != 0 && hiding) { + IStatusBar sbs = IStatusBar.Stub.asInterface(ServiceManager.getService("statusbar")); + if (sbs != null) { + try { + // Make sure the window shade is hidden. + sbs.deactivate(); + } catch (RemoteException e) { + } + } + } + + // Hide the key guard if a visible window explicitly specifies that it wants to be displayed + // when the screen is locked + if (mKeyguard != null) { + if (localLOGV) Log.v(TAG, "finishLayoutLw::mHideKeyguard="+mHideLockScreen); + if (mDismissKeyguard && !mKeyguardMediator.isSecure()) { + if (mKeyguard.hideLw(true)) { + changes |= FINISH_LAYOUT_REDO_LAYOUT + | FINISH_LAYOUT_REDO_CONFIG + | FINISH_LAYOUT_REDO_WALLPAPER; + } + if (mKeyguardMediator.isShowing()) { + mHandler.post(new Runnable() { + public void run() { + mKeyguardMediator.keyguardDone(false, false); + } + }); + } + } else if (mHideLockScreen) { + if (mKeyguard.hideLw(true)) { + changes |= FINISH_LAYOUT_REDO_LAYOUT + | FINISH_LAYOUT_REDO_CONFIG + | FINISH_LAYOUT_REDO_WALLPAPER; + } + mKeyguardMediator.setHidden(true); + } else { + if (mKeyguard.showLw(true)) { + changes |= FINISH_LAYOUT_REDO_LAYOUT + | FINISH_LAYOUT_REDO_CONFIG + | FINISH_LAYOUT_REDO_WALLPAPER; + } + mKeyguardMediator.setHidden(false); + } + } + + // update since mAllowLockscreenWhenOn might have changed + updateLockScreenTimeout(); + return changes; + } + + public boolean allowAppAnimationsLw() { + if (mKeyguard != null && mKeyguard.isVisibleLw()) { + // If keyguard is currently visible, no reason to animate + // behind it. + return false; + } + if (mStatusBar != null && mStatusBar.isVisibleLw()) { + Rect rect = new Rect(mStatusBar.getShownFrameLw()); + for (int i=mStatusBarPanels.size()-1; i>=0; i--) { + WindowState w = mStatusBarPanels.get(i); + if (w.isVisibleLw()) { + rect.union(w.getShownFrameLw()); + } + } + final int insetw = mW/10; + final int inseth = mH/10; + if (rect.contains(insetw, inseth, mW-insetw, mH-inseth)) { + // All of the status bar windows put together cover the + // screen, so the app can't be seen. (Note this test doesn't + // work if the rects of these windows are at off offsets or + // sizes, causing gaps in the rect union we have computed.) + return false; + } + } + return true; + } + + /** {@inheritDoc} */ + public boolean preprocessInputEventTq(RawInputEvent event) { + switch (event.type) { + case RawInputEvent.EV_SW: + if (event.keycode == RawInputEvent.SW_LID) { + // lid changed state + mLidOpen = event.value == 0; + boolean awakeNow = mKeyguardMediator.doLidChangeTq(mLidOpen); + updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + if (awakeNow) { + // If the lid opening and we don't have to keep the + // keyguard up, then we can turn on the screen + // immediately. + mKeyguardMediator.pokeWakelock(); + } else if (keyguardIsShowingTq()) { + if (mLidOpen) { + // If we are opening the lid and not hiding the + // keyguard, then we need to have it turn on the + // screen once it is shown. + mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq( + KeyEvent.KEYCODE_POWER); + } + } else { + // Light up the keyboard if we are sliding up. + if (mLidOpen) { + mPowerManager.userActivity(SystemClock.uptimeMillis(), false, + LocalPowerManager.BUTTON_EVENT); + } else { + mPowerManager.userActivity(SystemClock.uptimeMillis(), false, + LocalPowerManager.OTHER_EVENT); + } + } + } + } + return false; + } + + + /** {@inheritDoc} */ + public boolean isAppSwitchKeyTqTiLwLi(int keycode) { + return keycode == KeyEvent.KEYCODE_HOME + || keycode == KeyEvent.KEYCODE_ENDCALL; + } + + /** {@inheritDoc} */ + public boolean isMovementKeyTi(int keycode) { + switch (keycode) { + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + return true; + } + return false; + } + + + /** + * @return Whether a telephone call is in progress right now. + */ + boolean isInCall() { + final ITelephony phone = getPhoneInterface(); + if (phone == null) { + Log.w(TAG, "couldn't get ITelephony reference"); + return false; + } + try { + return phone.isOffhook(); + } catch (RemoteException e) { + Log.w(TAG, "ITelephony.isOffhhook threw RemoteException " + e); + return false; + } + } + + /** + * @return Whether music is being played right now. + */ + boolean isMusicActive() { + final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE); + if (am == null) { + Log.w(TAG, "isMusicActive: couldn't get AudioManager reference"); + return false; + } + return am.isMusicActive(); + } + + /** + * Tell the audio service to adjust the volume appropriate to the event. + * @param keycode + */ + void handleVolumeKey(int stream, int keycode) { + final IAudioService audio = getAudioInterface(); + if (audio == null) { + Log.w(TAG, "handleVolumeKey: couldn't get IAudioService reference"); + return; + } + try { + // since audio is playing, we shouldn't have to hold a wake lock + // during the call, but we do it as a precaution for the rare possibility + // that the music stops right before we call this + mBroadcastWakeLock.acquire(); + audio.adjustStreamVolume(stream, + keycode == KeyEvent.KEYCODE_VOLUME_UP + ? AudioManager.ADJUST_RAISE + : AudioManager.ADJUST_LOWER, + 0); + } catch (RemoteException e) { + Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e); + } finally { + mBroadcastWakeLock.release(); + } + } + + static boolean isMediaKey(int code) { + if (code == KeyEvent.KEYCODE_HEADSETHOOK || + code == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || + code == KeyEvent.KEYCODE_MEDIA_STOP || + code == KeyEvent.KEYCODE_MEDIA_NEXT || + code == KeyEvent.KEYCODE_MEDIA_PREVIOUS || + code == KeyEvent.KEYCODE_MEDIA_REWIND || + code == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) { + return true; + } + return false; + } + + /** {@inheritDoc} */ + public int interceptKeyTq(RawInputEvent event, boolean screenIsOn) { + int result = ACTION_PASS_TO_USER; + final boolean isWakeKey = isWakeKeyTq(event); + // If screen is off then we treat the case where the keyguard is open but hidden + // the same as if it were open and in front. + // This will prevent any keys other than the power button from waking the screen + // when the keyguard is hidden by another activity. + final boolean keyguardActive = (screenIsOn ? + mKeyguardMediator.isShowingAndNotHidden() : + mKeyguardMediator.isShowing()); + + if (false) { + Log.d(TAG, "interceptKeyTq event=" + event + " keycode=" + event.keycode + + " screenIsOn=" + screenIsOn + " keyguardActive=" + keyguardActive); + } + + if (keyguardActive) { + if (screenIsOn) { + // when the screen is on, always give the event to the keyguard + result |= ACTION_PASS_TO_USER; + } else { + // otherwise, don't pass it to the user + result &= ~ACTION_PASS_TO_USER; + + final boolean isKeyDown = + (event.type == RawInputEvent.EV_KEY) && (event.value != 0); + if (isWakeKey && isKeyDown) { + + // tell the mediator about a wake key, it may decide to + // turn on the screen depending on whether the key is + // appropriate. + if (!mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(event.keycode) + && (event.keycode == KeyEvent.KEYCODE_VOLUME_DOWN + || event.keycode == KeyEvent.KEYCODE_VOLUME_UP)) { + // when keyguard is showing and screen off, we need + // to handle the volume key for calls and music here + if (isInCall()) { + handleVolumeKey(AudioManager.STREAM_VOICE_CALL, event.keycode); + } else if (isMusicActive()) { + handleVolumeKey(AudioManager.STREAM_MUSIC, event.keycode); + } + } + } + } + } else if (!screenIsOn) { + // If we are in-call with screen off and keyguard is not showing, + // then handle the volume key ourselves. + // This is necessary because the phone app will disable the keyguard + // when the proximity sensor is in use. + if (isInCall() && event.type == RawInputEvent.EV_KEY && + (event.keycode == KeyEvent.KEYCODE_VOLUME_DOWN + || event.keycode == KeyEvent.KEYCODE_VOLUME_UP)) { + result &= ~ACTION_PASS_TO_USER; + handleVolumeKey(AudioManager.STREAM_VOICE_CALL, event.keycode); + } + if (isWakeKey) { + // a wake key has a sole purpose of waking the device; don't pass + // it to the user + result |= ACTION_POKE_USER_ACTIVITY; + result &= ~ACTION_PASS_TO_USER; + } + } + + int type = event.type; + int code = event.keycode; + boolean down = event.value != 0; + + if (type == RawInputEvent.EV_KEY) { + if (code == KeyEvent.KEYCODE_ENDCALL + || code == KeyEvent.KEYCODE_POWER) { + if (down) { + boolean handled = false; + boolean hungUp = false; + // key repeats are generated by the window manager, and we don't see them + // here, so unless the driver is doing something it shouldn't be, we know + // this is the real press event. + ITelephony phoneServ = getPhoneInterface(); + if (phoneServ != null) { + try { + if (code == KeyEvent.KEYCODE_ENDCALL) { + handled = hungUp = phoneServ.endCall(); + } else if (code == KeyEvent.KEYCODE_POWER) { + if (phoneServ.isRinging()) { + // Pressing Power while there's a ringing incoming + // call should silence the ringer. + phoneServ.silenceRinger(); + handled = true; + } else if (phoneServ.isOffhook() && + ((mIncallPowerBehavior + & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) + != 0)) { + // Otherwise, if "Power button ends call" is enabled, + // the Power button will hang up any current active call. + handled = hungUp = phoneServ.endCall(); + } + } + } catch (RemoteException ex) { + Log.w(TAG, "ITelephony threw RemoteException" + ex); + } + } else { + Log.w(TAG, "!!! Unable to find ITelephony interface !!!"); + } + + if (!screenIsOn + || (handled && code != KeyEvent.KEYCODE_POWER) + || (handled && hungUp && code == KeyEvent.KEYCODE_POWER)) { + mShouldTurnOffOnKeyUp = false; + } else { + // only try to turn off the screen if we didn't already hang up + mShouldTurnOffOnKeyUp = true; + mHandler.postDelayed(mPowerLongPress, + ViewConfiguration.getGlobalActionKeyTimeout()); + result &= ~ACTION_PASS_TO_USER; + } + } else { + mHandler.removeCallbacks(mPowerLongPress); + if (mShouldTurnOffOnKeyUp) { + mShouldTurnOffOnKeyUp = false; + boolean gohome, sleeps; + if (code == KeyEvent.KEYCODE_ENDCALL) { + gohome = (mEndcallBehavior + & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0; + sleeps = (mEndcallBehavior + & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0; + } else { + gohome = false; + sleeps = true; + } + if (keyguardActive + || (sleeps && !gohome) + || (gohome && !goHome() && sleeps)) { + // they must already be on the keyguad or home screen, + // go to sleep instead + Log.d(TAG, "I'm tired mEndcallBehavior=0x" + + Integer.toHexString(mEndcallBehavior)); + result &= ~ACTION_POKE_USER_ACTIVITY; + result |= ACTION_GO_TO_SLEEP; + } + result &= ~ACTION_PASS_TO_USER; + } + } + } else if (isMediaKey(code)) { + // This key needs to be handled even if the screen is off. + // If others need to be handled while it's off, this is a reasonable + // pattern to follow. + if ((result & ACTION_PASS_TO_USER) == 0) { + // Only do this if we would otherwise not pass it to the user. In that + // case, the PhoneWindow class will do the same thing, except it will + // only do it if the showing app doesn't process the key on its own. + KeyEvent keyEvent = new KeyEvent(event.when, event.when, + down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP, + code, 0); + mBroadcastWakeLock.acquire(); + mHandler.post(new PassHeadsetKey(keyEvent)); + } + } else if (code == KeyEvent.KEYCODE_CALL) { + // If an incoming call is ringing, answer it! + // (We handle this key here, rather than in the InCallScreen, to make + // sure we'll respond to the key even if the InCallScreen hasn't come to + // the foreground yet.) + + // We answer the call on the DOWN event, to agree with + // the "fallback" behavior in the InCallScreen. + if (down) { + try { + ITelephony phoneServ = getPhoneInterface(); + if (phoneServ != null) { + if (phoneServ.isRinging()) { + Log.i(TAG, "interceptKeyTq:" + + " CALL key-down while ringing: Answer the call!"); + phoneServ.answerRingingCall(); + + // And *don't* pass this key thru to the current activity + // (which is presumably the InCallScreen.) + result &= ~ACTION_PASS_TO_USER; + } + } else { + Log.w(TAG, "CALL button: Unable to find ITelephony interface"); + } + } catch (RemoteException ex) { + Log.w(TAG, "CALL button: RemoteException from getPhoneInterface()", ex); + } + } + } else if ((code == KeyEvent.KEYCODE_VOLUME_UP) + || (code == KeyEvent.KEYCODE_VOLUME_DOWN)) { + // If an incoming call is ringing, either VOLUME key means + // "silence ringer". We handle these keys here, rather than + // in the InCallScreen, to make sure we'll respond to them + // even if the InCallScreen hasn't come to the foreground yet. + + // Look for the DOWN event here, to agree with the "fallback" + // behavior in the InCallScreen. + if (down) { + try { + ITelephony phoneServ = getPhoneInterface(); + if (phoneServ != null) { + if (phoneServ.isRinging()) { + Log.i(TAG, "interceptKeyTq:" + + " VOLUME key-down while ringing: Silence ringer!"); + // Silence the ringer. (It's safe to call this + // even if the ringer has already been silenced.) + phoneServ.silenceRinger(); + + // And *don't* pass this key thru to the current activity + // (which is probably the InCallScreen.) + result &= ~ACTION_PASS_TO_USER; + } + } else { + Log.w(TAG, "VOLUME button: Unable to find ITelephony interface"); + } + } catch (RemoteException ex) { + Log.w(TAG, "VOLUME button: RemoteException from getPhoneInterface()", ex); + } + } + } + } + + return result; + } + + class PassHeadsetKey implements Runnable { + KeyEvent mKeyEvent; + + PassHeadsetKey(KeyEvent keyEvent) { + mKeyEvent = keyEvent; + } + + public void run() { + if (ActivityManagerNative.isSystemReady()) { + Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); + intent.putExtra(Intent.EXTRA_KEY_EVENT, mKeyEvent); + mContext.sendOrderedBroadcast(intent, null, mBroadcastDone, + mHandler, Activity.RESULT_OK, null, null); + } + } + } + + BroadcastReceiver mBroadcastDone = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + mBroadcastWakeLock.release(); + } + }; + + BroadcastReceiver mDockReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { + mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, + Intent.EXTRA_DOCK_STATE_UNDOCKED); + } else { + try { + IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( + ServiceManager.getService(Context.UI_MODE_SERVICE)); + mUiMode = uiModeService.getCurrentModeType(); + } catch (RemoteException e) { + } + } + updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + updateOrientationListenerLp(); + } + }; + + /** {@inheritDoc} */ + public boolean isWakeRelMovementTq(int device, int classes, + RawInputEvent event) { + // if it's tagged with one of the wake bits, it wakes up the device + return ((event.flags & (FLAG_WAKE | FLAG_WAKE_DROPPED)) != 0); + } + + /** {@inheritDoc} */ + public boolean isWakeAbsMovementTq(int device, int classes, + RawInputEvent event) { + // if it's tagged with one of the wake bits, it wakes up the device + return ((event.flags & (FLAG_WAKE | FLAG_WAKE_DROPPED)) != 0); + } + + /** + * Given the current state of the world, should this key wake up the device? + */ + protected boolean isWakeKeyTq(RawInputEvent event) { + // There are not key maps for trackball devices, but we'd still + // like to have pressing it wake the device up, so force it here. + int keycode = event.keycode; + int flags = event.flags; + if (keycode == RawInputEvent.BTN_MOUSE) { + flags |= WindowManagerPolicy.FLAG_WAKE; + } + return (flags + & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; + } + + /** {@inheritDoc} */ + public void screenTurnedOff(int why) { + EventLog.writeEvent(70000, 0); + mKeyguardMediator.onScreenTurnedOff(why); + synchronized (mLock) { + mScreenOn = false; + updateOrientationListenerLp(); + updateLockScreenTimeout(); + } + } + + /** {@inheritDoc} */ + public void screenTurnedOn() { + EventLog.writeEvent(70000, 1); + mKeyguardMediator.onScreenTurnedOn(); + synchronized (mLock) { + mScreenOn = true; + updateOrientationListenerLp(); + updateLockScreenTimeout(); + } + } + + /** {@inheritDoc} */ + public boolean isScreenOn() { + return mScreenOn; + } + + /** {@inheritDoc} */ + public void enableKeyguard(boolean enabled) { + mKeyguardMediator.setKeyguardEnabled(enabled); + } + + /** {@inheritDoc} */ + public void exitKeyguardSecurely(OnKeyguardExitResult callback) { + mKeyguardMediator.verifyUnlock(callback); + } + + private boolean keyguardIsShowingTq() { + return mKeyguardMediator.isShowingAndNotHidden(); + } + + /** {@inheritDoc} */ + public boolean inKeyguardRestrictedKeyInputMode() { + return mKeyguardMediator.isInputRestricted(); + } + + void sendCloseSystemWindows() { + sendCloseSystemWindows(mContext, null); + } + + void sendCloseSystemWindows(String reason) { + sendCloseSystemWindows(mContext, reason); + } + + static void sendCloseSystemWindows(Context context, String reason) { + if (ActivityManagerNative.isSystemReady()) { + try { + ActivityManagerNative.getDefault().closeSystemDialogs(reason); + } catch (RemoteException e) { + } + } + } + + public int rotationForOrientationLw(int orientation, int lastRotation, + boolean displayEnabled) { + + if (mPortraitRotation < 0) { + // Initialize the rotation angles for each orientation once. + Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay(); + if (d.getWidth() > d.getHeight()) { + mPortraitRotation = Surface.ROTATION_90; + mLandscapeRotation = Surface.ROTATION_0; + } else { + mPortraitRotation = Surface.ROTATION_0; + mLandscapeRotation = Surface.ROTATION_90; + } + } + + synchronized (mLock) { + switch (orientation) { + case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: + //always return landscape if orientation set to landscape + return mLandscapeRotation; + case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: + //always return portrait if orientation set to portrait + return mPortraitRotation; + } + // case for nosensor meaning ignore sensor and consider only lid + // or orientation sensor disabled + //or case.unspecified + if (mLidOpen) { + return mLidOpenRotation; + } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) { + return mCarDockRotation; + } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) { + return mDeskDockRotation; + } else { + if (useSensorForOrientationLp(orientation)) { + // If the user has enabled auto rotation by default, do it. + int curRotation = mOrientationListener.getCurrentRotation(); + return curRotation >= 0 ? curRotation : lastRotation; + } + return Surface.ROTATION_0; + } + } + } + + public boolean detectSafeMode() { + try { + int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU); + int sState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_S); + int dpadState = mWindowManager.getDPadKeycodeState(KeyEvent.KEYCODE_DPAD_CENTER); + int trackballState = mWindowManager.getTrackballScancodeState(RawInputEvent.BTN_MOUSE); + mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0; + performHapticFeedbackLw(null, mSafeMode + ? HapticFeedbackConstants.SAFE_MODE_ENABLED + : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); + if (mSafeMode) { + Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState + + " dpad=" + dpadState + " trackball=" + trackballState + ")"); + } else { + Log.i(TAG, "SAFE MODE not enabled"); + } + return mSafeMode; + } catch (RemoteException e) { + // Doom! (it's also local) + throw new RuntimeException("window manager dead"); + } + } + + static long[] getLongIntArray(Resources r, int resid) { + int[] ar = r.getIntArray(resid); + if (ar == null) { + return null; + } + long[] out = new long[ar.length]; + for (int i=0; i= 0) { + rotation = mCarDockRotation; + } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) { + rotation = mDeskDockRotation; + } + //if lid is closed orientation will be portrait + try { + //set orientation on WindowManager + mWindowManager.setRotation(rotation, true, + mFancyRotationAnimation | animFlags); + } catch (RemoteException e) { + // Ignore + } + } + + /** + * Return an Intent to launch the currently active dock as home. Returns + * null if the standard home should be launched. + * @return + */ + Intent createHomeDockIntent() { + Intent intent; + + // What home does is based on the mode, not the dock state. That + // is, when in car mode you should be taken to car home regardless + // of whether we are actually in a car dock. + if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { + intent = mCarDockIntent; + } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { + intent = mDeskDockIntent; + } else { + return null; + } + + ActivityInfo ai = intent.resolveActivityInfo( + mContext.getPackageManager(), PackageManager.GET_META_DATA); + if (ai == null) { + return null; + } + + if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { + intent = new Intent(intent); + intent.setClassName(ai.packageName, ai.name); + return intent; + } + + return null; + } + + void startDockOrHome() { + Intent dock = createHomeDockIntent(); + if (dock != null) { + try { + mContext.startActivity(dock); + return; + } catch (ActivityNotFoundException e) { + } + } + mContext.startActivity(mHomeIntent); + } + + /** + * goes to the home screen + * @return whether it did anything + */ + boolean goHome() { + if (false) { + // This code always brings home to the front. + try { + ActivityManagerNative.getDefault().stopAppSwitches(); + } catch (RemoteException e) { + } + sendCloseSystemWindows(); + startDockOrHome(); + } else { + // This code brings home to the front or, if it is already + // at the front, puts the device to sleep. + try { + if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { + /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. + Log.d(TAG, "UTS-TEST-MODE"); + } else { + ActivityManagerNative.getDefault().stopAppSwitches(); + sendCloseSystemWindows(); + Intent dock = createHomeDockIntent(); + if (dock != null) { + int result = ActivityManagerNative.getDefault() + .startActivity(null, dock, + dock.resolveTypeIfNeeded(mContext.getContentResolver()), + null, 0, null, null, 0, true /* onlyIfNeeded*/, false); + if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) { + return false; + } + } + } + int result = ActivityManagerNative.getDefault() + .startActivity(null, mHomeIntent, + mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), + null, 0, null, null, 0, true /* onlyIfNeeded*/, false); + if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) { + return false; + } + } catch (RemoteException ex) { + // bummer, the activity manager, which is in this process, is dead + } + } + return true; + } + + public void setCurrentOrientationLw(int newOrientation) { + synchronized (mLock) { + if (newOrientation != mCurrentAppOrientation) { + mCurrentAppOrientation = newOrientation; + updateOrientationListenerLp(); + } + } + } + + public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { + final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0; + if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) { + return false; + } + long[] pattern = null; + switch (effectId) { + case HapticFeedbackConstants.LONG_PRESS: + pattern = mLongPressVibePattern; + break; + case HapticFeedbackConstants.VIRTUAL_KEY: + pattern = mVirtualKeyVibePattern; + break; + case HapticFeedbackConstants.KEYBOARD_TAP: + pattern = mKeyboardTapVibePattern; + break; + case HapticFeedbackConstants.SAFE_MODE_DISABLED: + pattern = mSafeModeDisabledVibePattern; + break; + case HapticFeedbackConstants.SAFE_MODE_ENABLED: + pattern = mSafeModeEnabledVibePattern; + break; + default: + return false; + } + if (pattern.length == 1) { + // One-shot vibration + mVibrator.vibrate(pattern[0]); + } else { + // Pattern vibration + mVibrator.vibrate(pattern, -1); + } + return true; + } + + public void keyFeedbackFromInput(KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN + && (event.getFlags()&KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) { + performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); + } + } + + public void screenOnStoppedLw() { + if (!mKeyguardMediator.isShowingAndNotHidden() && mPowerManager.isScreenOn()) { + long curTime = SystemClock.uptimeMillis(); + mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT); + } + } + + public boolean allowKeyRepeat() { + // disable key repeat when screen is off + return mScreenOn; + } +} diff --git a/policy/com/android/internal/policy/impl/Policy.java b/policy/com/android/internal/policy/impl/Policy.java new file mode 100644 index 0000000000000000000000000000000000000000..17f3e912966672ab1278eae85cf9c9651fb00d7c --- /dev/null +++ b/policy/com/android/internal/policy/impl/Policy.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +import android.content.Context; +import android.util.Log; + +import com.android.internal.policy.IPolicy; +import com.android.internal.policy.impl.PhoneLayoutInflater; +import com.android.internal.policy.impl.PhoneWindow; +import com.android.internal.policy.impl.PhoneWindowManager; + +/** + * {@hide} + */ + +// Simple implementation of the policy interface that spawns the right +// set of objects +public class Policy implements IPolicy { + private static final String TAG = "PhonePolicy"; + + private static final String[] preload_classes = { + "com.android.internal.policy.impl.PhoneLayoutInflater", + "com.android.internal.policy.impl.PhoneWindow", + "com.android.internal.policy.impl.PhoneWindow$1", + "com.android.internal.policy.impl.PhoneWindow$ContextMenuCallback", + "com.android.internal.policy.impl.PhoneWindow$DecorView", + "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState", + "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState", + }; + + static { + // For performance reasons, preload some policy specific classes when + // the policy gets loaded. + for (String s : preload_classes) { + try { + Class.forName(s); + } catch (ClassNotFoundException ex) { + Log.e(TAG, "Could not preload class for phone policy: " + s); + } + } + } + + public PhoneWindow makeNewWindow(Context context) { + return new PhoneWindow(context); + } + + public PhoneLayoutInflater makeNewLayoutInflater(Context context) { + return new PhoneLayoutInflater(context); + } + + public PhoneWindowManager makeNewWindowManager() { + return new PhoneWindowManager(); + } +} diff --git a/policy/com/android/internal/policy/impl/PowerDialog.java b/policy/com/android/internal/policy/impl/PowerDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..de35bd7bd2cf865333bc89031cffba32f3c5964b --- /dev/null +++ b/policy/com/android/internal/policy/impl/PowerDialog.java @@ -0,0 +1,182 @@ +/* + * 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. + */ + +package com.android.internal.policy.impl; + +import com.android.internal.R; + +import android.app.Dialog; +import android.app.StatusBarManager; +import android.content.Context; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.LocalPowerManager; +import android.os.ServiceManager; +import android.os.SystemClock; + +import com.android.internal.app.ShutdownThread; +import com.android.internal.telephony.ITelephony; +import android.view.KeyEvent; +import android.util.Log; +import android.view.View; +import android.view.WindowManager; +import android.view.View.OnClickListener; +import android.view.View.OnKeyListener; +import android.widget.Button; + +/** + * @deprecated use {@link GlobalActions} instead. + */ +public class PowerDialog extends Dialog implements OnClickListener, + OnKeyListener { + private static final String TAG = "PowerDialog"; + + static private StatusBarManager sStatusBar; + private Button mKeyguard; + private Button mPower; + private Button mRadioPower; + private Button mSilent; + + private LocalPowerManager mPowerManager; + + public PowerDialog(Context context, LocalPowerManager powerManager) { + super(context); + mPowerManager = powerManager; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Context context = getContext(); + + if (sStatusBar == null) { + sStatusBar = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE); + } + + setContentView(com.android.internal.R.layout.power_dialog); + + getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); + if (!getContext().getResources().getBoolean( + com.android.internal.R.bool.config_sf_slowBlur)) { + getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND, + WindowManager.LayoutParams.FLAG_BLUR_BEHIND); + } + getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + + setTitle(context.getText(R.string.power_dialog)); + + mKeyguard = (Button) findViewById(R.id.keyguard); + mPower = (Button) findViewById(R.id.off); + mRadioPower = (Button) findViewById(R.id.radio_power); + mSilent = (Button) findViewById(R.id.silent); + + if (mKeyguard != null) { + mKeyguard.setOnKeyListener(this); + mKeyguard.setOnClickListener(this); + } + if (mPower != null) { + mPower.setOnClickListener(this); + } + if (mRadioPower != null) { + mRadioPower.setOnClickListener(this); + } + if (mSilent != null) { + mSilent.setOnClickListener(this); + // XXX: HACK for now hide the silent until we get mute support + mSilent.setVisibility(View.GONE); + } + + CharSequence text; + + // set the keyguard button's text + text = context.getText(R.string.screen_lock); + mKeyguard.setText(text); + mKeyguard.requestFocus(); + + try { + ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); + if (phone != null) { + text = phone.isRadioOn() ? context + .getText(R.string.turn_off_radio) : context + .getText(R.string.turn_on_radio); + } + } catch (RemoteException ex) { + // ignore it + } + + mRadioPower.setText(text); + } + + public void onClick(View v) { + this.dismiss(); + if (v == mPower) { + // shutdown by making sure radio and power are handled accordingly. + ShutdownThread.shutdown(getContext(), true); + } else if (v == mRadioPower) { + try { + ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); + if (phone != null) { + phone.toggleRadioOnOff(); + } + } catch (RemoteException ex) { + // ignore it + } + } else if (v == mSilent) { + // do something + } else if (v == mKeyguard) { + if (v.isInTouchMode()) { + // only in touch mode for the reasons explained in onKey. + this.dismiss(); + mPowerManager.goToSleep(SystemClock.uptimeMillis() + 1); + } + } + } + + public boolean onKey(View v, int keyCode, KeyEvent event) { + // The activate keyguard button needs to put the device to sleep on the + // key up event. If we try to put it to sleep on the click or down + // action + // the the up action will cause the device to wake back up. + + // Log.i(TAG, "keyCode: " + keyCode + " action: " + event.getAction()); + if (keyCode != KeyEvent.KEYCODE_DPAD_CENTER + || event.getAction() != KeyEvent.ACTION_UP) { + // Log.i(TAG, "getting out of dodge..."); + return false; + } + + // Log.i(TAG, "Clicked mKeyguard! dimissing dialog"); + this.dismiss(); + // Log.i(TAG, "onKey: turning off the screen..."); + // XXX: This is a hack for now + mPowerManager.goToSleep(event.getEventTime() + 1); + return true; + } + + public void show() { + super.show(); + Log.d(TAG, "show... disabling expand"); + sStatusBar.disable(StatusBarManager.DISABLE_EXPAND); + } + + public void dismiss() { + super.dismiss(); + Log.d(TAG, "dismiss... reenabling expand"); + sStatusBar.disable(StatusBarManager.DISABLE_NONE); + } +} diff --git a/policy/com/android/internal/policy/impl/RecentApplicationsBackground.java b/policy/com/android/internal/policy/impl/RecentApplicationsBackground.java new file mode 100644 index 0000000000000000000000000000000000000000..7c99e87928b8c63cac45c2e858c632207a93152c --- /dev/null +++ b/policy/com/android/internal/policy/impl/RecentApplicationsBackground.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2010 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. + */ + +package com.android.internal.policy.impl; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; + +/** + * A vertical linear layout. However, instead of drawing the background + * behnd the items, it draws the background outside the items based on the + * padding. If there isn't enough room to draw both, it clips the background + * instead of the contents. + */ +public class RecentApplicationsBackground extends LinearLayout { + private static final String TAG = "RecentApplicationsBackground"; + + private boolean mBackgroundSizeChanged; + private Drawable mBackground; + private Rect mTmp0 = new Rect(); + private Rect mTmp1 = new Rect(); + + public RecentApplicationsBackground(Context context) { + this(context, null); + init(); + } + + public RecentApplicationsBackground(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + private void init() { + mBackground = getBackground(); + setBackgroundDrawable(null); + setPadding(0, 0, 0, 0); + setGravity(Gravity.CENTER); + } + + @Override + protected boolean setFrame(int left, int top, int right, int bottom) { + setWillNotDraw(false); + if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { + mBackgroundSizeChanged = true; + } + return super.setFrame(left, top, right, bottom); + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return who == mBackground || super.verifyDrawable(who); + } + + @Override + protected void drawableStateChanged() { + Drawable d = mBackground; + if (d != null && d.isStateful()) { + d.setState(getDrawableState()); + } + super.drawableStateChanged(); + } + + @Override + public void draw(Canvas canvas) { + final Drawable background = mBackground; + if (background != null) { + if (mBackgroundSizeChanged) { + mBackgroundSizeChanged = false; + Rect chld = mTmp0; + Rect bkg = mTmp1; + mBackground.getPadding(bkg); + getChildBounds(chld); + // This doesn't clamp to this view's bounds, which is what we want, + // so that the drawing is clipped. + final int top = chld.top - bkg.top; + final int bottom = chld.bottom + bkg.bottom; + // The background here is a gradient that wants to + // extend the full width of the screen (whatever that + // may be). + int left, right; + if (false) { + // This limits the width of the drawable. + left = chld.left - bkg.left; + right = chld.right + bkg.right; + } else { + // This expands it to full width. + left = 0; + right = getRight(); + } + background.setBounds(left, top, right, bottom); + } + } + mBackground.draw(canvas); + + if (false) { + android.graphics.Paint p = new android.graphics.Paint(); + p.setColor(0x88ffff00); + canvas.drawRect(background.getBounds(), p); + } + canvas.drawARGB((int)(0.75*0xff), 0, 0, 0); + + super.draw(canvas); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mBackground.setCallback(this); + setWillNotDraw(false); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mBackground.setCallback(null); + } + + private void getChildBounds(Rect r) { + r.left = r.top = Integer.MAX_VALUE; + r.bottom = r.right = Integer.MIN_VALUE; + final int N = getChildCount(); + for (int i=0; i recentTasks = + am.getRecentTasks(MAX_RECENT_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE); + + ActivityInfo homeInfo = + new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME) + .resolveActivityInfo(pm, 0); + + IconUtilities iconUtilities = new IconUtilities(getContext()); + + // Performance note: Our android performance guide says to prefer Iterator when + // using a List class, but because we know that getRecentTasks() always returns + // an ArrayList<>, we'll use a simple index instead. + int index = 0; + int numTasks = recentTasks.size(); + for (int i = 0; i < numTasks && (index < NUM_BUTTONS); ++i) { + final ActivityManager.RecentTaskInfo info = recentTasks.get(i); + + // for debug purposes only, disallow first result to create empty lists + if (DBG_FORCE_EMPTY_LIST && (i == 0)) continue; + + Intent intent = new Intent(info.baseIntent); + if (info.origActivity != null) { + intent.setComponent(info.origActivity); + } + + // Skip the current home activity. + if (homeInfo != null) { + if (homeInfo.packageName.equals( + intent.getComponent().getPackageName()) + && homeInfo.name.equals( + intent.getComponent().getClassName())) { + continue; + } + } + + intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) + | Intent.FLAG_ACTIVITY_NEW_TASK); + final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0); + if (resolveInfo != null) { + final ActivityInfo activityInfo = resolveInfo.activityInfo; + final String title = activityInfo.loadLabel(pm).toString(); + Drawable icon = activityInfo.loadIcon(pm); + + if (title != null && title.length() > 0 && icon != null) { + final TextView tv = mIcons[index]; + tv.setText(title); + icon = iconUtilities.createIconDrawable(icon); + tv.setCompoundDrawables(null, icon, null, null); + tv.setTag(intent); + tv.setVisibility(View.VISIBLE); + tv.setPressed(false); + tv.clearFocus(); + ++index; + } + } + } + + // handle the case of "no icons to show" + mNoAppsText.setVisibility((index == 0) ? View.VISIBLE : View.GONE); + + // hide the rest + for (; index < NUM_BUTTONS; ++index) { + mIcons[index].setVisibility(View.GONE); + } + } + + /** + * This is the listener for the ACTION_CLOSE_SYSTEM_DIALOGS intent. It's an indication that + * we should close ourselves immediately, in order to allow a higher-priority UI to take over + * (e.g. phone call received). + */ + private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { + String reason = intent.getStringExtra(PhoneWindowManager.SYSTEM_DIALOG_REASON_KEY); + if (! PhoneWindowManager.SYSTEM_DIALOG_REASON_RECENT_APPS.equals(reason)) { + dismiss(); + } + } + } + }; +} diff --git a/policy/com/android/internal/policy/impl/ShortcutManager.java b/policy/com/android/internal/policy/impl/ShortcutManager.java new file mode 100644 index 0000000000000000000000000000000000000000..d86ac44cf87fb8501803edde79369268f6e1e72f --- /dev/null +++ b/policy/com/android/internal/policy/impl/ShortcutManager.java @@ -0,0 +1,120 @@ +/* + * 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. + */ + +package com.android.internal.policy.impl; + +import android.content.Context; +import android.content.Intent; +import android.database.ContentObserver; +import android.database.Cursor; +import android.os.Handler; +import android.provider.Settings; +import android.util.Log; +import android.util.SparseArray; +import android.view.KeyCharacterMap; + +import java.net.URISyntaxException; + +/** + * Manages quick launch shortcuts by: + *
  • Keeping the local copy in sync with the database (this is an observer) + *
  • Returning a shortcut-matching intent to clients + */ +class ShortcutManager extends ContentObserver { + + private static final String TAG = "ShortcutManager"; + + private static final int COLUMN_SHORTCUT = 0; + private static final int COLUMN_INTENT = 1; + private static final String[] sProjection = new String[] { + Settings.Bookmarks.SHORTCUT, Settings.Bookmarks.INTENT + }; + + private Context mContext; + private Cursor mCursor; + /** Map of a shortcut to its intent. */ + private SparseArray mShortcutIntents; + + public ShortcutManager(Context context, Handler handler) { + super(handler); + + mContext = context; + mShortcutIntents = new SparseArray(); + } + + /** Observes the provider of shortcut+intents */ + public void observe() { + mCursor = mContext.getContentResolver().query( + Settings.Bookmarks.CONTENT_URI, sProjection, null, null, null); + mCursor.registerContentObserver(this); + updateShortcuts(); + } + + @Override + public void onChange(boolean selfChange) { + updateShortcuts(); + } + + private void updateShortcuts() { + Cursor c = mCursor; + if (!c.requery()) { + Log.e(TAG, "ShortcutObserver could not re-query shortcuts."); + return; + } + + mShortcutIntents.clear(); + while (c.moveToNext()) { + int shortcut = c.getInt(COLUMN_SHORTCUT); + if (shortcut == 0) continue; + String intentURI = c.getString(COLUMN_INTENT); + Intent intent = null; + try { + intent = Intent.getIntent(intentURI); + } catch (URISyntaxException e) { + Log.w(TAG, "Intent URI for shortcut invalid.", e); + } + if (intent == null) continue; + mShortcutIntents.put(shortcut, intent); + } + } + + /** + * Gets the shortcut intent for a given keycode+modifier. Make sure you + * strip whatever modifier is used for invoking shortcuts (for example, + * if 'Sym+A' should invoke a shortcut on 'A', you should strip the + * 'Sym' bit from the modifiers before calling this method. + *

    + * This will first try an exact match (with modifiers), and then try a + * match without modifiers (primary character on a key). + * + * @param keyCode The keycode of the key pushed. + * @param modifiers The modifiers without any that are used for chording + * to invoke a shortcut. + * @return The intent that matches the shortcut, or null if not found. + */ + public Intent getIntent(int keyCode, int modifiers) { + KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD); + // First try the exact keycode (with modifiers) + int shortcut = kcm.get(keyCode, modifiers); + Intent intent = shortcut != 0 ? mShortcutIntents.get(shortcut) : null; + if (intent != null) return intent; + + // Next try the keycode without modifiers (the primary character on that key) + shortcut = Character.toLowerCase(kcm.get(keyCode, 0)); + return shortcut != 0 ? mShortcutIntents.get(shortcut) : null; + } + +} diff --git a/policy/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/com/android/internal/policy/impl/SimUnlockScreen.java new file mode 100644 index 0000000000000000000000000000000000000000..5518e11ab6392a76e4793068679ba25d817517b0 --- /dev/null +++ b/policy/com/android/internal/policy/impl/SimUnlockScreen.java @@ -0,0 +1,423 @@ +/* + * Copyright (C) 2008 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. + */ + +package com.android.internal.policy.impl; + +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.res.Configuration; +import android.os.RemoteException; +import android.os.ServiceManager; + +import com.android.internal.telephony.ITelephony; +import com.android.internal.widget.LockPatternUtils; + +import android.text.Editable; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; +import com.android.internal.R; + +/** + * Displays a dialer like interface to unlock the SIM PIN. + */ +public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, View.OnClickListener, + KeyguardUpdateMonitor.InfoCallback { + + private static final int DIGIT_PRESS_WAKE_MILLIS = 5000; + + private final KeyguardUpdateMonitor mUpdateMonitor; + private final KeyguardScreenCallback mCallback; + + private TextView mHeaderText; + private TextView mPinText; + + private TextView mOkButton; + private Button mEmergencyCallButton; + + private View mBackSpaceButton; + + private final int[] mEnteredPin = {0, 0, 0, 0, 0, 0, 0, 0}; + private int mEnteredDigits = 0; + + private ProgressDialog mSimUnlockProgressDialog = null; + + private LockPatternUtils mLockPatternUtils; + + private int mCreationOrientation; + + private int mKeyboardHidden; + + private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + + public SimUnlockScreen(Context context, Configuration configuration, + KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback, + LockPatternUtils lockpatternutils) { + super(context); + mUpdateMonitor = updateMonitor; + mCallback = callback; + + mCreationOrientation = configuration.orientation; + mKeyboardHidden = configuration.hardKeyboardHidden; + mLockPatternUtils = lockpatternutils; + + LayoutInflater inflater = LayoutInflater.from(context); + if (mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) { + inflater.inflate(R.layout.keyguard_screen_sim_pin_landscape, this, true); + } else { + inflater.inflate(R.layout.keyguard_screen_sim_pin_portrait, this, true); + new TouchInput(); + } + + mHeaderText = (TextView) findViewById(R.id.headerText); + mPinText = (TextView) findViewById(R.id.pinDisplay); + mBackSpaceButton = findViewById(R.id.backspace); + mBackSpaceButton.setOnClickListener(this); + + mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall); + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); + mOkButton = (TextView) findViewById(R.id.ok); + + mHeaderText.setText(R.string.keyguard_password_enter_pin_code); + mPinText.setFocusable(false); + + mEmergencyCallButton.setOnClickListener(this); + mOkButton.setOnClickListener(this); + + setFocusableInTouchMode(true); + } + + /** {@inheritDoc} */ + public boolean needsInput() { + return true; + } + + /** {@inheritDoc} */ + public void onPause() { + + } + + /** {@inheritDoc} */ + public void onResume() { + // start fresh + mHeaderText.setText(R.string.keyguard_password_enter_pin_code); + + // make sure that the number of entered digits is consistent when we + // erase the SIM unlock code, including orientation changes. + mPinText.setText(""); + mEnteredDigits = 0; + + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); + } + + /** {@inheritDoc} */ + public void cleanUp() { + // hide the dialog. + if (mSimUnlockProgressDialog != null) { + mSimUnlockProgressDialog.hide(); + } + mUpdateMonitor.removeCallback(this); + } + + + /** + * Since the IPC can block, we want to run the request in a separate thread + * with a callback. + */ + private abstract class CheckSimPin extends Thread { + + private final String mPin; + + protected CheckSimPin(String pin) { + mPin = pin; + } + + abstract void onSimLockChangedResponse(boolean success); + + @Override + public void run() { + try { + final boolean result = ITelephony.Stub.asInterface(ServiceManager + .checkService("phone")).supplyPin(mPin); + post(new Runnable() { + public void run() { + onSimLockChangedResponse(result); + } + }); + } catch (RemoteException e) { + post(new Runnable() { + public void run() { + onSimLockChangedResponse(false); + } + }); + } + } + } + + public void onClick(View v) { + if (v == mBackSpaceButton) { + final Editable digits = mPinText.getEditableText(); + final int len = digits.length(); + if (len > 0) { + digits.delete(len-1, len); + mEnteredDigits--; + } + mCallback.pokeWakelock(); + } else if (v == mEmergencyCallButton) { + mCallback.takeEmergencyCallAction(); + } else if (v == mOkButton) { + checkPin(); + } + } + + private Dialog getSimUnlockProgressDialog() { + if (mSimUnlockProgressDialog == null) { + mSimUnlockProgressDialog = new ProgressDialog(mContext); + mSimUnlockProgressDialog.setMessage( + mContext.getString(R.string.lockscreen_sim_unlock_progress_dialog_message)); + mSimUnlockProgressDialog.setIndeterminate(true); + mSimUnlockProgressDialog.setCancelable(false); + mSimUnlockProgressDialog.getWindow().setType( + WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + if (!mContext.getResources().getBoolean( + com.android.internal.R.bool.config_sf_slowBlur)) { + mSimUnlockProgressDialog.getWindow().setFlags( + WindowManager.LayoutParams.FLAG_BLUR_BEHIND, + WindowManager.LayoutParams.FLAG_BLUR_BEHIND); + } + } + return mSimUnlockProgressDialog; + } + + private void checkPin() { + + // make sure that the pin is at least 4 digits long. + if (mEnteredDigits < 4) { + // otherwise, display a message to the user, and don't submit. + mHeaderText.setText(R.string.invalidPin); + mPinText.setText(""); + mEnteredDigits = 0; + mCallback.pokeWakelock(); + return; + } + getSimUnlockProgressDialog().show(); + + new CheckSimPin(mPinText.getText().toString()) { + void onSimLockChangedResponse(boolean success) { + if (mSimUnlockProgressDialog != null) { + mSimUnlockProgressDialog.hide(); + } + if (success) { + // before closing the keyguard, report back that + // the sim is unlocked so it knows right away + mUpdateMonitor.reportSimPinUnlocked(); + mCallback.goToUnlockScreen(); + } else { + mHeaderText.setText(R.string.keyguard_password_wrong_pin_code); + mPinText.setText(""); + mEnteredDigits = 0; + } + mCallback.pokeWakelock(); + } + }.start(); + } + + + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + mCallback.goToLockScreen(); + return true; + } + + final char match = event.getMatch(DIGITS); + if (match != 0) { + reportDigit(match - '0'); + return true; + } + if (keyCode == KeyEvent.KEYCODE_DEL) { + if (mEnteredDigits > 0) { + mPinText.onKeyDown(keyCode, event); + mEnteredDigits--; + } + return true; + } + + if (keyCode == KeyEvent.KEYCODE_ENTER) { + checkPin(); + return true; + } + + return false; + } + + private void reportDigit(int digit) { + if (mEnteredDigits == 0) { + mPinText.setText(""); + } + if (mEnteredDigits == 8) { + return; + } + mPinText.append(Integer.toString(digit)); + mEnteredPin[mEnteredDigits++] = digit; + } + + void updateConfiguration() { + Configuration newConfig = getResources().getConfiguration(); + if (newConfig.orientation != mCreationOrientation) { + mCallback.recreateMe(newConfig); + } else if (newConfig.hardKeyboardHidden != mKeyboardHidden) { + mKeyboardHidden = newConfig.hardKeyboardHidden; + final boolean isKeyboardOpen = mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO; + if (mUpdateMonitor.isKeyguardBypassEnabled() && isKeyboardOpen) { + mCallback.goToUnlockScreen(); + } + } + + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + updateConfiguration(); + } + + /** {@inheritDoc} */ + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + updateConfiguration(); + } + + /** + * Helper class to handle input from touch dialer. Only relevant when + * the keyboard is shut. + */ + private class TouchInput implements View.OnClickListener { + private TextView mZero; + private TextView mOne; + private TextView mTwo; + private TextView mThree; + private TextView mFour; + private TextView mFive; + private TextView mSix; + private TextView mSeven; + private TextView mEight; + private TextView mNine; + private TextView mCancelButton; + + private TouchInput() { + mZero = (TextView) findViewById(R.id.zero); + mOne = (TextView) findViewById(R.id.one); + mTwo = (TextView) findViewById(R.id.two); + mThree = (TextView) findViewById(R.id.three); + mFour = (TextView) findViewById(R.id.four); + mFive = (TextView) findViewById(R.id.five); + mSix = (TextView) findViewById(R.id.six); + mSeven = (TextView) findViewById(R.id.seven); + mEight = (TextView) findViewById(R.id.eight); + mNine = (TextView) findViewById(R.id.nine); + mCancelButton = (TextView) findViewById(R.id.cancel); + + mZero.setText("0"); + mOne.setText("1"); + mTwo.setText("2"); + mThree.setText("3"); + mFour.setText("4"); + mFive.setText("5"); + mSix.setText("6"); + mSeven.setText("7"); + mEight.setText("8"); + mNine.setText("9"); + + mZero.setOnClickListener(this); + mOne.setOnClickListener(this); + mTwo.setOnClickListener(this); + mThree.setOnClickListener(this); + mFour.setOnClickListener(this); + mFive.setOnClickListener(this); + mSix.setOnClickListener(this); + mSeven.setOnClickListener(this); + mEight.setOnClickListener(this); + mNine.setOnClickListener(this); + mCancelButton.setOnClickListener(this); + } + + + public void onClick(View v) { + if (v == mCancelButton) { + mCallback.goToLockScreen(); + return; + } + + final int digit = checkDigit(v); + if (digit >= 0) { + mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS); + reportDigit(digit); + } + } + + private int checkDigit(View v) { + int digit = -1; + if (v == mZero) { + digit = 0; + } else if (v == mOne) { + digit = 1; + } else if (v == mTwo) { + digit = 2; + } else if (v == mThree) { + digit = 3; + } else if (v == mFour) { + digit = 4; + } else if (v == mFive) { + digit = 5; + } else if (v == mSix) { + digit = 6; + } else if (v == mSeven) { + digit = 7; + } else if (v == mEight) { + digit = 8; + } else if (v == mNine) { + digit = 9; + } + return digit; + } + } + + public void onPhoneStateChanged(String newState) { + mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); + } + + public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { + + } + + public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { + + } + + public void onRingerModeChanged(int state) { + + } + + public void onTimeChanged() { + + } +} diff --git a/policy/com/android/internal/policy/impl/package.html b/policy/com/android/internal/policy/impl/package.html new file mode 100644 index 0000000000000000000000000000000000000000..c9f96a66ab3bc86235e6c4a3fe28bbaa96c12c9b --- /dev/null +++ b/policy/com/android/internal/policy/impl/package.html @@ -0,0 +1,5 @@ + + +{@hide} + + diff --git a/preloaded-classes b/preloaded-classes index 1a058fd1aab564fde6ad9f026afa3acd2662eba0..f300fe7ff3a0d5bea07c8eb21b4f006d43ac94de 100644 --- a/preloaded-classes +++ b/preloaded-classes @@ -269,7 +269,6 @@ android.location.ILocationManager$Stub android.location.ILocationManager$Stub$Proxy android.location.Location android.location.LocationManager -android.location.LocationProviderInterface android.media.AudioFormat android.media.AudioManager android.media.AudioRecord @@ -633,7 +632,6 @@ com.android.internal.appwidget.IAppWidgetService$Stub com.android.internal.content.SyncStateContentProviderHelper com.android.internal.graphics.NativeUtils com.android.internal.location.DummyLocationProvider -com.android.internal.location.GpsLocationProvider com.android.internal.logging.AndroidHandler com.android.internal.os.AndroidPrintStream com.android.internal.os.BinderInternal diff --git a/services/java/Android.mk b/services/java/Android.mk index 934712cb2ce0cd4175769c3ecf77c322ee64b54b..c756d29f104ebfc2850b9c8c098ec5b899845fa8 100644 --- a/services/java/Android.mk +++ b/services/java/Android.mk @@ -13,7 +13,9 @@ LOCAL_MODULE:= services LOCAL_JAVA_LIBRARIES := android.policy +LOCAL_NO_EMMA_INSTRUMENT := true +LOCAL_NO_EMMA_COMPILE := true + include $(BUILD_JAVA_LIBRARY) include $(BUILD_DROIDDOC) - diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index 24526af68240623901971a2ace22431303679055..dc5fd30c15d51e7ac9848bbfee1cd74d9bd095c3 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -869,7 +869,7 @@ class AppWidgetService extends IAppWidgetService.Stub out.startTag(null, "p"); out.attribute(null, "pkg", p.info.provider.getPackageName()); out.attribute(null, "cl", p.info.provider.getClassName()); - out.endTag(null, "h"); + out.endTag(null, "p"); p.tag = providerIndex; providerIndex++; } diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index d67dde0b75c4d60f6ddfc5c81adba1f874402c86..2c388ee2480c8c7a1aef334999e2b20a284721c5 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -421,7 +421,7 @@ class BackupManagerService extends IBackupManager.Stub { Settings.Secure.BACKUP_AUTO_RESTORE, 1) != 0; // If Encrypted file systems is enabled or disabled, this call will return the // correct directory. - mBaseStateDir = new File(Environment.getDataDirectory(), "backup"); + mBaseStateDir = new File(Environment.getSecureDataDirectory(), "backup"); mBaseStateDir.mkdirs(); mDataDir = Environment.getDownloadCacheDirectory(); diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 0c205ca835664f5cec8424e342836f646b347f7f..5bf66e4d128287789c0ada3afdc2933028fb2412 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -889,13 +889,27 @@ public class InputMethodManagerService extends IInputMethodManager.Stub MSG_UNBIND_METHOD, mCurSeq, mCurClient.client)); } } + + private void finishSession(SessionState sessionState) { + if (sessionState != null && sessionState.session != null) { + try { + sessionState.session.finishSession(); + } catch (RemoteException e) { + Slog.w(TAG, "Session failed to close due to remote exception", e); + } + } + } void clearCurMethodLocked() { if (mCurMethod != null) { for (ClientState cs : mClients.values()) { cs.sessionRequested = false; + finishSession(cs.curSession); cs.curSession = null; } + + finishSession(mEnabledSession); + mEnabledSession = null; mCurMethod = null; } mStatusBar.setIconVisibility(mInputMethodIcon, false); diff --git a/services/java/com/android/server/Installer.java b/services/java/com/android/server/Installer.java index 2eaa58cfa548ce7c7484cb9d7ef859de102b930b..1f34eba59e9d6dacdffef019385246f346e0db14 100644 --- a/services/java/com/android/server/Installer.java +++ b/services/java/com/android/server/Installer.java @@ -166,11 +166,17 @@ class Installer { } } - public int install(String name, int uid, int gid) { + public int install(String name, boolean useEncryptedFilesystem, int uid, int gid) { StringBuilder builder = new StringBuilder("install"); builder.append(' '); builder.append(name); builder.append(' '); + if (useEncryptedFilesystem) { + builder.append('1'); + } else { + builder.append('0'); + } + builder.append(' '); builder.append(uid); builder.append(' '); builder.append(gid); @@ -203,33 +209,57 @@ class Installer { return execute(builder.toString()); } - public int remove(String name) { + public int remove(String name, boolean useEncryptedFilesystem) { StringBuilder builder = new StringBuilder("remove"); builder.append(' '); builder.append(name); + builder.append(' '); + if (useEncryptedFilesystem) { + builder.append('1'); + } else { + builder.append('0'); + } return execute(builder.toString()); } - public int rename(String oldname, String newname) { + public int rename(String oldname, String newname, boolean useEncryptedFilesystem) { StringBuilder builder = new StringBuilder("rename"); builder.append(' '); builder.append(oldname); builder.append(' '); builder.append(newname); + builder.append(' '); + if (useEncryptedFilesystem) { + builder.append('1'); + } else { + builder.append('0'); + } return execute(builder.toString()); } - public int deleteCacheFiles(String name) { + public int deleteCacheFiles(String name, boolean useEncryptedFilesystem) { StringBuilder builder = new StringBuilder("rmcache"); builder.append(' '); builder.append(name); + builder.append(' '); + if (useEncryptedFilesystem) { + builder.append('1'); + } else { + builder.append('0'); + } return execute(builder.toString()); } - public int clearUserData(String name) { + public int clearUserData(String name, boolean useEncryptedFilesystem) { StringBuilder builder = new StringBuilder("rmuserdata"); builder.append(' '); builder.append(name); + builder.append(' '); + if (useEncryptedFilesystem) { + builder.append('1'); + } else { + builder.append('0'); + } return execute(builder.toString()); } @@ -263,7 +293,7 @@ class Installer { } public int getSizeInfo(String pkgName, String apkPath, - String fwdLockApkPath, PackageStats pStats) { + String fwdLockApkPath, PackageStats pStats, boolean useEncryptedFilesystem) { StringBuilder builder = new StringBuilder("getsize"); builder.append(' '); builder.append(pkgName); @@ -271,6 +301,13 @@ class Installer { builder.append(apkPath); builder.append(' '); builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!"); + builder.append(' '); + if (useEncryptedFilesystem) { + builder.append('1'); + } else { + builder.append('0'); + } + String s = transaction(builder.toString()); String res[] = s.split(" "); diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index 65f4194512fc0b61a1e9d37afbf9399385305a48..8519e2ce1edd795f01765f2eddc54946771f5e69 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -16,17 +16,6 @@ package com.android.server; -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Observable; -import java.util.Observer; -import java.util.Set; - import android.app.Activity; import android.app.PendingIntent; import android.content.BroadcastReceiver; @@ -41,6 +30,7 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.Cursor; import android.location.Address; +import android.location.Criteria; import android.location.GeocoderParams; import android.location.IGpsStatusListener; import android.location.IGpsStatusProvider; @@ -50,7 +40,6 @@ import android.location.INetInitiatedListener; import android.location.Location; import android.location.LocationManager; import android.location.LocationProvider; -import android.location.LocationProviderInterface; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; @@ -68,12 +57,27 @@ import android.util.Log; import android.util.Slog; import android.util.PrintWriterPrinter; -import com.android.internal.location.GeocoderProxy; -import com.android.internal.location.GpsLocationProvider; import com.android.internal.location.GpsNetInitiatedHandler; -import com.android.internal.location.LocationProviderProxy; -import com.android.internal.location.MockProvider; -import com.android.internal.location.PassiveProvider; + +import com.android.server.location.GeocoderProxy; +import com.android.server.location.GpsLocationProvider; +import com.android.server.location.LocationProviderInterface; +import com.android.server.location.LocationProviderProxy; +import com.android.server.location.MockProvider; +import com.android.server.location.PassiveProvider; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Observable; +import java.util.Observer; +import java.util.Set; /** * The service class that manages LocationProviders and issues location @@ -609,10 +613,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run return out; } - public List getProviders(boolean enabledOnly) { + public List getProviders(Criteria criteria, boolean enabledOnly) { try { synchronized (mLock) { - return _getProvidersLocked(enabledOnly); + return _getProvidersLocked(criteria, enabledOnly); } } catch (SecurityException se) { throw se; @@ -622,7 +626,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } - private List _getProvidersLocked(boolean enabledOnly) { + private List _getProvidersLocked(Criteria criteria, boolean enabledOnly) { if (LOCAL_LOGV) { Slog.v(TAG, "getProviders"); } @@ -634,12 +638,225 @@ public class LocationManagerService extends ILocationManager.Stub implements Run if (enabledOnly && !isAllowedBySettingsLocked(name)) { continue; } + if (criteria != null && !p.meetsCriteria(criteria)) { + continue; + } out.add(name); } } return out; } + /** + * Returns the next looser power requirement, in the sequence: + * + * POWER_LOW -> POWER_MEDIUM -> POWER_HIGH -> NO_REQUIREMENT + */ + private int nextPower(int power) { + switch (power) { + case Criteria.POWER_LOW: + return Criteria.POWER_MEDIUM; + case Criteria.POWER_MEDIUM: + return Criteria.POWER_HIGH; + case Criteria.POWER_HIGH: + return Criteria.NO_REQUIREMENT; + case Criteria.NO_REQUIREMENT: + default: + return Criteria.NO_REQUIREMENT; + } + } + + /** + * Returns the next looser accuracy requirement, in the sequence: + * + * ACCURACY_FINE -> ACCURACY_APPROXIMATE-> NO_REQUIREMENT + */ + private int nextAccuracy(int accuracy) { + if (accuracy == Criteria.ACCURACY_FINE) { + return Criteria.ACCURACY_COARSE; + } else { + return Criteria.NO_REQUIREMENT; + } + } + + private class LpPowerComparator implements Comparator { + public int compare(LocationProviderInterface l1, LocationProviderInterface l2) { + // Smaller is better + return (l1.getPowerRequirement() - l2.getPowerRequirement()); + } + + public boolean equals(LocationProviderInterface l1, LocationProviderInterface l2) { + return (l1.getPowerRequirement() == l2.getPowerRequirement()); + } + } + + private class LpAccuracyComparator implements Comparator { + public int compare(LocationProviderInterface l1, LocationProviderInterface l2) { + // Smaller is better + return (l1.getAccuracy() - l2.getAccuracy()); + } + + public boolean equals(LocationProviderInterface l1, LocationProviderInterface l2) { + return (l1.getAccuracy() == l2.getAccuracy()); + } + } + + private class LpCapabilityComparator implements Comparator { + + private static final int ALTITUDE_SCORE = 4; + private static final int BEARING_SCORE = 4; + private static final int SPEED_SCORE = 4; + + private int score(LocationProviderInterface p) { + return (p.supportsAltitude() ? ALTITUDE_SCORE : 0) + + (p.supportsBearing() ? BEARING_SCORE : 0) + + (p.supportsSpeed() ? SPEED_SCORE : 0); + } + + public int compare(LocationProviderInterface l1, LocationProviderInterface l2) { + return (score(l2) - score(l1)); // Bigger is better + } + + public boolean equals(LocationProviderInterface l1, LocationProviderInterface l2) { + return (score(l1) == score(l2)); + } + } + + private LocationProviderInterface best(List providerNames) { + ArrayList providers; + synchronized (mLock) { + providers = new ArrayList(mProviders.size()); + for (int i = mProviders.size() - 1; i >= 0; i--) { + providers.add(mProviders.get(i)); + } + } + + if (providers.size() < 2) { + return providers.get(0); + } + + // First, sort by power requirement + Collections.sort(providers, new LpPowerComparator()); + int power = providers.get(0).getPowerRequirement(); + if (power < providers.get(1).getPowerRequirement()) { + return providers.get(0); + } + + int idx, size; + + ArrayList tmp = new ArrayList(); + idx = 0; + size = providers.size(); + while ((idx < size) && (providers.get(idx).getPowerRequirement() == power)) { + tmp.add(providers.get(idx)); + idx++; + } + + // Next, sort by accuracy + Collections.sort(tmp, new LpAccuracyComparator()); + int acc = tmp.get(0).getAccuracy(); + if (acc < tmp.get(1).getAccuracy()) { + return tmp.get(0); + } + + ArrayList tmp2 = new ArrayList(); + idx = 0; + size = tmp.size(); + while ((idx < size) && (tmp.get(idx).getAccuracy() == acc)) { + tmp2.add(tmp.get(idx)); + idx++; + } + + // Finally, sort by capability "score" + Collections.sort(tmp2, new LpCapabilityComparator()); + return tmp2.get(0); + } + + /** + * Returns the name of the provider that best meets the given criteria. Only providers + * that are permitted to be accessed by the calling activity will be + * returned. If several providers meet the criteria, the one with the best + * accuracy is returned. If no provider meets the criteria, + * the criteria are loosened in the following sequence: + * + *

      + *
    • power requirement + *
    • accuracy + *
    • bearing + *
    • speed + *
    • altitude + *
    + * + *

    Note that the requirement on monetary cost is not removed + * in this process. + * + * @param criteria the criteria that need to be matched + * @param enabledOnly if true then only a provider that is currently enabled is returned + * @return name of the provider that best matches the requirements + */ + public String getBestProvider(Criteria criteria, boolean enabledOnly) { + List goodProviders = getProviders(criteria, enabledOnly); + if (!goodProviders.isEmpty()) { + return best(goodProviders).getName(); + } + + // Make a copy of the criteria that we can modify + criteria = new Criteria(criteria); + + // Loosen power requirement + int power = criteria.getPowerRequirement(); + while (goodProviders.isEmpty() && (power != Criteria.NO_REQUIREMENT)) { + power = nextPower(power); + criteria.setPowerRequirement(power); + goodProviders = getProviders(criteria, enabledOnly); + } + if (!goodProviders.isEmpty()) { + return best(goodProviders).getName(); + } + + // Loosen accuracy requirement + int accuracy = criteria.getAccuracy(); + while (goodProviders.isEmpty() && (accuracy != Criteria.NO_REQUIREMENT)) { + accuracy = nextAccuracy(accuracy); + criteria.setAccuracy(accuracy); + goodProviders = getProviders(criteria, enabledOnly); + } + if (!goodProviders.isEmpty()) { + return best(goodProviders).getName(); + } + + // Remove bearing requirement + criteria.setBearingRequired(false); + goodProviders = getProviders(criteria, enabledOnly); + if (!goodProviders.isEmpty()) { + return best(goodProviders).getName(); + } + + // Remove speed requirement + criteria.setSpeedRequired(false); + goodProviders = getProviders(criteria, enabledOnly); + if (!goodProviders.isEmpty()) { + return best(goodProviders).getName(); + } + + // Remove altitude requirement + criteria.setAltitudeRequired(false); + goodProviders = getProviders(criteria, enabledOnly); + if (!goodProviders.isEmpty()) { + return best(goodProviders).getName(); + } + + return null; + } + + public boolean providerMeetsCriteria(String provider, Criteria criteria) { + LocationProviderInterface p = mProvidersByName.get(provider); + if (p == null) { + throw new IllegalArgumentException("provider=" + provider); + } + return p.meetsCriteria(criteria); + } + private void updateProvidersLocked() { for (int i = mProviders.size() - 1; i >= 0; i--) { LocationProviderInterface p = mProviders.get(i); @@ -716,6 +933,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run final Receiver mReceiver; final long mMinTime; final float mMinDistance; + final boolean mSingleShot; final int mUid; Location mLastFixBroadcast; long mLastStatusBroadcast; @@ -723,12 +941,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Run /** * Note: must be constructed with lock held. */ - UpdateRecord(String provider, long minTime, float minDistance, + UpdateRecord(String provider, long minTime, float minDistance, boolean singleShot, Receiver receiver, int uid) { mProvider = provider; mReceiver = receiver; mMinTime = minTime; mMinDistance = minDistance; + mSingleShot = singleShot; mUid = uid; ArrayList records = mRecordsByProvider.get(provider); @@ -763,6 +982,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run pw.println(prefix + this); pw.println(prefix + "mProvider=" + mProvider + " mReceiver=" + mReceiver); pw.println(prefix + "mMinTime=" + mMinTime + " mMinDistance=" + mMinDistance); + pw.println(prefix + "mSingleShot=" + mSingleShot); pw.println(prefix + "mUid=" + mUid); pw.println(prefix + "mLastFixBroadcast:"); if (mLastFixBroadcast != null) { @@ -818,12 +1038,21 @@ public class LocationManagerService extends ILocationManager.Stub implements Run return false; } - public void requestLocationUpdates(String provider, - long minTime, float minDistance, ILocationListener listener) { - + public void requestLocationUpdates(String provider, Criteria criteria, + long minTime, float minDistance, boolean singleShot, ILocationListener listener) { + if (criteria != null) { + // FIXME - should we consider using multiple providers simultaneously + // rather than only the best one? + // Should we do anything different for single shot fixes? + provider = getBestProvider(criteria, true); + if (provider == null) { + throw new IllegalArgumentException("no providers found for criteria"); + } + } try { synchronized (mLock) { - requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(listener)); + requestLocationUpdatesLocked(provider, minTime, minDistance, singleShot, + getReceiver(listener)); } } catch (SecurityException se) { throw se; @@ -834,11 +1063,21 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } - public void requestLocationUpdatesPI(String provider, - long minTime, float minDistance, PendingIntent intent) { + public void requestLocationUpdatesPI(String provider, Criteria criteria, + long minTime, float minDistance, boolean singleShot, PendingIntent intent) { + if (criteria != null) { + // FIXME - should we consider using multiple providers simultaneously + // rather than only the best one? + // Should we do anything different for single shot fixes? + provider = getBestProvider(criteria, true); + if (provider == null) { + throw new IllegalArgumentException("no providers found for criteria"); + } + } try { synchronized (mLock) { - requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(intent)); + requestLocationUpdatesLocked(provider, minTime, minDistance, singleShot, + getReceiver(intent)); } } catch (SecurityException se) { throw se; @@ -849,8 +1088,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } - private void requestLocationUpdatesLocked(String provider, - long minTime, float minDistance, Receiver receiver) { + private void requestLocationUpdatesLocked(String provider, long minTime, float minDistance, + boolean singleShot, Receiver receiver) { if (LOCAL_LOGV) { Slog.v(TAG, "_requestLocationUpdates: listener = " + receiver); } @@ -867,7 +1106,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run boolean newUid = !providerHasListener(provider, callingUid, null); long identity = Binder.clearCallingIdentity(); try { - UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, receiver, callingUid); + UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, singleShot, + receiver, callingUid); UpdateRecord oldRecord = receiver.mUpdateRecords.put(provider, r); if (oldRecord != null) { oldRecord.disposeLocked(); @@ -881,7 +1121,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run if (isProviderEnabled) { long minTimeForProvider = getMinTimeLocked(provider); p.setMinTime(minTimeForProvider); - p.enableLocationTracking(true); + // try requesting single shot if singleShot is true, and fall back to + // regular location tracking if requestSingleShotFix() is not supported + if (!singleShot || !p.requestSingleShotFix()) { + p.enableLocationTracking(true); + } } else { // Notify the listener that updates are currently disabled receiver.callProviderEnabledLocked(provider, false); @@ -1287,7 +1531,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run for (int i = mProviders.size() - 1; i >= 0; i--) { LocationProviderInterface provider = mProviders.get(i); - requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver); + requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, + false, mProximityReceiver); } } } @@ -1485,6 +1730,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run for (int i=0; i(); - } - deadReceivers.add(receiver); + receiverDead = true; } } @@ -1509,13 +1752,18 @@ public class LocationManagerService extends ILocationManager.Stub implements Run r.mLastStatusBroadcast = newStatusUpdateTime; if (!receiver.callStatusChangedLocked(provider, status, extras)) { + receiverDead = true; Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver); - if (deadReceivers == null) { - deadReceivers = new ArrayList(); - } - if (!deadReceivers.contains(receiver)) { - deadReceivers.add(receiver); - } + } + } + + // remove receiver if it is dead or we just processed a single shot request + if (receiverDead || r.mSingleShot) { + if (deadReceivers == null) { + deadReceivers = new ArrayList(); + } + if (!deadReceivers.contains(receiver)) { + deadReceivers.add(receiver); } } } @@ -1692,6 +1940,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // Geocoder + public boolean geocoderIsImplemented() { + return mGeocodeProvider != null; + } + public String getFromLocation(double latitude, double longitude, int maxResults, GeocoderParams params, List

    addrs) { if (mGeocodeProvider != null) { diff --git a/services/java/com/android/server/MasterClearReceiver.java b/services/java/com/android/server/MasterClearReceiver.java index 27a8a7447ad7fef9480f4cf043f761d6d4d74bd3..4d04cee3952d12b524ef65743a2fe46682270346 100644 --- a/services/java/com/android/server/MasterClearReceiver.java +++ b/services/java/com/android/server/MasterClearReceiver.java @@ -39,7 +39,11 @@ public class MasterClearReceiver extends BroadcastReceiver { try { Slog.w(TAG, "!!! FACTORY RESET !!!"); - RecoverySystem.rebootWipeUserData(context); + if (intent.hasExtra("enableEFS")) { + RecoverySystem.rebootToggleEFS(context, intent.getBooleanExtra("enableEFS", false)); + } else { + RecoverySystem.rebootWipeUserData(context); + } Log.wtf(TAG, "Still running after master clear?!"); } catch (IOException e) { Slog.e(TAG, "Can't perform master clear/factory reset", e); diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index 6ceeb95852ec6c9995f6adb2f52fc55dc4da9cdd..413d66f3ddf9c1448045dc6b0cbef9f024fbdc95 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -642,10 +642,20 @@ class MountService extends IMountService.Stub } private boolean doGetShareMethodAvailable(String method) { - ArrayList rsp = mConnector.doCommand("share status " + method); + try { + ArrayList rsp = mConnector.doCommand("share status " + method); + } catch (NativeDaemonConnectorException ex) { + Slog.e(TAG, "Failed to determine whether share method " + method + " is available."); + return false; + } for (String line : rsp) { - String []tok = line.split(" "); + String[] tok = line.split(" "); + if (tok.length < 3) { + Slog.e(TAG, "Malformed response to share status " + method); + return false; + } + int code; try { code = Integer.parseInt(tok[0]); @@ -770,10 +780,22 @@ class MountService extends IMountService.Stub private boolean doGetVolumeShared(String path, String method) { String cmd = String.format("volume shared %s %s", path, method); - ArrayList rsp = mConnector.doCommand(cmd); + ArrayList rsp; + + try { + rsp = mConnector.doCommand(cmd); + } catch (NativeDaemonConnectorException ex) { + Slog.e(TAG, "Failed to read response to volume shared " + path + " " + method); + return false; + } for (String line : rsp) { - String []tok = line.split(" "); + String[] tok = line.split(" "); + if (tok.length < 3) { + Slog.e(TAG, "Malformed response to volume shared " + path + " " + method + " command"); + return false; + } + int code; try { code = Integer.parseInt(tok[0]); @@ -782,9 +804,7 @@ class MountService extends IMountService.Stub return false; } if (code == VoldResponseCode.ShareEnabledResult) { - if (tok[2].equals("enabled")) - return true; - return false; + return "enabled".equals(tok[2]); } else { Slog.e(TAG, String.format("Unexpected response code %d", code)); return false; diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java index 08d7ce6b30afd91bb68d981fa5350c8995ebd87e..c45259064c4529be9f1711c9e97aaacea19ebe08 100644 --- a/services/java/com/android/server/NativeDaemonConnector.java +++ b/services/java/com/android/server/NativeDaemonConnector.java @@ -128,12 +128,11 @@ final class NativeDaemonConnector implements Runnable { Slog.e(TAG, String.format( "Error handling '%s'", event), ex); } - } else { - try { - mResponseQueue.put(event); - } catch (InterruptedException ex) { - Slog.e(TAG, "Failed to put response onto queue", ex); - } + } + try { + mResponseQueue.put(event); + } catch (InterruptedException ex) { + Slog.e(TAG, "Failed to put response onto queue", ex); } } catch (NumberFormatException nfe) { Slog.w(TAG, String.format("Bad msg (%s)", event)); diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index cbbc7bedcd2490e7e4218d1626de4a07bfb5d552..c15615064fccb4fc0fe66fac037407c7df56f498 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -35,6 +35,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.Slog; import java.util.ArrayList; +import java.util.NoSuchElementException; import java.util.StringTokenizer; import android.provider.Settings; import android.content.ContentResolver; @@ -226,44 +227,61 @@ class NetworkManagementService extends INetworkManagementService.Stub { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); - return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult); + try { + return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Cannot communicate with native daemon to list interfaces"); + } } public InterfaceConfiguration getInterfaceConfig(String iface) throws IllegalStateException { - String rsp = mConnector.doCommand("interface getcfg " + iface).get(0); + String rsp; + try { + rsp = mConnector.doCommand("interface getcfg " + iface).get(0); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Cannot communicate with native daemon to get interface config"); + } Slog.d(TAG, String.format("rsp <%s>", rsp)); // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz.zzz.zzz.zzz [flag1 flag2 flag3] StringTokenizer st = new StringTokenizer(rsp); + InterfaceConfiguration cfg; try { - int code = Integer.parseInt(st.nextToken(" ")); - if (code != NetdResponseCode.InterfaceGetCfgResult) { + try { + int code = Integer.parseInt(st.nextToken(" ")); + if (code != NetdResponseCode.InterfaceGetCfgResult) { + throw new IllegalStateException( + String.format("Expected code %d, but got %d", + NetdResponseCode.InterfaceGetCfgResult, code)); + } + } catch (NumberFormatException nfe) { throw new IllegalStateException( - String.format("Expected code %d, but got %d", - NetdResponseCode.InterfaceGetCfgResult, code)); + String.format("Invalid response from daemon (%s)", rsp)); } - } catch (NumberFormatException nfe) { - throw new IllegalStateException( - String.format("Invalid response from daemon (%s)", rsp)); - } - InterfaceConfiguration cfg = new InterfaceConfiguration(); - cfg.hwAddr = st.nextToken(" "); - try { - cfg.ipAddr = stringToIpAddr(st.nextToken(" ")); - } catch (UnknownHostException uhe) { - Slog.e(TAG, "Failed to parse ipaddr", uhe); - cfg.ipAddr = 0; - } + cfg = new InterfaceConfiguration(); + cfg.hwAddr = st.nextToken(" "); + try { + cfg.ipAddr = stringToIpAddr(st.nextToken(" ")); + } catch (UnknownHostException uhe) { + Slog.e(TAG, "Failed to parse ipaddr", uhe); + cfg.ipAddr = 0; + } - try { - cfg.netmask = stringToIpAddr(st.nextToken(" ")); - } catch (UnknownHostException uhe) { - Slog.e(TAG, "Failed to parse netmask", uhe); - cfg.netmask = 0; + try { + cfg.netmask = stringToIpAddr(st.nextToken(" ")); + } catch (UnknownHostException uhe) { + Slog.e(TAG, "Failed to parse netmask", uhe); + cfg.netmask = 0; + } + cfg.interfaceFlags = st.nextToken("]").trim() +"]"; + } catch (NoSuchElementException nsee) { + throw new IllegalStateException( + String.format("Invalid response from daemon (%s)", rsp)); } - cfg.interfaceFlags = st.nextToken("]").trim() +"]"; Slog.d(TAG, String.format("flags <%s>", cfg.interfaceFlags)); return cfg; } @@ -272,7 +290,12 @@ class NetworkManagementService extends INetworkManagementService.Stub { String iface, InterfaceConfiguration cfg) throws IllegalStateException { String cmd = String.format("interface setcfg %s %s %s %s", iface, intToIpString(cfg.ipAddr), intToIpString(cfg.netmask), cfg.interfaceFlags); - mConnector.doCommand(cmd); + try { + mConnector.doCommand(cmd); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate with native daemon to interface setcfg"); + } } public void shutdown() { @@ -289,20 +312,25 @@ class NetworkManagementService extends INetworkManagementService.Stub { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); - ArrayList rsp = mConnector.doCommand("ipfwd status"); + ArrayList rsp; + try { + rsp = mConnector.doCommand("ipfwd status"); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate with native daemon to ipfwd status"); + } for (String line : rsp) { - String []tok = line.split(" "); + String[] tok = line.split(" "); + if (tok.length < 3) { + Slog.e(TAG, "Malformed response from native daemon: " + line); + return false; + } + int code = Integer.parseInt(tok[0]); if (code == NetdResponseCode.IpFwdStatusResult) { // 211 Forwarding - if (tok.length !=2) { - throw new IllegalStateException( - String.format("Malformatted list entry '%s'", line)); - } - if (tok[2].equals("enabled")) - return true; - return false; + return "enabled".equals(tok[2]); } else { throw new IllegalStateException(String.format("Unexpected response code %d", code)); } @@ -326,29 +354,45 @@ class NetworkManagementService extends INetworkManagementService.Stub { for (String d : dhcpRange) { cmd += " " + d; } - mConnector.doCommand(cmd); + + try { + mConnector.doCommand(cmd); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Unable to communicate to native daemon"); + } } public void stopTethering() throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); - mConnector.doCommand("tether stop"); + try { + mConnector.doCommand("tether stop"); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Unable to communicate to native daemon to stop tether"); + } } public boolean isTetheringStarted() throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); - ArrayList rsp = mConnector.doCommand("tether status"); + ArrayList rsp; + try { + rsp = mConnector.doCommand("tether status"); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate to native daemon to get tether status"); + } for (String line : rsp) { - String []tok = line.split(" "); + String[] tok = line.split(" "); + if (tok.length < 3) { + throw new IllegalStateException("Malformed response for tether status: " + line); + } int code = Integer.parseInt(tok[0]); if (code == NetdResponseCode.TetherStatusResult) { // XXX: Tethering services ... - if (tok[2].equals("started")) - return true; - return false; + return "started".equals(tok[2]); } else { throw new IllegalStateException(String.format("Unexpected response code %d", code)); } @@ -359,20 +403,35 @@ class NetworkManagementService extends INetworkManagementService.Stub { public void tetherInterface(String iface) throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); - mConnector.doCommand("tether interface add " + iface); + try { + mConnector.doCommand("tether interface add " + iface); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate to native daemon for adding tether interface"); + } } public void untetherInterface(String iface) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); - mConnector.doCommand("tether interface remove " + iface); + try { + mConnector.doCommand("tether interface remove " + iface); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate to native daemon for removing tether interface"); + } } public String[] listTetheredInterfaces() throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); - return mConnector.doListCommand( - "tether interface list", NetdResponseCode.TetherInterfaceListResult); + try { + return mConnector.doListCommand( + "tether interface list", NetdResponseCode.TetherInterfaceListResult); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate to native daemon for listing tether interfaces"); + } } public void setDnsForwarders(String[] dns) throws IllegalStateException { @@ -383,7 +442,12 @@ class NetworkManagementService extends INetworkManagementService.Stub { for (String s : dns) { cmd += " " + InetAddress.getByName(s).getHostAddress(); } - mConnector.doCommand(cmd); + try { + mConnector.doCommand(cmd); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate to native daemon for setting tether dns"); + } } catch (UnknownHostException e) { throw new IllegalStateException("Error resolving dns name", e); } @@ -392,30 +456,50 @@ class NetworkManagementService extends INetworkManagementService.Stub { public String[] getDnsForwarders() throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); - return mConnector.doListCommand( - "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult); + try { + return mConnector.doListCommand( + "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate to native daemon for listing tether dns"); + } } public void enableNat(String internalInterface, String externalInterface) throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); - mConnector.doCommand( - String.format("nat enable %s %s", internalInterface, externalInterface)); + try { + mConnector.doCommand( + String.format("nat enable %s %s", internalInterface, externalInterface)); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate to native daemon for enabling NAT interface"); + } } public void disableNat(String internalInterface, String externalInterface) throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); - mConnector.doCommand( - String.format("nat disable %s %s", internalInterface, externalInterface)); + try { + mConnector.doCommand( + String.format("nat disable %s %s", internalInterface, externalInterface)); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate to native daemon for disabling NAT interface"); + } } public String[] listTtys() throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); - return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult); + try { + return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Unable to communicate to native daemon for listing TTYs"); + } } public void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr, @@ -430,31 +514,52 @@ class NetworkManagementService extends INetworkManagementService.Stub { InetAddress.getByName(dns2Addr).getHostAddress())); } catch (UnknownHostException e) { throw new IllegalStateException("Error resolving addr", e); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Error communicating to native daemon to attach pppd", e); } } public void detachPppd(String tty) throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); - mConnector.doCommand(String.format("pppd detach %s", tty)); + try { + mConnector.doCommand(String.format("pppd detach %s", tty)); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Error communicating to native daemon to detach pppd", e); + } } public void startUsbRNDIS() throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); - mConnector.doCommand("usb startrndis"); + try { + mConnector.doCommand("usb startrndis"); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Error communicating to native daemon for starting RNDIS", e); + } } public void stopUsbRNDIS() throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); - mConnector.doCommand("usb stoprndis"); + try { + mConnector.doCommand("usb stoprndis"); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Error communicating to native daemon", e); + } } public boolean isUsbRNDISStarted() throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); - ArrayList rsp = mConnector.doCommand("usb rndisstatus"); + ArrayList rsp; + try { + rsp = mConnector.doCommand("usb rndisstatus"); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Error communicating to native daemon to check RNDIS status", e); + } for (String line : rsp) { String []tok = line.split(" "); @@ -476,31 +581,35 @@ class NetworkManagementService extends INetworkManagementService.Stub { android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); - mConnector.doCommand(String.format("softap stop " + wlanIface)); - mConnector.doCommand(String.format("softap fwreload " + wlanIface + " AP")); - mConnector.doCommand(String.format("softap start " + wlanIface)); - if (wifiConfig == null) { - mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface)); - } else { - /** - * softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8] - * argv1 - wlan interface - * argv2 - softap interface - * argv3 - SSID - * argv4 - Security - * argv5 - Key - * argv6 - Channel - * argv7 - Preamble - * argv8 - Max SCB - */ - String str = String.format("softap set " + wlanIface + " " + softapIface + - " %s %s %s", convertQuotedString(wifiConfig.SSID), - wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ? - "wpa2-psk" : "open", - convertQuotedString(wifiConfig.preSharedKey)); - mConnector.doCommand(str); - } - mConnector.doCommand(String.format("softap startap")); + try { + mConnector.doCommand(String.format("softap stop " + wlanIface)); + mConnector.doCommand(String.format("softap fwreload " + wlanIface + " AP")); + mConnector.doCommand(String.format("softap start " + wlanIface)); + if (wifiConfig == null) { + mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface)); + } else { + /** + * softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8] + * argv1 - wlan interface + * argv2 - softap interface + * argv3 - SSID + * argv4 - Security + * argv5 - Key + * argv6 - Channel + * argv7 - Preamble + * argv8 - Max SCB + */ + String str = String.format("softap set " + wlanIface + " " + softapIface + + " %s %s %s", convertQuotedString(wifiConfig.SSID), + wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ? + "wpa2-psk" : "open", + convertQuotedString(wifiConfig.preSharedKey)); + mConnector.doCommand(str); + } + mConnector.doCommand(String.format("softap startap")); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Error communicating to native daemon to start softap", e); + } } private String convertQuotedString(String s) { @@ -516,7 +625,12 @@ class NetworkManagementService extends INetworkManagementService.Stub { android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); - mConnector.doCommand("softap stopap"); + try { + mConnector.doCommand("softap stopap"); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Error communicating to native daemon to stop soft AP", + e); + } } public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface) @@ -525,15 +639,19 @@ class NetworkManagementService extends INetworkManagementService.Stub { android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); - if (wifiConfig == null) { - mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface)); - } else { - String str = String.format("softap set " + wlanIface + " " + softapIface + - " %s %s %s", convertQuotedString(wifiConfig.SSID), - wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ? - "wpa2-psk" : "open", - convertQuotedString(wifiConfig.preSharedKey)); - mConnector.doCommand(str); + try { + if (wifiConfig == null) { + mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface)); + } else { + String str = String.format("softap set " + wlanIface + " " + softapIface + + " %s %s %s", convertQuotedString(wifiConfig.SSID), + wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ? "wpa2-psk" : "open", + convertQuotedString(wifiConfig.preSharedKey)); + mConnector.doCommand(str); + } + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Error communicating to native daemon to set soft AP", + e); } } @@ -541,9 +659,22 @@ class NetworkManagementService extends INetworkManagementService.Stub { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); try { - String rsp = mConnector.doCommand( - String.format("interface read%scounter %s", (rx ? "rx" : "tx"), iface)).get(0); - String []tok = rsp.split(" "); + String rsp; + try { + rsp = mConnector.doCommand( + String.format("interface read%scounter %s", (rx ? "rx" : "tx"), iface)).get(0); + } catch (NativeDaemonConnectorException e1) { + Slog.e(TAG, "Error communicating with native daemon", e1); + return -1; + } + + String[] tok = rsp.split(" "); + if (tok.length < 2) { + Slog.e(TAG, String.format("Malformed response for reading %s interface", + (rx ? "rx" : "tx"))); + return -1; + } + int code; try { code = Integer.parseInt(tok[0]); @@ -575,17 +706,34 @@ class NetworkManagementService extends INetworkManagementService.Stub { public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); - mConnector.doCommand(String.format( - "interface setthrottle %s %d %d", iface, rxKbps, txKbps)); + try { + mConnector.doCommand(String.format( + "interface setthrottle %s %d %d", iface, rxKbps, txKbps)); + } catch (NativeDaemonConnectorException e) { + Slog.e(TAG, "Error communicating with native daemon to set throttle", e); + } } private int getInterfaceThrottle(String iface, boolean rx) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); try { - String rsp = mConnector.doCommand( - String.format("interface getthrottle %s %s", iface,(rx ? "rx" : "tx"))).get(0); - String []tok = rsp.split(" "); + String rsp; + try { + rsp = mConnector.doCommand( + String.format("interface getthrottle %s %s", iface, + (rx ? "rx" : "tx"))).get(0); + } catch (NativeDaemonConnectorException e) { + Slog.e(TAG, "Error communicating with native daemon to getthrottle", e); + return -1; + } + + String[] tok = rsp.split(" "); + if (tok.length < 2) { + Slog.e(TAG, "Malformed response to getthrottle command"); + return -1; + } + int code; try { code = Integer.parseInt(tok[0]); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 5ed19a2b722e96c240f381b5fb63c7b2353221fc..599023ce9430269ffba2bea976fbdf899b929b49 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -150,6 +150,8 @@ class PackageManagerService extends IPackageManager.Stub { private static final boolean GET_CERTIFICATES = true; + private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; + private static final int REMOVE_EVENTS = FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM; private static final int ADD_EVENTS = @@ -204,6 +206,10 @@ class PackageManagerService extends IPackageManager.Stub { // This is where all application persistent data goes. final File mAppDataDir; + // If Encrypted File System feature is enabled, all application persistent data + // should go here instead. + final File mSecureAppDataDir; + // This is the object monitoring the framework dir. final FileObserver mFrameworkInstallObserver; @@ -768,6 +774,7 @@ class PackageManagerService extends IPackageManager.Stub { File dataDir = Environment.getDataDirectory(); mAppDataDir = new File(dataDir, "data"); + mSecureAppDataDir = new File(dataDir, "secure/data"); mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); if (mInstaller == null) { @@ -777,6 +784,7 @@ class PackageManagerService extends IPackageManager.Stub { File miscDir = new File(dataDir, "misc"); miscDir.mkdirs(); mAppDataDir.mkdirs(); + mSecureAppDataDir.mkdirs(); mDrmAppPrivateInstallDir.mkdirs(); } @@ -937,7 +945,9 @@ class PackageManagerService extends IPackageManager.Stub { + " no longer exists; wiping its data"; reportSettingsProblem(Log.WARN, msg); if (mInstaller != null) { - mInstaller.remove(ps.name); + // XXX how to set useEncryptedFSDir for packages that + // are not encrypted? + mInstaller.remove(ps.name, true); } } } @@ -1020,7 +1030,8 @@ class PackageManagerService extends IPackageManager.Stub { void cleanupInstallFailedPackage(PackageSetting ps) { Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name); if (mInstaller != null) { - int retCode = mInstaller.remove(ps.name); + boolean useSecureFS = useEncryptedFilesystemForPackage(ps.pkg); + int retCode = mInstaller.remove(ps.name, useSecureFS); if (retCode < 0) { Slog.w(TAG, "Couldn't remove app data directory for package: " + ps.name + ", retcode=" + retCode); @@ -1718,6 +1729,7 @@ class PackageManagerService extends IPackageManager.Stub { static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) { if (pi1.icon != pi2.icon) return false; + if (pi1.logo != pi2.logo) return false; if (pi1.protectionLevel != pi2.protectionLevel) return false; if (!compareStrings(pi1.name, pi2.name)) return false; if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false; @@ -2363,7 +2375,7 @@ class PackageManagerService extends IPackageManager.Stub { && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0 && (!mSafeMode || (p.applicationInfo.flags &ApplicationInfo.FLAG_SYSTEM) != 0)) { - finalList.add(p.applicationInfo); + finalList.add(PackageParser.generateApplicationInfo(p, flags)); } } } @@ -2743,6 +2755,11 @@ class PackageManagerService extends IPackageManager.Stub { return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED; } + + private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) { + return Environment.isEncryptedFilesystemEnabled() && + ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0); + } private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) { if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { @@ -2760,7 +2777,14 @@ class PackageManagerService extends IPackageManager.Stub { } private File getDataPathForPackage(PackageParser.Package pkg) { - return new File(mAppDataDir, pkg.packageName); + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg); + File dataPath; + if (useEncryptedFSDir) { + dataPath = new File(mSecureAppDataDir, pkg.packageName); + } else { + dataPath = new File(mAppDataDir, pkg.packageName); + } + return dataPath; } private PackageParser.Package scanPackageLI(PackageParser.Package pkg, @@ -3111,6 +3135,7 @@ class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.dataDir = dataPath.getPath(); } else { // This is a normal package, need to make its data directory. + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg); dataPath = getDataPathForPackage(pkg); boolean uidError = false; @@ -3127,7 +3152,7 @@ class PackageManagerService extends IPackageManager.Stub { // If this is a system app, we can at least delete its // current data so the application will still work. if (mInstaller != null) { - int ret = mInstaller.remove(pkgName); + int ret = mInstaller.remove(pkgName, useEncryptedFSDir); if (ret >= 0) { // Old data gone! String msg = "System package " + pkg.packageName @@ -3138,7 +3163,7 @@ class PackageManagerService extends IPackageManager.Stub { recovered = true; // And now re-install the app. - ret = mInstaller.install(pkgName, pkg.applicationInfo.uid, + ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid, pkg.applicationInfo.uid); if (ret == -1) { // Ack should not happen! @@ -3178,7 +3203,7 @@ class PackageManagerService extends IPackageManager.Stub { Log.v(TAG, "Want this data dir: " + dataPath); //invoke installer to do the actual installation if (mInstaller != null) { - int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid, + int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid, pkg.applicationInfo.uid); if(ret < 0) { // Error from installer @@ -6209,8 +6234,9 @@ class PackageManagerService extends IPackageManager.Stub { deletedPs = mSettings.mPackages.get(packageName); } if ((flags&PackageManager.DONT_DELETE_DATA) == 0) { + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p); if (mInstaller != null) { - int retCode = mInstaller.remove(packageName); + int retCode = mInstaller.remove(packageName, useEncryptedFSDir); if (retCode < 0) { Slog.w(TAG, "Couldn't remove app data or cache directory for package: " + packageName + ", retcode=" + retCode); @@ -6451,6 +6477,7 @@ class PackageManagerService extends IPackageManager.Stub { p = ps.pkg; } } + boolean useEncryptedFSDir = false; if(!dataOnly) { //need to check this only for fully installed applications @@ -6463,9 +6490,10 @@ class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "Package " + packageName + " has no applicationInfo."); return false; } + useEncryptedFSDir = useEncryptedFilesystemForPackage(p); } if (mInstaller != null) { - int retCode = mInstaller.clearUserData(packageName); + int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir); if (retCode < 0) { Slog.w(TAG, "Couldn't remove cache files for package: " + packageName); @@ -6516,8 +6544,9 @@ class PackageManagerService extends IPackageManager.Stub { Slog.w(TAG, "Package " + packageName + " has no applicationInfo."); return false; } + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p); if (mInstaller != null) { - int retCode = mInstaller.deleteCacheFiles(packageName); + int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir); if (retCode < 0) { Slog.w(TAG, "Couldn't remove cache files for package: " + packageName); @@ -6579,9 +6608,10 @@ class PackageManagerService extends IPackageManager.Stub { } publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null; } + boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p); if (mInstaller != null) { int res = mInstaller.getSizeInfo(packageName, p.mPath, - publicSrcDir, pStats); + publicSrcDir, pStats, useEncryptedFSDir); if (res < 0) { return false; } else { @@ -7091,6 +7121,12 @@ class PackageManagerService extends IPackageManager.Stub { pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion); pw.print(" supportsScreens=["); boolean first = true; + if ((ps.pkg.applicationInfo.flags & + ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) { + if (!first) pw.print(", "); + first = false; + pw.print("small"); + } if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) { if (!first) pw.print(", "); @@ -7104,10 +7140,10 @@ class PackageManagerService extends IPackageManager.Stub { pw.print("large"); } if ((ps.pkg.applicationInfo.flags & - ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) { + ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { if (!first) pw.print(", "); first = false; - pw.print("small"); + pw.print("xlarge"); } if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { @@ -7631,7 +7667,8 @@ class PackageManagerService extends IPackageManager.Stub { this.pkgFlags = pkgFlags & ( ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_FORWARD_LOCK | - ApplicationInfo.FLAG_EXTERNAL_STORAGE); + ApplicationInfo.FLAG_EXTERNAL_STORAGE | + ApplicationInfo.FLAG_NEVER_ENCRYPT); } } @@ -7898,11 +7935,17 @@ class PackageManagerService extends IPackageManager.Stub { File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); // TODO(oam): This secure dir creation needs to be moved somewhere else (later) + File systemSecureDir = new File(dataDir, "secure/system"); systemDir.mkdirs(); + systemSecureDir.mkdirs(); FileUtils.setPermissions(systemDir.toString(), FileUtils.S_IRWXU|FileUtils.S_IRWXG |FileUtils.S_IROTH|FileUtils.S_IXOTH, -1, -1); + FileUtils.setPermissions(systemSecureDir.toString(), + FileUtils.S_IRWXU|FileUtils.S_IRWXG + |FileUtils.S_IROTH|FileUtils.S_IXOTH, + -1, -1); mSettingsFilename = new File(systemDir, "packages.xml"); mBackupSettingsFilename = new File(systemDir, "packages-backup.xml"); mPackageListFilename = new File(systemDir, "packages.list"); diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 53de7d99e51771a56ea90c9cdd495edbeb9d4a08..a1c08fd1d63c477294146526135836fe11a3cda9 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -4900,8 +4900,12 @@ public class WindowManagerService extends IWindowManager.Stub mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL | Configuration.SCREENLAYOUT_LONG_NO; } else { - // Is this a large screen? - if (longSize > 640 && shortSize >= 480) { + // What size is this screen screen? + if (longSize >= 800 && shortSize >= 600) { + // SVGA or larger screens at medium density are the point + // at which we consider it to be an extra large screen. + mScreenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE; + } else if (longSize >= 640 && shortSize >= 480) { // VGA or larger screens at medium density are the point // at which we consider it to be a large screen. mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE; @@ -6526,18 +6530,30 @@ public class WindowManagerService extends IWindowManager.Stub case RawInputEvent.CLASS_KEYBOARD: KeyEvent ke = (KeyEvent)ev.event; if (ke.isDown()) { - lastKey = ke; - downTime = curTime; - keyRepeatCount = 0; lastKeyTime = curTime; - nextKeyTime = lastKeyTime - + ViewConfiguration.getLongPressTimeout(); - if (DEBUG_INPUT) Slog.v( - TAG, "Received key down: first repeat @ " - + nextKeyTime); + if (lastKey != null && + ke.getKeyCode() == lastKey.getKeyCode()) { + keyRepeatCount++; + // Arbitrary long timeout to block + // repeating here since we know that + // the device driver takes care of it. + nextKeyTime = lastKeyTime + LONG_WAIT; + if (DEBUG_INPUT) Slog.v( + TAG, "Received repeated key down"); + } else { + downTime = curTime; + keyRepeatCount = 0; + nextKeyTime = lastKeyTime + + ViewConfiguration.getLongPressTimeout(); + if (DEBUG_INPUT) Slog.v( + TAG, "Received key down: first repeat @ " + + nextKeyTime); + } + lastKey = ke; } else { lastKey = null; downTime = 0; + keyRepeatCount = 0; // Arbitrary long timeout. lastKeyTime = curTime; nextKeyTime = curTime + LONG_WAIT; @@ -6545,7 +6561,12 @@ public class WindowManagerService extends IWindowManager.Stub TAG, "Received key up: ignore repeat @ " + nextKeyTime); } - dispatchKey((KeyEvent)ev.event, 0, 0); + if (keyRepeatCount > 0) { + dispatchKey(KeyEvent.changeTimeRepeat(ke, + ke.getEventTime(), keyRepeatCount), 0, 0); + } else { + dispatchKey(ke, 0, 0); + } mQueue.recycleEvent(ev); break; case RawInputEvent.CLASS_TOUCHSCREEN: @@ -8684,7 +8705,8 @@ public class WindowManagerService extends IWindowManager.Stub for (int i=0; i= 0) { - int interval = (int)(minTime/1000); - if (interval < 1) { - interval = 1; + mFixInterval = (int)minTime; + + if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) { + if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC, + mFixInterval, 0, 0)) { + Log.e(TAG, "set_position_mode failed in setMinTime()"); + } } - mFixInterval = interval; } } @@ -802,9 +799,13 @@ public class GpsLocationProvider implements LocationProviderInterface { } public void addListener(int uid) { - Message m = Message.obtain(mHandler, ADD_LISTENER); - m.arg1 = uid; - mHandler.sendMessage(m); + synchronized (mWakeLock) { + mPendingListenerMessages++; + mWakeLock.acquire(); + Message m = Message.obtain(mHandler, ADD_LISTENER); + m.arg1 = uid; + mHandler.sendMessage(m); + } } private void handleAddListener(int uid) { @@ -826,9 +827,13 @@ public class GpsLocationProvider implements LocationProviderInterface { } public void removeListener(int uid) { - Message m = Message.obtain(mHandler, REMOVE_LISTENER); - m.arg1 = uid; - mHandler.sendMessage(m); + synchronized (mWakeLock) { + mPendingListenerMessages++; + mWakeLock.acquire(); + Message m = Message.obtain(mHandler, REMOVE_LISTENER); + m.arg1 = uid; + mHandler.sendMessage(m); + } } private void handleRemoveListener(int uid) { @@ -851,24 +856,25 @@ public class GpsLocationProvider implements LocationProviderInterface { public boolean sendExtraCommand(String command, Bundle extras) { + long identity = Binder.clearCallingIdentity(); + boolean result = false; + if ("delete_aiding_data".equals(command)) { - return deleteAidingData(extras); - } - if ("force_time_injection".equals(command)) { - mHandler.removeMessages(INJECT_NTP_TIME); - mHandler.sendMessage(Message.obtain(mHandler, INJECT_NTP_TIME)); - return true; - } - if ("force_xtra_injection".equals(command)) { + result = deleteAidingData(extras); + } else if ("force_time_injection".equals(command)) { + sendMessage(INJECT_NTP_TIME, 0, null); + result = true; + } else if ("force_xtra_injection".equals(command)) { if (native_supports_xtra()) { xtraDownloadRequest(); - return true; + result = true; } - return false; + } else { + Log.w(TAG, "sendExtraCommand: unknown command " + command); } - Log.w(TAG, "sendExtraCommand: unknown command " + command); - return false; + Binder.restoreCallingIdentity(identity); + return result; } private boolean deleteAidingData(Bundle extras) { @@ -901,19 +907,30 @@ public class GpsLocationProvider implements LocationProviderInterface { return false; } - private void startNavigating() { + private void startNavigating(boolean singleShot) { if (!mStarted) { if (DEBUG) Log.d(TAG, "startNavigating"); mStarted = true; - int positionMode; - if (Settings.Secure.getInt(mContext.getContentResolver(), + mSingleShot = singleShot; + mPositionMode = GPS_POSITION_MODE_STANDALONE; + + if (Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) { - positionMode = GPS_POSITION_MODE_MS_BASED; - } else { - positionMode = GPS_POSITION_MODE_STANDALONE; + if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) { + mPositionMode = GPS_POSITION_MODE_MS_ASSISTED; + } else if (hasCapability(GPS_CAPABILITY_MSA)) { + mPositionMode = GPS_POSITION_MODE_MS_BASED; + } } - if (!native_start(positionMode, false, 1)) { + int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000); + if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC, + interval, 0, 0)) { + mStarted = false; + Log.e(TAG, "set_position_mode failed in startNavigating()"); + return; + } + if (!native_start()) { mStarted = false; Log.e(TAG, "native_start failed in startNavigating()"); return; @@ -921,13 +938,14 @@ public class GpsLocationProvider implements LocationProviderInterface { // reset SV count to zero updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0); - mFixCount = 0; mFixRequestTime = System.currentTimeMillis(); - // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT - // and our fix interval is not short - if (mFixInterval >= NO_FIX_TIMEOUT) { - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT * 1000, mTimeoutIntent); + if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) { + // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT + // and our fix interval is not short + if (mFixInterval >= NO_FIX_TIMEOUT) { + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent); + } } } } @@ -936,6 +954,7 @@ public class GpsLocationProvider implements LocationProviderInterface { if (DEBUG) Log.d(TAG, "stopNavigating"); if (mStarted) { mStarted = false; + mSingleShot = false; native_stop(); mTTFF = 0; mLastFixTime = 0; @@ -949,12 +968,15 @@ public class GpsLocationProvider implements LocationProviderInterface { private void hibernate() { // stop GPS until our next fix interval arrives stopNavigating(); - mFixCount = 0; mAlarmManager.cancel(mTimeoutIntent); mAlarmManager.cancel(mWakeupIntent); long now = SystemClock.elapsedRealtime(); mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - SystemClock.elapsedRealtime() + mFixInterval * 1000, mWakeupIntent); + SystemClock.elapsedRealtime() + mFixInterval, mWakeupIntent); + } + + private boolean hasCapability(int capability) { + return ((mEngineCapabilities & capability) != 0); } /** @@ -965,29 +987,6 @@ public class GpsLocationProvider implements LocationProviderInterface { if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude + " timestamp: " + timestamp); - mLastFixTime = System.currentTimeMillis(); - // report time to first fix - if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) { - mTTFF = (int)(mLastFixTime - mFixRequestTime); - if (DEBUG) Log.d(TAG, "TTFF: " + mTTFF); - - // notify status listeners - synchronized(mListeners) { - int size = mListeners.size(); - for (int i = 0; i < size; i++) { - Listener listener = mListeners.get(i); - try { - listener.mListener.onFirstFix(mTTFF); - } catch (RemoteException e) { - Log.w(TAG, "RemoteException in stopNavigating"); - mListeners.remove(listener); - // adjust for size of list changing - size--; - } - } - } - } - synchronized (mLocation) { mLocationFlags = flags; if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) { @@ -1023,22 +1022,48 @@ public class GpsLocationProvider implements LocationProviderInterface { } } + mLastFixTime = System.currentTimeMillis(); + // report time to first fix + if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) { + mTTFF = (int)(mLastFixTime - mFixRequestTime); + if (DEBUG) Log.d(TAG, "TTFF: " + mTTFF); + + // notify status listeners + synchronized(mListeners) { + int size = mListeners.size(); + for (int i = 0; i < size; i++) { + Listener listener = mListeners.get(i); + try { + listener.mListener.onFirstFix(mTTFF); + } catch (RemoteException e) { + Log.w(TAG, "RemoteException in stopNavigating"); + mListeners.remove(listener); + // adjust for size of list changing + size--; + } + } + } + } + + if (mSingleShot) { + stopNavigating(); + } if (mStarted && mStatus != LocationProvider.AVAILABLE) { - // we still want to time out if we do not receive MIN_FIX_COUNT + // we want to time out if we do not receive a fix // within the time out and we are requesting infrequent fixes - if (mFixInterval < NO_FIX_TIMEOUT) { + if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) { mAlarmManager.cancel(mTimeoutIntent); } // send an intent to notify that the GPS is receiving fixes. - Intent intent = new Intent(GPS_FIX_CHANGE_ACTION); - intent.putExtra(EXTRA_ENABLED, true); + Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION); + intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true); mContext.sendBroadcast(intent); updateStatus(LocationProvider.AVAILABLE, mSvCount); } - if (mFixCount++ >= MIN_FIX_COUNT && mFixInterval > 1) { - if (DEBUG) Log.d(TAG, "exceeded MIN_FIX_COUNT"); + if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted && mFixInterval > 1000) { + if (DEBUG) Log.d(TAG, "got fix, hibernating"); hibernate(); } } @@ -1069,12 +1094,6 @@ public class GpsLocationProvider implements LocationProviderInterface { break; } - // beware, the events can come out of order - if ((mNavigating || mEngineOn) && !mWakeLock.isHeld()) { - if (DEBUG) Log.d(TAG, "Acquiring wakelock"); - mWakeLock.acquire(); - } - if (wasNavigating != mNavigating) { int size = mListeners.size(); for (int i = 0; i < size; i++) { @@ -1108,16 +1127,10 @@ public class GpsLocationProvider implements LocationProviderInterface { } // send an intent to notify that the GPS has been enabled or disabled. - Intent intent = new Intent(GPS_ENABLED_CHANGE_ACTION); - intent.putExtra(EXTRA_ENABLED, mNavigating); + Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION); + intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating); mContext.sendBroadcast(intent); } - - // beware, the events can come out of order - if (!mNavigating && !mEngineOn && mWakeLock.isHeld()) { - if (DEBUG) Log.d(TAG, "Releasing wakelock"); - mWakeLock.release(); - } } } @@ -1160,13 +1173,14 @@ public class GpsLocationProvider implements LocationProviderInterface { } } - updateStatus(mStatus, svCount); + // return number of sets used in fix instead of total + updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK])); if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 && - System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT * 1000) { + System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) { // send an intent to notify that the GPS is no longer receiving fixes. - Intent intent = new Intent(GPS_FIX_CHANGE_ACTION); - intent.putExtra(EXTRA_ENABLED, false); + Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION); + intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false); mContext.sendBroadcast(intent); updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount); } @@ -1240,13 +1254,19 @@ public class GpsLocationProvider implements LocationProviderInterface { } } + /** + * called from native code to inform us what the GPS engine capabilities are + */ + private void setEngineCapabilities(int capabilities) { + mEngineCapabilities = capabilities; + } + /** * called from native code to request XTRA data */ private void xtraDownloadRequest() { if (DEBUG) Log.d(TAG, "xtraDownloadRequest"); - mHandler.removeMessages(DOWNLOAD_XTRA_DATA); - mHandler.sendMessage(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA)); + sendMessage(DOWNLOAD_XTRA_DATA, 0, null); } //============================================================= @@ -1361,11 +1381,25 @@ public class GpsLocationProvider implements LocationProviderInterface { } } + private void sendMessage(int message, int arg, Object obj) { + // hold a wake lock while messages are pending + synchronized (mWakeLock) { + mPendingMessageBits |= (1 << message); + mWakeLock.acquire(); + mHandler.removeMessages(message); + Message m = Message.obtain(mHandler, message); + m.arg1 = arg; + m.obj = obj; + mHandler.sendMessage(m); + } + } + private final class ProviderHandler extends Handler { @Override public void handleMessage(Message msg) { - switch (msg.what) { + int message = msg.what; + switch (message) { case ENABLE: if (msg.arg1 == 1) { handleEnable(); @@ -1376,6 +1410,9 @@ public class GpsLocationProvider implements LocationProviderInterface { case ENABLE_TRACKING: handleEnableLocationTracking(msg.arg1 == 1); break; + case REQUEST_SINGLE_SHOT: + handleRequestSingleShot(); + break; case UPDATE_NETWORK_STATE: handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj); break; @@ -1397,6 +1434,16 @@ public class GpsLocationProvider implements LocationProviderInterface { handleRemoveListener(msg.arg1); break; } + // release wake lock if no messages are pending + synchronized (mWakeLock) { + mPendingMessageBits &= ~(1 << message); + if (message == ADD_LISTENER || message == REMOVE_LISTENER) { + mPendingListenerMessages--; + } + if (mPendingMessageBits == 0 && mPendingListenerMessages == 0) { + mWakeLock.release(); + } + } } }; @@ -1440,9 +1487,10 @@ public class GpsLocationProvider implements LocationProviderInterface { private native boolean native_init(); private native void native_disable(); private native void native_cleanup(); - private native boolean native_start(int positionMode, boolean singleFix, int fixInterval); + private native boolean native_set_position_mode(int mode, int recurrence, int min_interval, + int preferred_accuracy, int preferred_time); + private native boolean native_start(); private native boolean native_stop(); - private native void native_set_fix_frequency(int fixFrequency); private native void native_delete_aiding_data(int flags); private native void native_wait_for_event(); // returns number of SVs diff --git a/location/java/com/android/internal/location/GpsXtraDownloader.java b/services/java/com/android/server/location/GpsXtraDownloader.java similarity index 99% rename from location/java/com/android/internal/location/GpsXtraDownloader.java rename to services/java/com/android/server/location/GpsXtraDownloader.java index 978bda2193ae258c7932cf3061a4dc2a49f5fba3..bc9698090b5ef764a2b1f1857714e7846ec27543 100644 --- a/location/java/com/android/internal/location/GpsXtraDownloader.java +++ b/services/java/com/android/server/location/GpsXtraDownloader.java @@ -14,7 +14,13 @@ * limitations under the License. */ -package com.android.internal.location; +package com.android.server.location; + +import android.content.Context; +import android.net.Proxy; +import android.net.http.AndroidHttpClient; +import android.util.Config; +import android.util.Log; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; @@ -30,14 +36,6 @@ import java.io.IOException; import java.util.Properties; import java.util.Random; -import android.content.Context; -import android.net.Proxy; -import android.net.http.AndroidHttpClient; -import android.util.Config; -import android.util.Log; - - - /** * A class for downloading GPS XTRA data. * diff --git a/location/java/android/location/LocationProviderInterface.java b/services/java/com/android/server/location/LocationProviderInterface.java similarity index 88% rename from location/java/android/location/LocationProviderInterface.java rename to services/java/com/android/server/location/LocationProviderInterface.java index 5ffe15c359b278c996f2437054cd9e8b60ad1246..084ab81f48d243ab891d08c7495db68ae3abf872 100644 --- a/location/java/android/location/LocationProviderInterface.java +++ b/services/java/com/android/server/location/LocationProviderInterface.java @@ -14,8 +14,9 @@ * limitations under the License. */ -package android.location; +package com.android.server.location; +import android.location.Criteria; import android.location.Location; import android.net.NetworkInfo; import android.os.Bundle; @@ -35,6 +36,7 @@ public interface LocationProviderInterface { boolean supportsSpeed(); boolean supportsBearing(); int getPowerRequirement(); + boolean meetsCriteria(Criteria criteria); int getAccuracy(); boolean isEnabled(); void enable(); @@ -42,6 +44,8 @@ public interface LocationProviderInterface { int getStatus(Bundle extras); long getStatusUpdateTime(); void enableLocationTracking(boolean enable); + /* returns false if single shot is not supported */ + boolean requestSingleShotFix(); String getInternalState(); void setMinTime(long minTime); void updateNetworkState(int state, NetworkInfo info); diff --git a/location/java/com/android/internal/location/LocationProviderProxy.java b/services/java/com/android/server/location/LocationProviderProxy.java similarity index 89% rename from location/java/com/android/internal/location/LocationProviderProxy.java rename to services/java/com/android/server/location/LocationProviderProxy.java index 31ec09a4503b4bb5c44849b1e94aef458dde26b8..24d7737010dbdfff22307e32e0a397029b3dc471 100644 --- a/location/java/com/android/internal/location/LocationProviderProxy.java +++ b/services/java/com/android/server/location/LocationProviderProxy.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package com.android.internal.location; +package com.android.server.location; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.location.Criteria; import android.location.ILocationProvider; import android.location.Location; -import android.location.LocationProviderInterface; import android.net.NetworkInfo; import android.os.Bundle; import android.os.Handler; @@ -31,6 +31,8 @@ import android.os.RemoteException; import android.os.SystemClock; import android.util.Log; +import com.android.internal.location.DummyLocationProvider; + /** * A class for proxying location providers implemented as services. * @@ -96,7 +98,7 @@ public class LocationProviderProxy implements LocationProviderInterface { if (mCachedAttributes == null) { try { - mCachedAttributes = new DummyLocationProvider(mName); + mCachedAttributes = new DummyLocationProvider(mName, null); mCachedAttributes.setRequiresNetwork(provider.requiresNetwork()); mCachedAttributes.setRequiresSatellite(provider.requiresSatellite()); mCachedAttributes.setRequiresCell(provider.requiresCell()); @@ -198,6 +200,39 @@ public class LocationProviderProxy implements LocationProviderInterface { } } + public boolean meetsCriteria(Criteria criteria) { + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + } + if (provider != null) { + try { + return provider.meetsCriteria(criteria); + } catch (RemoteException e) { + } + } + // default implementation if we lost connection to the provider + if ((criteria.getAccuracy() != Criteria.NO_REQUIREMENT) && + (criteria.getAccuracy() < getAccuracy())) { + return false; + } + int criteriaPower = criteria.getPowerRequirement(); + if ((criteriaPower != Criteria.NO_REQUIREMENT) && + (criteriaPower < getPowerRequirement())) { + return false; + } + if (criteria.isAltitudeRequired() && !supportsAltitude()) { + return false; + } + if (criteria.isSpeedRequired() && !supportsSpeed()) { + return false; + } + if (criteria.isBearingRequired() && !supportsBearing()) { + return false; + } + return true; + } + public int getAccuracy() { if (mCachedAttributes != null) { return mCachedAttributes.getAccuracy(); @@ -296,6 +331,10 @@ public class LocationProviderProxy implements LocationProviderInterface { } } + public boolean requestSingleShotFix() { + return false; + } + public long getMinTime() { return mMinTime; } diff --git a/location/java/com/android/internal/location/MockProvider.java b/services/java/com/android/server/location/MockProvider.java similarity index 86% rename from location/java/com/android/internal/location/MockProvider.java rename to services/java/com/android/server/location/MockProvider.java index d912740f2e029a9502f2f489ac4c55164b5c3b2a..01b34b744ffa215b66d58fe14ce44b81ca947850 100644 --- a/location/java/com/android/internal/location/MockProvider.java +++ b/services/java/com/android/server/location/MockProvider.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.android.internal.location; +package com.android.server.location; +import android.location.Criteria; import android.location.ILocationManager; import android.location.Location; import android.location.LocationProvider; -import android.location.LocationProviderInterface; import android.net.NetworkInfo; import android.os.Bundle; import android.os.RemoteException; @@ -139,6 +139,28 @@ public class MockProvider implements LocationProviderInterface { return mSupportsSpeed; } + public boolean meetsCriteria(Criteria criteria) { + if ((criteria.getAccuracy() != Criteria.NO_REQUIREMENT) && + (criteria.getAccuracy() < mAccuracy)) { + return false; + } + int criteriaPower = criteria.getPowerRequirement(); + if ((criteriaPower != Criteria.NO_REQUIREMENT) && + (criteriaPower < mPowerRequirement)) { + return false; + } + if (criteria.isAltitudeRequired() && !mSupportsAltitude) { + return false; + } + if (criteria.isSpeedRequired() && !mSupportsSpeed) { + return false; + } + if (criteria.isBearingRequired() && !mSupportsBearing) { + return false; + } + return true; + } + public void setLocation(Location l) { mLocation.set(l); mHasLocation = true; @@ -175,6 +197,10 @@ public class MockProvider implements LocationProviderInterface { public void enableLocationTracking(boolean enable) { } + public boolean requestSingleShotFix() { + return false; + } + public void setMinTime(long minTime) { } diff --git a/location/java/com/android/internal/location/PassiveProvider.java b/services/java/com/android/server/location/PassiveProvider.java similarity index 91% rename from location/java/com/android/internal/location/PassiveProvider.java rename to services/java/com/android/server/location/PassiveProvider.java index ab909371d5b69c60e044482a5ebb91302ba564cc..7fc93f8b635ca3b39f72aa03741f2b6a0edf32f6 100644 --- a/location/java/com/android/internal/location/PassiveProvider.java +++ b/services/java/com/android/server/location/PassiveProvider.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.android.internal.location; +package com.android.server.location; +import android.location.Criteria; import android.location.ILocationManager; import android.location.Location; import android.location.LocationManager; import android.location.LocationProvider; -import android.location.LocationProviderInterface; import android.net.NetworkInfo; import android.os.Bundle; import android.os.RemoteException; @@ -80,6 +80,11 @@ public class PassiveProvider implements LocationProviderInterface { return -1; } + public boolean meetsCriteria(Criteria criteria) { + // We do not want to match the special passive provider based on criteria. + return false; + } + public int getAccuracy() { return -1; } @@ -114,6 +119,10 @@ public class PassiveProvider implements LocationProviderInterface { mTracking = enable; } + public boolean requestSingleShotFix() { + return false; + } + public void setMinTime(long minTime) { } diff --git a/services/java/com/android/server/status/StatusBarIcon.java b/services/java/com/android/server/status/StatusBarIcon.java index 6f8b8a8da6ca0a964312650b40f5cc4f8abffa33..f77b550a433f74e81dc7d865f802dd47beb3d3c7 100644 --- a/services/java/com/android/server/status/StatusBarIcon.java +++ b/services/java/com/android/server/status/StatusBarIcon.java @@ -51,14 +51,11 @@ class StatusBarIcon { switch (data.type) { case IconData.TEXT: { TextView t; - t = new TextView(context); + t = new TextView(context, null, com.android.internal.R.style.TextAppearance_StatusBar_Icon); mTextView = t; LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT); - t.setTextSize(16); - t.setTextColor(0xff000000); - t.setTypeface(Typeface.DEFAULT_BOLD); t.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); t.setPadding(6, 0, 0, 0); t.setLayoutParams(layoutParams); diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java index 94d1cb492494335e2dc94b5ef27a299f6589f69b..cab2662126a2fb196fb4321eee3de5f36e618d73 100644 --- a/services/java/com/android/server/status/StatusBarPolicy.java +++ b/services/java/com/android/server/status/StatusBarPolicy.java @@ -29,7 +29,9 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.TypedArray; import android.graphics.PixelFormat; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.location.LocationManager; import android.media.AudioManager; import android.media.Ringtone; import android.media.RingtoneManager; @@ -48,7 +50,10 @@ import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.text.format.DateFormat; +import android.text.style.CharacterStyle; import android.text.style.RelativeSizeSpan; +import android.text.style.ForegroundColorSpan; +import android.text.style.StyleSpan; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.util.Slog; @@ -62,7 +67,6 @@ import android.widget.TextView; import com.android.internal.R; import com.android.internal.app.IBatteryStats; -import com.android.internal.location.GpsLocationProvider; import com.android.internal.telephony.IccCard; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.cdma.EriInfo; @@ -86,6 +90,12 @@ public class StatusBarPolicy { // message codes for the handler private static final int EVENT_BATTERY_CLOSE = 4; + private static final int AM_PM_STYLE_NORMAL = 0; + private static final int AM_PM_STYLE_SMALL = 1; + private static final int AM_PM_STYLE_GONE = 2; + + private static final int AM_PM_STYLE = AM_PM_STYLE_GONE; + private final Context mContext; private final StatusBarService mService; private final Handler mHandler = new StatusBarHandler(); @@ -390,8 +400,8 @@ public class StatusBarPolicy { action.equals(WifiManager.RSSI_CHANGED_ACTION)) { updateWifi(intent); } - else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) || - action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION)) { + else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) || + action.equals(LocationManager.GPS_FIX_CHANGE_ACTION)) { updateGps(intent); } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) || @@ -536,8 +546,8 @@ public class StatusBarPolicy { filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); filter.addAction(WifiManager.RSSI_CHANGED_ACTION); - filter.addAction(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION); - filter.addAction(GpsLocationProvider.GPS_FIX_CHANGE_ACTION); + filter.addAction(LocationManager.GPS_ENABLED_CHANGE_ACTION); + filter.addAction(LocationManager.GPS_FIX_CHANGE_ACTION); filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); @@ -576,29 +586,31 @@ public class StatusBarPolicy { * add dummy characters around it to let us find it again after * formatting and change its size. */ - int a = -1; - boolean quoted = false; - for (int i = 0; i < format.length(); i++) { - char c = format.charAt(i); - - if (c == '\'') { - quoted = !quoted; - } + if (AM_PM_STYLE != AM_PM_STYLE_NORMAL) { + int a = -1; + boolean quoted = false; + for (int i = 0; i < format.length(); i++) { + char c = format.charAt(i); + + if (c == '\'') { + quoted = !quoted; + } - if (!quoted && c == 'a') { - a = i; - break; + if (!quoted && c == 'a') { + a = i; + break; + } } - } - if (a >= 0) { - // Move a back so any whitespace before the AM/PM is also in the alternate size. - final int b = a; - while (a > 0 && Character.isWhitespace(format.charAt(a-1))) { - a--; + if (a >= 0) { + // Move a back so any whitespace before the AM/PM is also in the alternate size. + final int b = a; + while (a > 0 && Character.isWhitespace(format.charAt(a-1))) { + a--; + } + format = format.substring(0, a) + MAGIC1 + format.substring(a, b) + + "a" + MAGIC2 + format.substring(b + 1); } - format = format.substring(0, a) + MAGIC1 + format.substring(a, b) - + "a" + MAGIC2 + format.substring(b + 1); } mClockFormat = sdf = new SimpleDateFormat(format); @@ -608,22 +620,31 @@ public class StatusBarPolicy { } String result = sdf.format(mCalendar.getTime()); - int magic1 = result.indexOf(MAGIC1); - int magic2 = result.indexOf(MAGIC2); + if (AM_PM_STYLE != AM_PM_STYLE_NORMAL) { + int magic1 = result.indexOf(MAGIC1); + int magic2 = result.indexOf(MAGIC2); - if (magic1 >= 0 && magic2 > magic1) { - SpannableStringBuilder formatted = new SpannableStringBuilder(result); + if (magic1 >= 0 && magic2 > magic1) { + SpannableStringBuilder formatted = new SpannableStringBuilder(result); - formatted.setSpan(new RelativeSizeSpan(0.7f), magic1, magic2, - Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + if (AM_PM_STYLE == AM_PM_STYLE_GONE) { + formatted.delete(magic1, magic2+1); + } else { + if (AM_PM_STYLE == AM_PM_STYLE_SMALL) { + CharacterStyle style = new RelativeSizeSpan(0.7f); + formatted.setSpan(style, magic1, magic2, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE); + } - formatted.delete(magic2, magic2 + 1); - formatted.delete(magic1, magic1 + 1); + formatted.delete(magic2, magic2 + 1); + formatted.delete(magic1, magic1 + 1); + } - return formatted; - } else { - return result; + return formatted; + } } + + return result; } private final void updateClock() { @@ -954,7 +975,9 @@ public class StatusBarPolicy { && ((mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_0) || (mServiceState.getRadioTechnology() - == ServiceState.RADIO_TECHNOLOGY_EVDO_A))); + == ServiceState.RADIO_TECHNOLOGY_EVDO_A) + || (mServiceState.getRadioTechnology() + == ServiceState.RADIO_TECHNOLOGY_EVDO_B))); } private boolean hasService() { @@ -1070,7 +1093,6 @@ public class StatusBarPolicy { } private final void updateDataNetType(int net) { - switch (net) { case TelephonyManager.NETWORK_TYPE_EDGE: mDataIconList = sDataNetType_e; @@ -1096,6 +1118,7 @@ public class StatusBarPolicy { break; case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_EVDO_B: mDataIconList = sDataNetType_3g; break; default: @@ -1179,7 +1202,7 @@ public class StatusBarPolicy { final int ringerMode = audioManager.getRingerMode(); final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT || ringerMode == AudioManager.RINGER_MODE_VIBRATE; - final int iconId = (ringerMode == AudioManager.RINGER_MODE_VIBRATE) + final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER) ? com.android.internal.R.drawable.stat_sys_ringer_vibrate : com.android.internal.R.drawable.stat_sys_ringer_silent; @@ -1290,13 +1313,13 @@ public class StatusBarPolicy { private final void updateGps(Intent intent) { final String action = intent.getAction(); - final boolean enabled = intent.getBooleanExtra(GpsLocationProvider.EXTRA_ENABLED, false); + final boolean enabled = intent.getBooleanExtra(LocationManager.EXTRA_GPS_ENABLED, false); - if (action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION) && enabled) { + if (action.equals(LocationManager.GPS_FIX_CHANGE_ACTION) && enabled) { // GPS is getting fixes mService.updateIcon(mGpsIcon, mGpsFixIconData, null); mService.setIconVisibility(mGpsIcon, true); - } else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) && !enabled) { + } else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) && !enabled) { // GPS is off mService.setIconVisibility(mGpsIcon, false); } else { diff --git a/services/jni/Android.mk b/services/jni/Android.mk index 9d2760e167c82cbd49ef696b5fdce2d5378974be..b90e327ea6e38c9bc7d6b3f8842b8fc70da8143d 100644 --- a/services/jni/Android.mk +++ b/services/jni/Android.mk @@ -9,6 +9,7 @@ LOCAL_SRC_FILES:= \ com_android_server_SensorService.cpp \ com_android_server_SystemServer.cpp \ com_android_server_VibratorService.cpp \ + com_android_server_location_GpsLocationProvider.cpp \ onload.cpp LOCAL_C_INCLUDES += \ diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/services/jni/com_android_server_location_GpsLocationProvider.cpp similarity index 87% rename from core/jni/android_location_GpsLocationProvider.cpp rename to services/jni/com_android_server_location_GpsLocationProvider.cpp index f60fe6da070a31dda70519dcdda40073a3e0af28..afd6ca89121f320d01e78533a3f02cca90d6b12d 100755 --- a/core/jni/android_location_GpsLocationProvider.cpp +++ b/services/jni/com_android_server_location_GpsLocationProvider.cpp @@ -20,8 +20,9 @@ #include "JNIHelp.h" #include "jni.h" -#include "hardware_legacy/gps.h" -#include "hardware_legacy/gps_ni.h" +#include "hardware/hardware.h" +#include "hardware/gps.h" +#include "hardware_legacy/power.h" #include "utils/Log.h" #include "utils/misc.h" @@ -35,13 +36,13 @@ static jmethodID method_reportStatus; static jmethodID method_reportSvStatus; static jmethodID method_reportAGpsStatus; static jmethodID method_reportNmea; +static jmethodID method_setEngineCapabilities; static jmethodID method_xtraDownloadRequest; static jmethodID method_reportNiNotification; static const GpsInterface* sGpsInterface = NULL; static const GpsXtraInterface* sGpsXtraInterface = NULL; static const AGpsInterface* sAGpsInterface = NULL; -static const GpsPrivacyInterface* sGpsPrivacyInterface = NULL; static const GpsNiInterface* sGpsNiInterface = NULL; static const GpsDebugInterface* sGpsDebugInterface = NULL; @@ -52,6 +53,8 @@ static GpsSvStatus sGpsSvStatus; static AGpsStatus sAGpsStatus; static GpsNiNotification sGpsNiNotification; +#define WAKE_LOCK_NAME "GPS" + // buffer for NMEA data #define NMEA_SENTENCE_LENGTH 100 #define NMEA_SENTENCE_COUNT 40 @@ -70,6 +73,8 @@ static GpsSvStatus sGpsSvStatusCopy; static AGpsStatus sAGpsStatusCopy; static NmeaSentence sNmeaBufferCopy[NMEA_SENTENCE_COUNT]; static GpsNiNotification sGpsNiNotificationCopy; +static uint32_t sEngineCapabilities; + enum CallbackType { kLocation = 1, @@ -80,6 +85,7 @@ enum CallbackType { kDisableRequest = 32, kNmeaAvailable = 64, kNiNotification = 128, + kSetCapabilities = 256, }; static int sPendingCallbacks; @@ -142,6 +148,29 @@ static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length) pthread_mutex_unlock(&sEventMutex); } +static void set_capabilities_callback(uint32_t capabilities) +{ + LOGD("set_capabilities_callback: %08X", capabilities); + + pthread_mutex_lock(&sEventMutex); + + sPendingCallbacks |= kSetCapabilities; + sEngineCapabilities = capabilities; + + pthread_cond_signal(&sEventCond); + pthread_mutex_unlock(&sEventMutex); +} + +static void acquire_wakelock_callback() +{ + acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); +} + +static void release_wakelock_callback() +{ + release_wake_lock(WAKE_LOCK_NAME); +} + static void agps_status_callback(AGpsStatus* agps_status) { pthread_mutex_lock(&sEventMutex); @@ -154,10 +183,14 @@ static void agps_status_callback(AGpsStatus* agps_status) } GpsCallbacks sGpsCallbacks = { + sizeof(GpsCallbacks), location_callback, status_callback, sv_status_callback, - nmea_callback + nmea_callback, + set_capabilities_callback, + acquire_wakelock_callback, + release_wakelock_callback, }; static void @@ -201,20 +234,39 @@ static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V"); method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II)V"); method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(IJ)V"); + method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V"); method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V"); method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification", "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V"); } +static const GpsInterface* get_gps_interface() { + int err; + hw_module_t* module; + const GpsInterface* interface = NULL; + + err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); + if (err == 0) { + hw_device_t* device; + err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device); + if (err == 0) { + gps_device_t* gps_device = (gps_device_t *)device; + interface = gps_device->get_gps_interface(gps_device); + } + } + + return interface; +} + static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz) { if (!sGpsInterface) - sGpsInterface = gps_get_interface(); + sGpsInterface = get_gps_interface(); return (sGpsInterface != NULL); } static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj) { if (!sGpsInterface) - sGpsInterface = gps_get_interface(); + sGpsInterface = get_gps_interface(); if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) return false; @@ -224,15 +276,9 @@ static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject o sAGpsInterface->init(&sAGpsCallbacks); if (!sGpsNiInterface) - sGpsNiInterface = (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE); + sGpsNiInterface = (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE); if (sGpsNiInterface) - sGpsNiInterface->init(&sGpsNiCallbacks); - - // Clear privacy lock while enabled - if (!sGpsPrivacyInterface) - sGpsPrivacyInterface = (const GpsPrivacyInterface*)sGpsInterface->get_extension(GPS_PRIVACY_INTERFACE); - if (sGpsPrivacyInterface) - sGpsPrivacyInterface->set_privacy_lock(0); + sGpsNiInterface->init(&sGpsNiCallbacks); if (!sGpsDebugInterface) sGpsDebugInterface = (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE); @@ -242,12 +288,6 @@ static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject o static void android_location_GpsLocationProvider_disable(JNIEnv* env, jobject obj) { - // Enable privacy lock while disabled - if (!sGpsPrivacyInterface) - sGpsPrivacyInterface = (const GpsPrivacyInterface*)sGpsInterface->get_extension(GPS_PRIVACY_INTERFACE); - if (sGpsPrivacyInterface) - sGpsPrivacyInterface->set_privacy_lock(1); - pthread_mutex_lock(&sEventMutex); sPendingCallbacks |= kDisableRequest; pthread_cond_signal(&sEventCond); @@ -259,14 +299,15 @@ static void android_location_GpsLocationProvider_cleanup(JNIEnv* env, jobject ob sGpsInterface->cleanup(); } -static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj, jint positionMode, - jboolean singleFix, jint fixFrequency) +static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* env, jobject obj, + jint mode, jint recurrence, jint min_interval, jint preferred_accuracy, jint preferred_time) { - int result = sGpsInterface->set_position_mode(positionMode, (singleFix ? 0 : fixFrequency)); - if (result) { - return false; - } + return (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy, + preferred_time) == 0); +} +static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj) +{ return (sGpsInterface->start() == 0); } @@ -354,6 +395,9 @@ static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, job extras ); } + if (pendingCallbacks & kSetCapabilities) { + env->CallVoidMethod(obj, method_setEngineCapabilities, sEngineCapabilities); + } } static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, jobject obj, @@ -489,10 +533,12 @@ static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jo static void android_location_GpsLocationProvider_send_ni_response(JNIEnv* env, jobject obj, jint notifId, jint response) { - if (!sGpsNiInterface) + if (!sGpsNiInterface) { sGpsNiInterface = (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE); - if (sGpsNiInterface) + } + if (sGpsNiInterface) { sGpsNiInterface->respond(notifId, response); + } } static jstring android_location_GpsLocationProvider_get_internal_state(JNIEnv* env, jobject obj) @@ -516,7 +562,8 @@ static JNINativeMethod sMethods[] = { {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init}, {"native_disable", "()V", (void*)android_location_GpsLocationProvider_disable}, {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup}, - {"native_start", "(IZI)Z", (void*)android_location_GpsLocationProvider_start}, + {"native_set_position_mode", "(IIIII)Z", (void*)android_location_GpsLocationProvider_set_position_mode}, + {"native_start", "()Z", (void*)android_location_GpsLocationProvider_start}, {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop}, {"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data}, {"native_wait_for_event", "()V", (void*)android_location_GpsLocationProvider_wait_for_event}, @@ -534,9 +581,9 @@ static JNINativeMethod sMethods[] = { {"native_get_internal_state", "()Ljava/lang/String;", (void*)android_location_GpsLocationProvider_get_internal_state}, }; -int register_android_location_GpsLocationProvider(JNIEnv* env) +int register_android_server_location_GpsLocationProvider(JNIEnv* env) { - return jniRegisterNativeMethods(env, "com/android/internal/location/GpsLocationProvider", sMethods, NELEM(sMethods)); + return jniRegisterNativeMethods(env, "com/android/server/location/GpsLocationProvider", sMethods, NELEM(sMethods)); } } /* namespace android */ diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp index c16fdb809a7a8bf5d6ed1f4bf365da6283c6bed7..d11e7e1b6b82d689be1e77c4ecea3fd63518a016 100644 --- a/services/jni/onload.cpp +++ b/services/jni/onload.cpp @@ -11,6 +11,7 @@ int register_android_server_LightsService(JNIEnv* env); int register_android_server_SensorService(JNIEnv* env); int register_android_server_VibratorService(JNIEnv* env); int register_android_server_SystemServer(JNIEnv* env); +int register_android_server_location_GpsLocationProvider(JNIEnv* env); }; using namespace android; @@ -33,6 +34,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) register_android_server_SensorService(env); register_android_server_VibratorService(env); register_android_server_SystemServer(env); + register_android_server_location_GpsLocationProvider(env); return JNI_VERSION_1_4; } diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java index ad7dfc9e28587f1fb3c443866f9646ebe16c9dc5..2f7666d118bceff8186f361be7318bacae6746d9 100644 --- a/telephony/java/android/telephony/NeighboringCellInfo.java +++ b/telephony/java/android/telephony/NeighboringCellInfo.java @@ -133,8 +133,11 @@ public class NeighboringCellInfo implements Parcelable case NETWORK_TYPE_GPRS: case NETWORK_TYPE_EDGE: mNetworkType = radioType; - mLac = Integer.valueOf(location.substring(0, 4), 16); - mCid = Integer.valueOf(location.substring(4), 16); + // check if 0xFFFFFFFF for UNKNOWN_CID + if (!location.equalsIgnoreCase("FFFFFFFF")) { + mCid = Integer.valueOf(location.substring(4), 16); + mLac = Integer.valueOf(location.substring(0, 4), 16); + } break; case NETWORK_TYPE_UMTS: case NETWORK_TYPE_HSDPA: @@ -293,4 +296,4 @@ public class NeighboringCellInfo implements Parcelable return new NeighboringCellInfo[size]; } }; -} \ No newline at end of file +} diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 32e717685fe5baf1ddf23320e5b1b640a89f4198..a60d2be0f2cd672dde963720119803b572cc8620 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -732,7 +732,8 @@ public class PhoneNumberUtils return ""; } - if ((bytes[offset] & 0xff) == TOA_International) { + //Only TON field should be taken in consideration + if ((bytes[offset] & 0xf0) == (TOA_International & 0xf0)) { prependPlus = true; } diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 6c665595cc26e74bf1ec1e9b6989702f936d8b00..35a2c196e0cf0f7cf792adedcfb740b86f128784 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -57,7 +57,7 @@ public class ServiceState implements Parcelable { public static final int STATE_EMERGENCY_ONLY = 2; /** - * Radio of telephony is explictly powered off. + * Radio of telephony is explicitly powered off. */ public static final int STATE_POWER_OFF = 3; @@ -89,6 +89,8 @@ public class ServiceState implements Parcelable { public static final int RADIO_TECHNOLOGY_HSUPA = 10; /** @hide */ public static final int RADIO_TECHNOLOGY_HSPA = 11; + /** @hide */ + public static final int RADIO_TECHNOLOGY_EVDO_B = 12; /** * Available registration states for GSM, UMTS and CDMA. @@ -218,7 +220,8 @@ public class ServiceState implements Parcelable { return 0; } - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { public ServiceState createFromParcel(Parcel in) { return new ServiceState(in); } @@ -229,7 +232,7 @@ public class ServiceState implements Parcelable { }; /** - * Get current servcie state of phone + * Get current service state of phone * * @see #STATE_IN_SERVICE * @see #STATE_OUT_OF_SERVICE @@ -288,10 +291,10 @@ public class ServiceState implements Parcelable { } /** - * Get current registered operator name in long alphanumeric format + * Get current registered operator name in long alphanumeric format. * - * In GSM/UMTS, long format can be upto 16 characters long - * In CDMA, returns the ERI text, if set, otherwise the ONS + * In GSM/UMTS, long format can be up to 16 characters long. + * In CDMA, returns the ERI text, if set. Otherwise, returns the ONS. * * @return long name of operator, null if unregistered or unknown */ @@ -300,9 +303,9 @@ public class ServiceState implements Parcelable { } /** - * Get current registered operator name in short lphanumeric format + * Get current registered operator name in short alphanumeric format. * - * In GSM/UMST, short format can be upto 8 characters long + * In GSM/UMTS, short format can be up to 8 characters long. * * @return short name of operator, null if unregistered or unknown */ @@ -311,21 +314,23 @@ public class ServiceState implements Parcelable { } /** - * Get current registered operator numeric id + * Get current registered operator numeric id. * * In GSM/UMTS, numeric format is 3 digit country code plus 2 or 3 digit - * network code - * - * The country code can be decoded using MccTable.countryCodeForMcc() + * network code. * * @return numeric format of operator, null if unregistered or unknown */ + /* + * The country code can be decoded using + * {@link com.android.internal.telephony.MccTable#countryCodeForMcc(int)}. + */ public String getOperatorNumeric() { return mOperatorNumeric; } /** - * Get current network selection mode + * Get current network selection mode. * * @return true if manual mode, false if automatic mode */ @@ -379,7 +384,6 @@ public class ServiceState implements Parcelable { @Override public String toString() { String radioTechnology = new String("Error in radioTechnology"); - switch(this.mRadioTechnology) { case 0: radioTechnology = "Unknown"; @@ -417,6 +421,9 @@ public class ServiceState implements Parcelable { case 11: radioTechnology = "HSPA"; break; + case 12: + radioTechnology = "EvDo rev. B"; + break; default: Log.w(LOG_TAG, "mRadioTechnology variable out of range."); break; @@ -454,7 +461,7 @@ public class ServiceState implements Parcelable { mIsEmergencyOnly = false; } - // TODO - can't this be combined with the above func.. + // TODO - can't this be combined with the above method? public void setStateOff() { mState = STATE_POWER_OFF; mRoaming = false; @@ -524,8 +531,8 @@ public class ServiceState implements Parcelable { } /** - * In CDMA mOperatorAlphaLong can be set from the ERI - * text, this is done from the CDMAPhone and not from the CdmaServiceStateTracker + * In CDMA, mOperatorAlphaLong can be set from the ERI text. + * This is done from the CDMAPhone and not from the CdmaServiceStateTracker. * * @hide */ @@ -538,7 +545,7 @@ public class ServiceState implements Parcelable { } /** - * Test whether two objects hold the same data values or both are null + * Test whether two objects hold the same data values or both are null. * * @param a first obj * @param b second obj @@ -549,7 +556,7 @@ public class ServiceState implements Parcelable { } /** - * Set ServiceState based on intent notifier map + * Set ServiceState based on intent notifier map. * * @param m intent notifier map * @hide @@ -571,7 +578,7 @@ public class ServiceState implements Parcelable { } /** - * Set intent notifier Bundle based on service state + * Set intent notifier Bundle based on service state. * * @param m intent notifier Bundle * @hide diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index 312272272f8580715d59de4b8ef70301f90f51e5..f5e9751b95714b4d51756f7cc8867afd6c45b25f 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -398,4 +398,6 @@ public final class SmsManager { static public final int RESULT_ERROR_NO_SERVICE = 4; /** Failed because we reached the sending queue limit. {@hide} */ static public final int RESULT_ERROR_LIMIT_EXCEEDED = 5; + /** Failed because FDN is enabled. {@hide} */ + static public final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index f018d1074a74508468dcf3bb5116be52ae620313..ab63017b0df1b9828d3d04ee73d2ca377287dfc6 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -391,6 +391,9 @@ public class TelephonyManager { public static final int NETWORK_TYPE_HSPA = 10; /** Current network is iDen */ public static final int NETWORK_TYPE_IDEN = 11; + /** Current network is EVDO revision B*/ + public static final int NETWORK_TYPE_EVDO_B = 12; + /** * Returns a constant indicating the radio technology (network type) @@ -407,6 +410,7 @@ public class TelephonyManager { * @see #NETWORK_TYPE_CDMA * @see #NETWORK_TYPE_EVDO_0 * @see #NETWORK_TYPE_EVDO_A + * @see #NETWORK_TYPE_EVDO_B * @see #NETWORK_TYPE_1xRTT */ public int getNetworkType() { @@ -454,6 +458,8 @@ public class TelephonyManager { return "CDMA - EvDo rev. 0"; case NETWORK_TYPE_EVDO_A: return "CDMA - EvDo rev. A"; + case NETWORK_TYPE_EVDO_B: + return "CDMA - EvDo rev. B"; case NETWORK_TYPE_1xRTT: return "CDMA - 1xRTT"; default: diff --git a/telephony/java/android/telephony/gsm/SmsManager.java b/telephony/java/android/telephony/gsm/SmsManager.java index 241c4852c4eb18cf567ad28aee903477fb312e4a..3b75298b593df0cbed97e42b17429abb8d5379ba 100644 --- a/telephony/java/android/telephony/gsm/SmsManager.java +++ b/telephony/java/android/telephony/gsm/SmsManager.java @@ -56,7 +56,7 @@ import java.util.ArrayList; * the current default SMSC * @param text the body of the message to send * @param sentIntent if not NULL this PendingIntent is - * broadcast when the message is sucessfully sent, or failed. + * broadcast when the message is successfully sent, or failed. * The result code will be Activity.RESULT_OK for success, * or one of these errors: * RESULT_ERROR_GENERIC_FAILURE diff --git a/telephony/java/com/android/internal/telephony/AdnRecord.java b/telephony/java/com/android/internal/telephony/AdnRecord.java index 0896ba60ee710750cf88fa7f530e8a1f4239a641..1bf2d3c61d502c17607c3e50657c1fffd72e590a 100644 --- a/telephony/java/com/android/internal/telephony/AdnRecord.java +++ b/telephony/java/com/android/internal/telephony/AdnRecord.java @@ -19,10 +19,9 @@ package com.android.internal.telephony; import android.os.Parcel; import android.os.Parcelable; import android.telephony.PhoneNumberUtils; +import android.text.TextUtils; import android.util.Log; -import com.android.internal.telephony.GsmAlphabet; - import java.util.Arrays; @@ -38,8 +37,8 @@ public class AdnRecord implements Parcelable { //***** Instance Variables - String alphaTag = ""; - String number = ""; + String alphaTag = null; + String number = null; String[] emails; int extRecord = 0xff; int efid; // or 0 if none @@ -63,8 +62,8 @@ public class AdnRecord implements Parcelable { // ADN offset static final int ADN_BCD_NUMBER_LENGTH = 0; static final int ADN_TON_AND_NPI = 1; - static final int ADN_DAILING_NUMBER_START = 2; - static final int ADN_DAILING_NUMBER_END = 11; + static final int ADN_DIALING_NUMBER_START = 2; + static final int ADN_DIALING_NUMBER_END = 11; static final int ADN_CAPABILITY_ID = 12; static final int ADN_EXTENSION_ID = 13; @@ -152,17 +151,31 @@ public class AdnRecord implements Parcelable { } public boolean isEmpty() { - return alphaTag.equals("") && number.equals("") && emails == null; + return TextUtils.isEmpty(alphaTag) && TextUtils.isEmpty(number) && emails == null; } public boolean hasExtendedRecord() { return extRecord != 0 && extRecord != 0xff; } + /** Helper function for {@link #isEqual}. */ + private static boolean stringCompareNullEqualsEmpty(String s1, String s2) { + if (s1 == s2) { + return true; + } + if (s1 == null) { + s1 = ""; + } + if (s2 == null) { + s2 = ""; + } + return (s1.equals(s2)); + } + public boolean isEqual(AdnRecord adn) { - return ( alphaTag.equals(adn.getAlphaTag()) && - number.equals(adn.getNumber()) && - Arrays.equals(emails, adn.getEmails())); + return ( stringCompareNullEqualsEmpty(alphaTag, adn.alphaTag) && + stringCompareNullEqualsEmpty(number, adn.number) && + Arrays.equals(emails, adn.emails)); } //***** Parcelable Implementation @@ -184,36 +197,33 @@ public class AdnRecord implements Parcelable { * * @param recordSize is the size X of EF record * @return hex byte[recordSize] to be written to EF record - * return nulll for wrong format of dialing nubmer or tag + * return null for wrong format of dialing number or tag */ public byte[] buildAdnString(int recordSize) { byte[] bcdNumber; byte[] byteTag; - byte[] adnString = null; + byte[] adnString; int footerOffset = recordSize - FOOTER_SIZE_BYTES; - if (number == null || number.equals("") || - alphaTag == null || alphaTag.equals("")) { + // create an empty record + adnString = new byte[recordSize]; + for (int i = 0; i < recordSize; i++) { + adnString[i] = (byte) 0xFF; + } - Log.w(LOG_TAG, "[buildAdnString] Empty alpha tag or number"); - adnString = new byte[recordSize]; - for (int i = 0; i < recordSize; i++) { - adnString[i] = (byte) 0xFF; - } + if (TextUtils.isEmpty(number)) { + Log.w(LOG_TAG, "[buildAdnString] Empty dialing number"); + return adnString; // return the empty record (for delete) } else if (number.length() - > (ADN_DAILING_NUMBER_END - ADN_DAILING_NUMBER_START + 1) * 2) { + > (ADN_DIALING_NUMBER_END - ADN_DIALING_NUMBER_START + 1) * 2) { Log.w(LOG_TAG, - "[buildAdnString] Max length of dailing number is 20"); - } else if (alphaTag.length() > footerOffset) { + "[buildAdnString] Max length of dialing number is 20"); + return null; + } else if (alphaTag != null && alphaTag.length() > footerOffset) { Log.w(LOG_TAG, "[buildAdnString] Max length of tag is " + footerOffset); + return null; } else { - - adnString = new byte[recordSize]; - for (int i = 0; i < recordSize; i++) { - adnString[i] = (byte) 0xFF; - } - bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD(number); System.arraycopy(bcdNumber, 0, adnString, @@ -222,16 +232,17 @@ public class AdnRecord implements Parcelable { adnString[footerOffset + ADN_BCD_NUMBER_LENGTH] = (byte) (bcdNumber.length); adnString[footerOffset + ADN_CAPABILITY_ID] - = (byte) 0xFF; // Capacility Id + = (byte) 0xFF; // Capability Id adnString[footerOffset + ADN_EXTENSION_ID] = (byte) 0xFF; // Extension Record Id - byteTag = GsmAlphabet.stringToGsm8BitPacked(alphaTag); - System.arraycopy(byteTag, 0, adnString, 0, byteTag.length); + if (!TextUtils.isEmpty(alphaTag)) { + byteTag = GsmAlphabet.stringToGsm8BitPacked(alphaTag); + System.arraycopy(byteTag, 0, adnString, 0, byteTag.length); + } + return adnString; } - - return adnString; } /** diff --git a/telephony/java/com/android/internal/telephony/AdnRecordLoader.java b/telephony/java/com/android/internal/telephony/AdnRecordLoader.java index cfb5aaa84b399ee8e895461cb609ddbe0b596cf2..55bdc06b8aea7b5a92275fcf9dac3ed78d28b31a 100644 --- a/telephony/java/com/android/internal/telephony/AdnRecordLoader.java +++ b/telephony/java/com/android/internal/telephony/AdnRecordLoader.java @@ -106,7 +106,7 @@ public class AdnRecordLoader extends Handler { * It will get the record size of EF record and compose hex adn array * then write the hex array to EF record * - * @param adn is set with alphaTag and phoneNubmer + * @param adn is set with alphaTag and phone number * @param ef EF fileid * @param extensionEF extension EF fileid * @param recordNumber 1-based record index @@ -159,7 +159,7 @@ public class AdnRecordLoader extends Handler { data = adn.buildAdnString(recordSize[0]); if(data == null) { - throw new RuntimeException("worong ADN format", + throw new RuntimeException("wrong ADN format", ar.exception); } @@ -218,7 +218,7 @@ public class AdnRecordLoader extends Handler { throw new RuntimeException("load failed", ar.exception); } - Log.d(LOG_TAG,"ADN extention EF: 0x" + Log.d(LOG_TAG,"ADN extension EF: 0x" + Integer.toHexString(extensionEF) + ":" + adn.extRecord + "\n" + IccUtils.bytesToHexString(data)); diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index 802e79b2cadda5da06bf6752bf35b04b16c14d56..798a5a56b8478f574c7780e0e6e43ed252dc4e6a 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -284,7 +284,7 @@ public class CallerInfoAsyncQuery { */ public static CallerInfoAsyncQuery startQuery(int token, Context context, String number, OnQueryCompleteListener listener, Object cookie) { - //contruct the URI object and start Query. + //construct the URI object and start Query. Uri contactRef = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)); CallerInfoAsyncQuery c = new CallerInfoAsyncQuery(); diff --git a/telephony/java/com/android/internal/telephony/CommandException.java b/telephony/java/com/android/internal/telephony/CommandException.java index eb0a440dff253a0aa3ebfa6a45c5e393f07e4782..94c544ecffd5c731c7bc1bcdd3e117e3253380a0 100644 --- a/telephony/java/com/android/internal/telephony/CommandException.java +++ b/telephony/java/com/android/internal/telephony/CommandException.java @@ -37,6 +37,10 @@ public class CommandException extends RuntimeException { OP_NOT_ALLOWED_DURING_VOICE_CALL, OP_NOT_ALLOWED_BEFORE_REG_NW, SMS_FAIL_RETRY, + SIM_ABSENT, + SUBSCRIPTION_NOT_AVAILABLE, + MODE_NOT_SUPPORTED, + FDN_CHECK_FAILURE, ILLEGAL_SIM_OR_ME, } @@ -69,6 +73,14 @@ public class CommandException extends RuntimeException { return new CommandException(Error.OP_NOT_ALLOWED_BEFORE_REG_NW); case RILConstants.SMS_SEND_FAIL_RETRY: return new CommandException(Error.SMS_FAIL_RETRY); + case RILConstants.SIM_ABSENT: + return new CommandException(Error.SIM_ABSENT); + case RILConstants.SUBSCRIPTION_NOT_AVAILABLE: + return new CommandException(Error.SUBSCRIPTION_NOT_AVAILABLE); + case RILConstants.MODE_NOT_SUPPORTED: + return new CommandException(Error.MODE_NOT_SUPPORTED); + case RILConstants.FDN_CHECK_FAILURE: + return new CommandException(Error.FDN_CHECK_FAILURE); case RILConstants.ILLEGAL_SIM_OR_ME: return new CommandException(Error.ILLEGAL_SIM_OR_ME); default: diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java index d90c3056bf76b71ca00993e722c133b9b5d1b808..8e03c5a5bd5e1ebac281bbab5884271880b43972 100644 --- a/telephony/java/com/android/internal/telephony/CommandsInterface.java +++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java @@ -659,6 +659,19 @@ public interface CommandsInterface { */ void dial (String address, int clirMode, Message result); + /** + * returned message + * retMsg.obj = AsyncResult ar + * ar.exception carries exception on failure + * ar.userObject contains the orignal value of result.obj + * ar.result is null on success and failure + * + * CLIR_DEFAULT == on "use subscription default value" + * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation) + * CLIR_INVOCATION == on "CLIR invocation" (restrict CLI presentation) + */ + void dial(String address, int clirMode, UUSInfo uusInfo, Message result); + /** * returned message * retMsg.obj = AsyncResult ar diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java index 37e8a99e6799f1770ab84c82db0b5b73a91eb41b..11d0b1b3a28fb3f29e5dbee9d5bc3c3b1b5926bc 100644 --- a/telephony/java/com/android/internal/telephony/Connection.java +++ b/telephony/java/com/android/internal/telephony/Connection.java @@ -45,17 +45,18 @@ public abstract class Connection { POWER_OFF, /* radio is turned off explicitly */ OUT_OF_SERVICE, /* out of service */ ICC_ERROR, /* No ICC, ICC locked, or other ICC error */ - CALL_BARRED, /* call was blocked by call barrring */ + CALL_BARRED, /* call was blocked by call barring */ FDN_BLOCKED, /* call was blocked by fixed dial number */ CS_RESTRICTED, /* call was blocked by restricted all voice access */ CS_RESTRICTED_NORMAL, /* call was blocked by restricted normal voice access */ CS_RESTRICTED_EMERGENCY, /* call was blocked by restricted emergency voice access */ + UNOBTAINABLE_NUMBER, /* Unassigned number (3GPP TS 24.008 table 10.5.123) */ CDMA_LOCKED_UNTIL_POWER_CYCLE, /* MS is locked until next power cycle */ CDMA_DROP, CDMA_INTERCEPT, /* INTERCEPT order received, MS state idle entered */ CDMA_REORDER, /* MS has been redirected, call is cancelled */ CDMA_SO_REJECT, /* service option rejection */ - CDMA_RETRY_ORDER, /* requeseted service is rejected, retry delay is set */ + CDMA_RETRY_ORDER, /* requested service is rejected, retry delay is set */ CDMA_ACCESS_FAILURE, CDMA_PREEMPTED, CDMA_NOT_EMERGENCY, /* not an emergency call */ @@ -68,8 +69,8 @@ public abstract class Connection { /* Instance Methods */ /** - * Gets address (e.g., phone number) associated with connection - * TODO: distinguish reasons for unavailablity + * Gets address (e.g. phone number) associated with connection. + * TODO: distinguish reasons for unavailability * * @return address or null if unavailable */ @@ -77,7 +78,7 @@ public abstract class Connection { public abstract String getAddress(); /** - * Gets cdma CNAP name associated with connection + * Gets CDMA CNAP name associated with connection. * @return cnap name or null if unavailable */ public String getCnapName() { @@ -85,15 +86,15 @@ public abstract class Connection { } /** - * Get orignal dial string - * @return orignal dial string or null if unavailable + * Get original dial string. + * @return original dial string or null if unavailable */ public String getOrigDialString(){ return null; } /** - * Gets cdma CNAP presentation associated with connection + * Gets CDMA CNAP presentation associated with connection. * @return cnap name or null if unavailable */ @@ -115,45 +116,45 @@ public abstract class Connection { public abstract long getCreateTime(); /** - * Connection connect time in currentTimeMillis() format - * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition - * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition - * Returns 0 before then + * Connection connect time in currentTimeMillis() format. + * For outgoing calls: Begins at (DIALING|ALERTING) -> ACTIVE transition. + * For incoming calls: Begins at (INCOMING|WAITING) -> ACTIVE transition. + * Returns 0 before then. */ public abstract long getConnectTime(); /** - * Disconnect time in currentTimeMillis() format - * The time when this Connection makes a transition into ENDED or FAIL - * Returns 0 before then + * Disconnect time in currentTimeMillis() format. + * The time when this Connection makes a transition into ENDED or FAIL. + * Returns 0 before then. */ public abstract long getDisconnectTime(); /** - * returns the number of milliseconds the call has been connected, + * Returns the number of milliseconds the call has been connected, * or 0 if the call has never connected. * If the call is still connected, then returns the elapsed - * time since connect + * time since connect. */ public abstract long getDurationMillis(); /** * If this connection is HOLDING, return the number of milliseconds - * that it has been on hold for (approximently) - * If this connection is in any other state, return 0 + * that it has been on hold for (approximately). + * If this connection is in any other state, return 0. */ public abstract long getHoldDurationMillis(); /** - * Returns "NOT_DISCONNECTED" if not yet disconnected + * Returns "NOT_DISCONNECTED" if not yet disconnected. */ public abstract DisconnectCause getDisconnectCause(); /** * Returns true of this connection originated elsewhere * ("MT" or mobile terminated; another party called this terminal) - * or false if this call originated here (MO or mobile originated) + * or false if this call originated here (MO or mobile originated). */ public abstract boolean isIncoming(); @@ -272,6 +273,13 @@ public abstract class Connection { */ public abstract int getNumberPresentation(); + /** + * Returns the User to User Signaling (UUS) information associated with + * incoming and waiting calls + * @return UUSInfo containing the UUS userdata. + */ + public abstract UUSInfo getUUSInfo(); + /** * Build a human representation of a connection instance, suitable for debugging. * Don't log personal stuff unless in debug mode. diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java index 1f8bbcfbe42461c3c276c67cf99e082b5d3fbf4d..6634017c84a51c8f44a0964cb416dadde698af24 100644 --- a/telephony/java/com/android/internal/telephony/DataConnection.java +++ b/telephony/java/com/android/internal/telephony/DataConnection.java @@ -164,7 +164,7 @@ public abstract class DataConnection extends HierarchicalStateMachine { NONE, OPERATOR_BARRED, INSUFFICIENT_RESOURCES, - MISSING_UKNOWN_APN, + MISSING_UNKNOWN_APN, UNKNOWN_PDP_ADDRESS, USER_AUTHENTICATION, ACTIVATION_REJECT_GGSN, @@ -181,7 +181,7 @@ public abstract class DataConnection extends HierarchicalStateMachine { RADIO_NOT_AVAILABLE; public boolean isPermanentFail() { - return (this == OPERATOR_BARRED) || (this == MISSING_UKNOWN_APN) || + return (this == OPERATOR_BARRED) || (this == MISSING_UNKNOWN_APN) || (this == UNKNOWN_PDP_ADDRESS) || (this == USER_AUTHENTICATION) || (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) || (this == SERVICE_OPTION_NOT_SUPPORTED) || @@ -208,12 +208,12 @@ public abstract class DataConnection extends HierarchicalStateMachine { return "Operator Barred"; case INSUFFICIENT_RESOURCES: return "Insufficient Resources"; - case MISSING_UKNOWN_APN: + case MISSING_UNKNOWN_APN: return "Missing / Unknown APN"; case UNKNOWN_PDP_ADDRESS: return "Unknown PDP Address"; case USER_AUTHENTICATION: - return "Error User Autentication"; + return "Error User Authentication"; case ACTIVATION_REJECT_GGSN: return "Activation Reject GGSN"; case ACTIVATION_REJECT_UNSPECIFIED: diff --git a/telephony/java/com/android/internal/telephony/DriverCall.java b/telephony/java/com/android/internal/telephony/DriverCall.java index 66f6b9cbff957d8530f2b3325ea0fac8422eaec9..663c2842a79357f183849b90690115ef91679d3e 100644 --- a/telephony/java/com/android/internal/telephony/DriverCall.java +++ b/telephony/java/com/android/internal/telephony/DriverCall.java @@ -49,6 +49,7 @@ public class DriverCall implements Comparable { public int numberPresentation; public String name; public int namePresentation; + public UUSInfo uusInfo; /** returns null on error */ static DriverCall diff --git a/telephony/java/com/android/internal/telephony/IccProvider.java b/telephony/java/com/android/internal/telephony/IccProvider.java index fa914570c34117f51853075b72ea0e6a2dc8dbbd..3471ec2885afcc35e19dde27a6a026e53c8f54e2 100644 --- a/telephony/java/com/android/internal/telephony/IccProvider.java +++ b/telephony/java/com/android/internal/telephony/IccProvider.java @@ -417,11 +417,11 @@ public class IccProvider extends ContentProvider { } } - if (TextUtils.isEmpty(tag)) { + if (TextUtils.isEmpty(number)) { return 0; } - if (efType == FDN && TextUtils.isEmpty(pin2)) { + if (efType == IccConstants.EF_FDN && TextUtils.isEmpty(pin2)) { return 0; } diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java index 7179bef9f1656a61151a8e00e68d44a5ff6520b4..23325f6f5ddc3487d8fd4c727b3bf940297a022b 100644 --- a/telephony/java/com/android/internal/telephony/Phone.java +++ b/telephony/java/com/android/internal/telephony/Phone.java @@ -243,15 +243,14 @@ public interface Phone { /** * Get the current DataState. No change notification exists at this * interface -- use - * {@link com.android.telephony.PhoneStateListener PhoneStateListener} - * instead. + * {@link android.telephony.PhoneStateListener} instead. */ DataState getDataConnectionState(); /** * Get the current DataActivityState. No change notification exists at this * interface -- use - * {@link TelephonyManager} instead. + * {@link android.telephony.TelephonyManager} instead. */ DataActivityState getDataActivityState(); @@ -788,6 +787,19 @@ public interface Phone { */ Connection dial(String dialString) throws CallStateException; + /** + * Initiate a new voice connection with supplementary User to User + * Information. This happens asynchronously, so you cannot assume the audio + * path is connected (or a call index has been assigned) until + * PhoneStateChanged notification has occurred. + * + * @exception CallStateException if a new outgoing call is not currently + * possible because no more call slots exist or a call exists + * that is dialing, alerting, ringing, or waiting. Other + * errors are handled asynchronously. + */ + Connection dial(String dialString, UUSInfo uusInfo) throws CallStateException; + /** * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated * without SEND (so dial is not appropriate). @@ -840,7 +852,7 @@ public interface Phone { * @param dtmfString is string representing the dialing digit(s) in the active call * @param on the DTMF ON length in milliseconds, or 0 for default * @param off the DTMF OFF length in milliseconds, or 0 for default - * @param onCompelte is the callback message when the action is processed by BP + * @param onComplete is the callback message when the action is processed by BP * */ void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete); @@ -980,7 +992,7 @@ public interface Phone { * ((AsyncResult)onComplete.obj) is an array of int, with a length of 2. * * @param onComplete a callback message when the action is completed. - * @see com.android.internal.telephony.CommandsInterface.getCLIR for details. + * @see com.android.internal.telephony.CommandsInterface#getCLIR for details. */ void getOutgoingCallerIdDisplay(Message onComplete); @@ -1002,7 +1014,7 @@ public interface Phone { * ((AsyncResult)onComplete.obj) is an array of int, with a length of 1. * * @param onComplete a callback message when the action is completed. - * @see com.android.internal.telephony.CommandsInterface.queryCallWaiting for details. + * @see com.android.internal.telephony.CommandsInterface#queryCallWaiting for details. */ void getCallWaiting(Message onComplete); @@ -1445,7 +1457,7 @@ public interface Phone { * setTTYMode * sets a TTY mode option. * - * @param enable is a boolean representing the state that you are + * @param ttyMode is a boolean representing the state that you are * requesting, true for enabled, false for disabled. * @param onComplete a callback message when the action is completed */ diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index a8f41430488e74fd4ed98a87e771c2747d7d757e..74601e620be42b0b3ea4892316d741c7d037402f 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -543,7 +543,7 @@ public abstract class PhoneBase extends Handler implements Phone { private void setPropertiesByCarrier() { String carrier = SystemProperties.get("ro.carrier"); - if (null == carrier || 0 == carrier.length()) { + if (null == carrier || 0 == carrier.length() || "unknown".equals(carrier)) { return; } diff --git a/telephony/java/com/android/internal/telephony/PhoneFactory.java b/telephony/java/com/android/internal/telephony/PhoneFactory.java index cd72752e43281a1875e8dc77075e4a3676db2813..803b7368558782aad675a8e8d66aaa6a77636b73 100644 --- a/telephony/java/com/android/internal/telephony/PhoneFactory.java +++ b/telephony/java/com/android/internal/telephony/PhoneFactory.java @@ -109,13 +109,13 @@ public class PhoneFactory { int phoneType = getPhoneType(networkMode); if (phoneType == Phone.PHONE_TYPE_GSM) { + Log.i(LOG_TAG, "Creating GSMPhone"); sProxyPhone = new PhoneProxy(new GSMPhone(context, sCommandsInterface, sPhoneNotifier)); - Log.i(LOG_TAG, "Creating GSMPhone"); } else if (phoneType == Phone.PHONE_TYPE_CDMA) { + Log.i(LOG_TAG, "Creating CDMAPhone"); sProxyPhone = new PhoneProxy(new CDMAPhone(context, sCommandsInterface, sPhoneNotifier)); - Log.i(LOG_TAG, "Creating CDMAPhone"); } sMadeDefaults = true; diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java index 6d3798ed145992812119cada4bc1e749e9f155d5..e1511e6ed79f12743ea0320267f99cb04223b336 100644 --- a/telephony/java/com/android/internal/telephony/PhoneProxy.java +++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java @@ -423,6 +423,10 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.dial(dialString); } + public Connection dial(String dialString, UUSInfo uusInfo) throws CallStateException { + return mActivePhone.dial(dialString, uusInfo); + } + public boolean handlePinMmi(String dialString) { return mActivePhone.handlePinMmi(dialString); } diff --git a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java index 1ac2da36338ef059139cc185c8b9efb8eb7caa3d..4f71bb1b7bda7c1f6202df41dd50964fa029051a 100644 --- a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java +++ b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java @@ -65,7 +65,7 @@ public class PhoneSubInfo extends IPhoneSubInfo.Stub { } /** - * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones. + * Retrieves the unique subscriber ID, e.g., IMSI for GSM phones. */ public String getSubscriberId() { mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE"); diff --git a/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java b/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java index adfbe20b067fbd586a11fc1bbb902253c5be9d80..202ded28e92475d2255e2ed29659658d7fff94dc 100644 --- a/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java +++ b/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java @@ -47,7 +47,7 @@ public class PhoneSubInfoProxy extends IPhoneSubInfo.Stub { } /** - * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones. + * Retrieves the unique subscriber ID, e.g., IMSI for GSM phones. */ public String getSubscriberId() { return mPhoneSubInfo.getSubscriberId(); diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java index d8e313a79908974ee7958df2f28b4a767c44734f..3d410fd2c465a365b790159f465e6384ef2e29b2 100644 --- a/telephony/java/com/android/internal/telephony/RIL.java +++ b/telephony/java/com/android/internal/telephony/RIL.java @@ -796,12 +796,26 @@ public final class RIL extends BaseCommands implements CommandsInterface { public void dial (String address, int clirMode, Message result) { + dial(address, clirMode, null, result); + } + + public void + dial(String address, int clirMode, UUSInfo uusInfo, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result); rr.mp.writeString(address); rr.mp.writeInt(clirMode); rr.mp.writeInt(0); // UUS information is absent + if (uusInfo == null) { + rr.mp.writeInt(0); // UUS information is absent + } else { + rr.mp.writeInt(1); // UUS information is present + rr.mp.writeInt(uusInfo.getType()); + rr.mp.writeInt(uusInfo.getDcs()); + rr.mp.writeByteArray(uusInfo.getUserData()); + } + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); send(rr); @@ -2837,10 +2851,21 @@ public final class RIL extends BaseCommands implements CommandsInterface { dc.namePresentation = p.readInt(); int uusInfoPresent = p.readInt(); if (uusInfoPresent == 1) { - // TODO: Copy the data to dc to forward to the apps. - p.readInt(); - p.readInt(); - p.createByteArray(); + dc.uusInfo = new UUSInfo(); + dc.uusInfo.setType(p.readInt()); + dc.uusInfo.setDcs(p.readInt()); + byte[] userData = p.createByteArray(); + dc.uusInfo.setUserData(userData); + Log + .v(LOG_TAG, String.format("Incoming UUS : type=%d, dcs=%d, length=%d", + dc.uusInfo.getType(), dc.uusInfo.getDcs(), + dc.uusInfo.getUserData().length)); + Log.v(LOG_TAG, "Incoming UUS : data (string)=" + + new String(dc.uusInfo.getUserData())); + Log.v(LOG_TAG, "Incoming UUS : data (hex): " + + IccUtils.bytesToHexString(dc.uusInfo.getUserData())); + } else { + Log.v(LOG_TAG, "Incoming UUS : NOT present!"); } // Make sure there's a leading + on addresses with a TOA of 145 diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 01f4ab274c1316706ca7bed826263386ac33c3f0..71a80e01eacf44170ef495696f5e62ec81988d62 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -45,6 +45,11 @@ public interface RILConstants { int OP_NOT_ALLOWED_BEFORE_REG_NW = 9; /* request is not allowed before device registers to network */ int SMS_SEND_FAIL_RETRY = 10; /* send sms fail and need retry */ + int SIM_ABSENT = 11; /* ICC card is absent */ + int SUBSCRIPTION_NOT_AVAILABLE = 12; /* fail to find CDMA subscription from specified + location */ + int MODE_NOT_SUPPORTED = 13; /* HW does not support preferred network type */ + int FDN_CHECK_FAILURE = 14; /* send operation barred error when FDN is enabled */ int ILLEGAL_SIM_OR_ME = 15; /* network selection failure due to wrong SIM/ME and no retries needed */ diff --git a/telephony/java/com/android/internal/telephony/RetryManager.java b/telephony/java/com/android/internal/telephony/RetryManager.java index 779f358307acf7ba2589973f46ca5088a0a8645c..b1049a2892b1a23ad4e844dac83cc5ca1e01c088 100644 --- a/telephony/java/com/android/internal/telephony/RetryManager.java +++ b/telephony/java/com/android/internal/telephony/RetryManager.java @@ -25,7 +25,7 @@ import java.util.ArrayList; /** * Retry manager allows a simple way to declare a series of - * retires timeouts. After creating a RetryManager the configure + * retry timeouts. After creating a RetryManager the configure * method is used to define the sequence. A simple linear series * may be initialized using configure with three integer parameters * The other configure method allows a series to be declared using @@ -54,18 +54,18 @@ import java.util.ArrayList; *

    * Examples: *

      - *
    • 3 retires with no randomization value which means its 0: + *
    • 3 retries with no randomization value which means its 0: *
      • "1000, 2000, 3000"
      * - *
    • 10 retires with a 500 default randomization value for each and + *
    • 10 retries with a 500 default randomization value for each and * the 4..10 retries all using 3000 as the delay: *
      • "max_retries=10, default_randomization=500, 1000, 2000, 3000"
      * - *
    • 4 retires with a 100 as the default randomization value for the first 2 values and + *
    • 4 retries with a 100 as the default randomization value for the first 2 values and * the other two having specified values of 500: *
      • "default_randomization=100, 1000, 2000, 4000:500, 5000:500"
      * - *
    • Infinite number of retires with the first one at 1000, the second at 2000 all + *
    • Infinite number of retries with the first one at 1000, the second at 2000 all * others will be at 3000. *
      • "max_retries=infinite,1000,2000,3000
      *
    @@ -75,9 +75,6 @@ import java.util.ArrayList; public class RetryManager { static public final String LOG_TAG = "RetryManager"; static public final boolean DBG = false; - static public final int RETRYIES_NOT_STARTED = 0; - static public final int RETRYIES_ON_GOING = 1; - static public final int RETRYIES_COMPLETED = 2; /** * Retry record with times in milli-seconds @@ -104,7 +101,7 @@ public class RetryManager { */ private int mMaxRetryCount; - /** The current number of retires */ + /** The current number of retries */ private int mRetryCount; /** Random number generator */ @@ -125,7 +122,7 @@ public class RetryManager { * @param randomizationTime a random value between 0 and * randomizationTime will be added to retryTime. this * parameter may be 0. - * @return true if successfull + * @return true if successful */ public boolean configure(int maxRetryCount, int retryTime, int randomizationTime) { Pair value; @@ -242,7 +239,7 @@ public class RetryManager { /** * Report whether data reconnection should be retried * - * @return {@code true} if the max retires has not been reached. {@code + * @return {@code true} if the max retries has not been reached. {@code * false} otherwise. */ public boolean isRetryNeeded() { @@ -289,7 +286,7 @@ public class RetryManager { if (mRetryCount > mMaxRetryCount) { mRetryCount = mMaxRetryCount; } - if (DBG) log("increseRetryCount: " + mRetryCount); + if (DBG) log("increaseRetryCount: " + mRetryCount); } /** diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java index 764d12ebe067ea449042610487420cf3033773cc..ca526a521dc31481d4ec42c3480a20d84d87ee0b 100644 --- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java @@ -62,6 +62,7 @@ import static android.telephony.SmsManager.RESULT_ERROR_NO_SERVICE; import static android.telephony.SmsManager.RESULT_ERROR_NULL_PDU; import static android.telephony.SmsManager.RESULT_ERROR_RADIO_OFF; import static android.telephony.SmsManager.RESULT_ERROR_LIMIT_EXCEEDED; +import static android.telephony.SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE; public abstract class SMSDispatcher extends Handler { @@ -499,13 +500,20 @@ public abstract class SMSDispatcher extends Handler { Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker); sendMessageDelayed(retryMsg, SEND_RETRY_DELAY); } else if (tracker.mSentIntent != null) { + int error = RESULT_ERROR_GENERIC_FAILURE; + + if (((CommandException)(ar.exception)).getCommandError() + == CommandException.Error.FDN_CHECK_FAILURE) { + error = RESULT_ERROR_FDN_CHECK_FAILURE; + } // Done retrying; return an error to the app. try { Intent fillIn = new Intent(); if (ar.result != null) { fillIn.putExtra("errorCode", ((SmsResponse)ar.result).errorCode); } - tracker.mSentIntent.send(mContext, RESULT_ERROR_GENERIC_FAILURE, fillIn); + tracker.mSentIntent.send(mContext, error, fillIn); + } catch (CanceledException ex) {} } } diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java index 73836497dc4e2dfd37a5d88bc2d075d03512a9ad..e8bbe5e9ecac3998069d0f953937a291a381a0c6 100644 --- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java @@ -44,6 +44,7 @@ public abstract class ServiceStateTracker extends Handler { protected static final int DATA_ACCESS_HSDPA = 9; protected static final int DATA_ACCESS_HSUPA = 10; protected static final int DATA_ACCESS_HSPA = 11; + protected static final int DATA_ACCESS_CDMA_EvDo_B = 12; protected CommandsInterface cm; @@ -206,8 +207,8 @@ public abstract class ServiceStateTracker extends Handler { } /** - * Reregister network through toggle perferred network type - * This is a work aorund to deregister and register network since there is + * Re-register network by toggling preferred network type. + * This is a work-around to deregister and register network since there is * no ril api to set COPS=2 (deregister) only. * * @param onComplete is dispatched when this is complete. it will be @@ -229,7 +230,7 @@ public abstract class ServiceStateTracker extends Handler { /** * These two flags manage the behavior of the cell lock -- the * lock should be held if either flag is true. The intention is - * to allow temporary aquisition of the lock to get a single + * to allow temporary acquisition of the lock to get a single * update. Such a lock grab and release can thus be made to not * interfere with more permanent lock holds -- in other words, the * lock will only be released if both flags are false, and so diff --git a/telephony/java/com/android/internal/telephony/UUSInfo.java b/telephony/java/com/android/internal/telephony/UUSInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..801b84563c98a863fddd89bcc9e71721094afa39 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/UUSInfo.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2010 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. + */ + +package com.android.internal.telephony; + +public class UUSInfo { + + /* + * User-to-User signaling Info activation types derived from 3GPP 23.087 + * v8.0 + */ + + public static final int UUS_TYPE1_IMPLICIT = 0; + + public static final int UUS_TYPE1_REQUIRED = 1; + + public static final int UUS_TYPE1_NOT_REQUIRED = 2; + + public static final int UUS_TYPE2_REQUIRED = 3; + + public static final int UUS_TYPE2_NOT_REQUIRED = 4; + + public static final int UUS_TYPE3_REQUIRED = 5; + + public static final int UUS_TYPE3_NOT_REQUIRED = 6; + + /* + * User-to-User Signaling Information data coding schemes. Possible values + * for Octet 3 (Protocol Discriminator field) in the UUIE. The values have + * been specified in section 10.5.4.25 of 3GPP TS 24.008 + */ + + public static final int UUS_DCS_USP = 0; /* User specified protocol */ + + public static final int UUS_DCS_OSIHLP = 1; /* OSI higher layer protocol */ + + public static final int UUS_DCS_X244 = 2; /* X.244 */ + + public static final int UUS_DCS_RMCF = 3; /* + * Reserved for system management + * convergence function + */ + + public static final int UUS_DCS_IA5c = 4; /* IA5 characters */ + + private int uusType; + + private int uusDcs; + + private byte[] uusData; + + public UUSInfo() { + this.uusType = UUS_TYPE1_IMPLICIT; + this.uusDcs = UUS_DCS_IA5c; + this.uusData = null; + } + + public UUSInfo(int uusType, int uusDcs, byte[] uusData) { + this.uusType = uusType; + this.uusDcs = uusDcs; + this.uusData = uusData; + } + + public int getDcs() { + return uusDcs; + } + + public void setDcs(int uusDcs) { + this.uusDcs = uusDcs; + } + + public int getType() { + return uusType; + } + + public void setType(int uusType) { + this.uusType = uusType; + } + + public byte[] getUserData() { + return uusData; + } + + public void setUserData(byte[] uusData) { + this.uusData = uusData; + } +} diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index 1f5accf38f21e557c20af960ef8cefcc6edf1e38..0c591e4d951cd9d0559d367d7e80c5e7bddd27e4 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -62,11 +62,13 @@ import com.android.internal.telephony.PhoneProxy; import com.android.internal.telephony.PhoneSubInfo; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyProperties; +import com.android.internal.telephony.UUSInfo; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY; +import java.util.ArrayList; import java.util.List; @@ -101,6 +103,7 @@ public class CDMAPhone extends PhoneBase { RuimFileHandler mRuimFileHandler; RuimRecords mRuimRecords; RuimCard mRuimCard; + ArrayList mPendingMmis = new ArrayList(); RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager; RuimSmsInterfaceManager mRuimSmsInterfaceManager; PhoneSubInfo mSubInfo; @@ -219,6 +222,8 @@ public class CDMAPhone extends PhoneBase { mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK mCM.unSetOnSuppServiceNotification(this); + mPendingMmis.clear(); + //Force all referenced classes to unregister their former registered events mCT.dispose(); mDataConnection.dispose(); @@ -344,6 +349,10 @@ public class CDMAPhone extends PhoneBase { return mCT.dial(newDialString); } + public Connection dial(String dialString, UUSInfo uusInfo) throws CallStateException { + throw new CallStateException("Sending UUS information NOT supported in CDMA!"); + } + public SignalStrength getSignalStrength() { return mSST.mSignalStrength; } @@ -355,8 +364,7 @@ public class CDMAPhone extends PhoneBase { public List getPendingMmiCodes() { - Log.e(LOG_TAG, "method getPendingMmiCodes is NOT supported in CDMA!"); - return null; + return mPendingMmis; } public void registerForSuppServiceNotification( @@ -373,6 +381,15 @@ public class CDMAPhone extends PhoneBase { return false; } + boolean isInCall() { + CdmaCall.State foregroundCallState = getForegroundCall().getState(); + CdmaCall.State backgroundCallState = getBackgroundCall().getState(); + CdmaCall.State ringingCallState = getRingingCall().getState(); + + return (foregroundCallState.isAlive() || backgroundCallState.isAlive() || ringingCallState + .isAlive()); + } + public void setNetworkSelectionModeAutomatic(Message response) { Log.e(LOG_TAG, "method setNetworkSelectionModeAutomatic is NOT supported in CDMA!"); @@ -472,7 +489,18 @@ public class CDMAPhone extends PhoneBase { } public boolean handlePinMmi(String dialString) { - Log.e(LOG_TAG, "method handlePinMmi is NOT supported in CDMA!"); + CdmaMmiCode mmi = CdmaMmiCode.newFromDialString(dialString, this); + + if (mmi == null) { + Log.e(LOG_TAG, "Mmi is NULL!"); + return false; + } else if (mmi.isPukCommand()) { + mPendingMmis.add(mmi); + mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); + mmi.processCode(); + return true; + } + Log.e(LOG_TAG, "Unrecognized mmi!"); return false; } @@ -484,6 +512,22 @@ public class CDMAPhone extends PhoneBase { (mDataConnection.getDataOnRoamingEnabled() || !getServiceState().getRoaming()); } + /** + * Removes the given MMI from the pending list and notifies registrants that + * it is complete. + * + * @param mmi MMI that is done + */ + void onMMIDone(CdmaMmiCode mmi) { + /* + * Only notify complete if it's on the pending list. Otherwise, it's + * already been handled (eg, previously canceled). + */ + if (mPendingMmis.remove(mmi)) { + mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); + } + } + public void setLine1Number(String alphaTag, String number, Message onComplete) { Log.e(LOG_TAG, "setLine1Number: not possible in CDMA"); } @@ -1405,5 +1449,4 @@ public class CDMAPhone extends PhoneBase { } return false; } - } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java index 1005d2045f42050d2f4792f890ace8f6b4baf6d4..3669e6062b020d72be98dc0cd7f8300eeb17f2b0 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java @@ -61,7 +61,7 @@ public final class CdmaCallTracker extends CallTracker { RegistrantList callWaitingRegistrants = new RegistrantList(); - // connections dropped durin last poll + // connections dropped during last poll ArrayList droppedDuringPoll = new ArrayList(MAX_CONNECTIONS); diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java index 188145b33fcbb4469f5db6104b0d6aa5be0eedac..fbe455e1ffddcfce4c1f2ea98d9ced6da40dd883 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java @@ -945,4 +945,10 @@ public class CdmaConnection extends Connection { public int getNumberPresentation() { return numberPresentation; } + + @Override + public UUSInfo getUUSInfo() { + // UUS information not supported in CDMA + return null; + } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java index 217e1e86b0931253aa20ff0d229a65f1ef9d7598..9f2a44b743b76ac9532ce6c4f7fd02d05fd67537 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java @@ -114,7 +114,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { // if we have no active Apn this is null protected ApnSetting mActiveApn; - // Possibly promoate to base class, the only difference is + // Possibly promote to base class, the only difference is // the INTENT_RECONNECT_ALARM action is a different string. // Do consider technology changes if it is promoted. BroadcastReceiver mIntentReceiver = new BroadcastReceiver () @@ -420,7 +420,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { CdmaDataConnection conn = findFreeDataConnection(); if (conn == null) { - if (DBG) log("setupData: No free CdmaDataConnectionfound!"); + if (DBG) log("setupData: No free CdmaDataConnection found!"); return false; } @@ -646,7 +646,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } /** - * @override com.android.intenral.telephony.DataConnectionTracker + * @override com.android.internal.telephony.DataConnectionTracker */ @Override protected void onEnableNewApn() { diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaMmiCode.java b/telephony/java/com/android/internal/telephony/cdma/CdmaMmiCode.java new file mode 100644 index 0000000000000000000000000000000000000000..8dd8c2e6c6793269a00e91414c1ef39fd76801d2 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaMmiCode.java @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2006 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. + */ + +package com.android.internal.telephony.cdma; + +import android.content.Context; + +import com.android.internal.telephony.CommandException; +import com.android.internal.telephony.MmiCode; + +import android.os.AsyncResult; +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * This class can handle Puk code Mmi + * + * {@hide} + * + */ +public final class CdmaMmiCode extends Handler implements MmiCode { + static final String LOG_TAG = "CDMA_MMI"; + + // Constants + + // From TS 22.030 6.5.2 + static final String ACTION_REGISTER = "**"; + + // Supp Service codes from TS 22.030 Annex B + static final String SC_PUK = "05"; + + // Event Constant + + static final int EVENT_SET_COMPLETE = 1; + + // Instance Variables + + CDMAPhone phone; + Context context; + + String action; // ACTION_REGISTER + String sc; // Service Code + String sia, sib, sic; // Service Info a,b,c + String poundString; // Entire MMI string up to and including # + String dialingNumber; + String pwd; // For password registration + + State state = State.PENDING; + CharSequence message; + + // Class Variables + + static Pattern sPatternSuppService = Pattern.compile( + "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)"); +/* 1 2 3 4 5 6 7 8 9 10 11 12 + + 1 = Full string up to and including # + 2 = action + 3 = service code + 5 = SIA + 7 = SIB + 9 = SIC + 10 = dialing number +*/ + + static final int MATCH_GROUP_POUND_STRING = 1; + static final int MATCH_GROUP_ACTION = 2; + static final int MATCH_GROUP_SERVICE_CODE = 3; + static final int MATCH_GROUP_SIA = 5; + static final int MATCH_GROUP_SIB = 7; + static final int MATCH_GROUP_SIC = 9; + static final int MATCH_GROUP_PWD_CONFIRM = 11; + static final int MATCH_GROUP_DIALING_NUMBER = 12; + + + // Public Class methods + + /** + * Check if provided string contains Mmi code in it and create corresponding + * Mmi if it does + */ + + public static CdmaMmiCode + newFromDialString(String dialString, CDMAPhone phone) { + Matcher m; + CdmaMmiCode ret = null; + + m = sPatternSuppService.matcher(dialString); + + // Is this formatted like a standard supplementary service code? + if (m.matches()) { + ret = new CdmaMmiCode(phone); + ret.poundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING)); + ret.action = makeEmptyNull(m.group(MATCH_GROUP_ACTION)); + ret.sc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE)); + ret.sia = makeEmptyNull(m.group(MATCH_GROUP_SIA)); + ret.sib = makeEmptyNull(m.group(MATCH_GROUP_SIB)); + ret.sic = makeEmptyNull(m.group(MATCH_GROUP_SIC)); + ret.pwd = makeEmptyNull(m.group(MATCH_GROUP_PWD_CONFIRM)); + ret.dialingNumber = makeEmptyNull(m.group(MATCH_GROUP_DIALING_NUMBER)); + + } + + return ret; + } + + // Private Class methods + + /** make empty strings be null. + * Regexp returns empty strings for empty groups + */ + private static String + makeEmptyNull (String s) { + if (s != null && s.length() == 0) return null; + + return s; + } + + // Constructor + + CdmaMmiCode (CDMAPhone phone) { + super(phone.getHandler().getLooper()); + this.phone = phone; + this.context = phone.getContext(); + } + + // MmiCode implementation + + public State + getState() { + return state; + } + + public CharSequence + getMessage() { + return message; + } + + // inherited javadoc suffices + public void + cancel() { + // Complete or failed cannot be cancelled + if (state == State.COMPLETE || state == State.FAILED) { + return; + } + + state = State.CANCELLED; + phone.onMMIDone (this); + } + + public boolean isCancelable() { + return false; + } + + // Instance Methods + + /** + * @return true if the Service Code is PIN/PIN2/PUK/PUK2-related + */ + boolean isPukCommand() { + return sc != null && sc.equals(SC_PUK); + } + + boolean isRegister() { + return action != null && action.equals(ACTION_REGISTER); + } + + public boolean isUssdRequest() { + Log.w(LOG_TAG, "isUssdRequest is not implemented in CdmaMmiCode"); + return false; + } + + /** Process a MMI PUK code */ + void + processCode () { + try { + if (isPukCommand()) { + // sia = old PUK + // sib = new PIN + // sic = new PIN + String oldPinOrPuk = sia; + String newPin = sib; + int pinLen = newPin.length(); + if (isRegister()) { + if (!newPin.equals(sic)) { + // password mismatch; return error + handlePasswordError(com.android.internal.R.string.mismatchPin); + } else if (pinLen < 4 || pinLen > 8 ) { + // invalid length + handlePasswordError(com.android.internal.R.string.invalidPin); + } else { + phone.mCM.supplyIccPuk(oldPinOrPuk, newPin, + obtainMessage(EVENT_SET_COMPLETE, this)); + } + } else { + throw new RuntimeException ("Invalid or Unsupported MMI Code"); + } + } else { + throw new RuntimeException ("Invalid or Unsupported MMI Code"); + } + } catch (RuntimeException exc) { + state = State.FAILED; + message = context.getText(com.android.internal.R.string.mmiError); + phone.onMMIDone(this); + } + } + + private void handlePasswordError(int res) { + state = State.FAILED; + StringBuilder sb = new StringBuilder(getScString()); + sb.append("\n"); + sb.append(context.getText(res)); + message = sb; + phone.onMMIDone(this); + } + + public void + handleMessage (Message msg) { + AsyncResult ar; + + if (msg.what == EVENT_SET_COMPLETE) { + ar = (AsyncResult) (msg.obj); + onSetComplete(ar); + } else { + Log.e(LOG_TAG, "Unexpected reply"); + } + } + // Private instance methods + + private CharSequence getScString() { + if (sc != null) { + if (isPukCommand()) { + return context.getText(com.android.internal.R.string.PinMmi); + } + } + + return ""; + } + + private void + onSetComplete(AsyncResult ar){ + StringBuilder sb = new StringBuilder(getScString()); + sb.append("\n"); + + if (ar.exception != null) { + state = State.FAILED; + if (ar.exception instanceof CommandException) { + CommandException.Error err = ((CommandException)(ar.exception)).getCommandError(); + if (err == CommandException.Error.PASSWORD_INCORRECT) { + if (isPukCommand()) { + sb.append(context.getText( + com.android.internal.R.string.badPuk)); + } else { + sb.append(context.getText( + com.android.internal.R.string.passwordIncorrect)); + } + } else { + sb.append(context.getText( + com.android.internal.R.string.mmiError)); + } + } else { + sb.append(context.getText( + com.android.internal.R.string.mmiError)); + } + } else if (isRegister()) { + state = State.COMPLETE; + sb.append(context.getText( + com.android.internal.R.string.serviceRegistered)); + } else { + state = State.FAILED; + sb.append(context.getText( + com.android.internal.R.string.mmiError)); + } + + message = sb; + phone.onMMIDone(this); + } + +} diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index 39fe007f4b20c75b2ae237e7a820877caa21226e..2cad6cc00a65f5c21aef59efa8da7dd245f727e5 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -66,7 +66,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { CdmaCellLocation cellLoc; CdmaCellLocation newCellLoc; - /** if time between NTIZ updates is less than mNitzUpdateSpacing the update may be ignored. */ + /** if time between NITZ updates is less than mNitzUpdateSpacing the update may be ignored. */ private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10; private int mNitzUpdateSpacing = SystemProperties.getInt("ro.nitz_update_spacing", NITZ_UPDATE_SPACING_DEFAULT); @@ -395,7 +395,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } // Release any temporary cell lock, which could have been - // aquired to allow a single-shot location update. + // acquired to allow a single-shot location update. disableSingleLocationUpdate(); break; @@ -591,7 +591,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { boolean showPlmn = false; int rule = 0; if (cm.getRadioState().isRUIMReady()) { - // TODO RUIM SPN is not implemnted, EF_SPN has to be read and Display Condition + // TODO RUIM SPN is not implemented, EF_SPN has to be read and Display Condition // Character Encoding, Language Indicator and SPN has to be set // rule = phone.mRuimRecords.getDisplayRule(ss.getOperatorNumeric()); // spn = phone.mSIMRecords.getServiceProvideName(); @@ -872,7 +872,6 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { * and start over again if the radio notifies us that some * event has changed */ - private void pollState() { pollingContext = new int[1]; @@ -945,6 +944,9 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { case DATA_ACCESS_CDMA_EvDo_A: ret = "CDMA - EvDo rev. A"; break; + case DATA_ACCESS_CDMA_EvDo_B: + ret = "CDMA - EvDo rev. B"; + break; default: if (DBG) { Log.e(LOG_TAG, "Wrong network. Can not return a string."); @@ -1237,6 +1239,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { case 6: // RADIO_TECHNOLOGY_1xRTT case 7: // RADIO_TECHNOLOGY_EVDO_0 case 8: // RADIO_TECHNOLOGY_EVDO_A + case 12: // RADIO_TECHNOLOGY_EVDO_B retVal = ServiceState.STATE_IN_SERVICE; break; default: @@ -1256,7 +1259,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { return ServiceState.STATE_IN_SERVICE; case 2: // 2 is "searching", fall through case 3: // 3 is "registration denied", fall through - case 4: // 4 is "unknown" no vaild in current baseband + case 4: // 4 is "unknown", not valid in current baseband return ServiceState.STATE_OUT_OF_SERVICE; case 5:// 5 is "Registered, roaming" return ServiceState.STATE_IN_SERVICE; @@ -1295,12 +1298,12 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { */ private boolean isRoamIndForHomeSystem(String roamInd) { // retrieve the carrier-specified list of ERIs for home system - String homeRoamIndcators = SystemProperties.get("ro.cdma.homesystem"); + String homeRoamIndicators = SystemProperties.get("ro.cdma.homesystem"); - if (!TextUtils.isEmpty(homeRoamIndcators)) { + if (!TextUtils.isEmpty(homeRoamIndicators)) { // searches through the comma-separated list for a match, // return true if one is found. - for (String homeRoamInd : homeRoamIndcators.split(",")) { + for (String homeRoamInd : homeRoamIndicators.split(",")) { if (homeRoamInd.equals(roamInd)) { return true; } diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index 403b7a1d16d3e104c75531178475f732902126ff..b50502c73a5ec2b38a11c4708dc3ca23002fc66e 100755 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -313,7 +313,7 @@ public class SmsMessage extends SmsMessageBase { } /** - * Get an SMS-SUBMIT PDU for a data message to a destination address & port + * Get an SMS-SUBMIT PDU for a data message to a destination address and port. * * @param scAddr Service Centre address. null == use default * @param destAddr the address of the destination for the message diff --git a/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java index 3813b1da98e07638f51bd2872f98a4653de47754..4907aa946800a702763535aa262997fdb04c68c6 100644 --- a/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java +++ b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java @@ -56,10 +56,10 @@ public class TtyIntent { /** * The lookup key for an int that indicates preferred TTY mode. * Valid modes are: - * - {@link Phone.TTY_MODE_OFF} - * - {@link Phone.TTY_MODE_FULL} - * - {@link Phone.TTY_MODE_HCO} - * - {@link Phone.TTY_MODE_VCO} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} + * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO} * * {@hide} */ diff --git a/telephony/java/com/android/internal/telephony/gsm/CallFailCause.java b/telephony/java/com/android/internal/telephony/gsm/CallFailCause.java index e7fbf6bd8a8b3e990a2c36c54e5cf6c35675e030..af2ad48a9bc03751ed53a649233a7307e85bf273 100644 --- a/telephony/java/com/android/internal/telephony/gsm/CallFailCause.java +++ b/telephony/java/com/android/internal/telephony/gsm/CallFailCause.java @@ -25,6 +25,9 @@ package com.android.internal.telephony.gsm; * */ public interface CallFailCause { + // Unassigned/Unobtainable number + static final int UNOBTAINABLE_NUMBER = 1; + static final int NORMAL_CLEARING = 16; // Busy Tone static final int USER_BUSY = 17; diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java old mode 100755 new mode 100644 index 2bb796827049899ea966b49060bb9670d688a08b..c7b1e5cd3c52178b9c28cca422283d6a6d8ebd8e --- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java +++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java @@ -67,6 +67,7 @@ import com.android.internal.telephony.PhoneNotifier; import com.android.internal.telephony.PhoneProxy; import com.android.internal.telephony.PhoneSubInfo; import com.android.internal.telephony.TelephonyProperties; +import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.gsm.stk.StkService; import com.android.internal.telephony.test.SimulatedRadioControl; import com.android.internal.telephony.IccVmNotSupportedException; @@ -711,7 +712,12 @@ public class GSMPhone extends PhoneBase { } public Connection - dial (String dialString) throws CallStateException { + dial(String dialString) throws CallStateException { + return dial(dialString, null); + } + + public Connection + dial (String dialString, UUSInfo uusInfo) throws CallStateException { // Need to make sure dialString gets parsed properly String newDialString = PhoneNumberUtils.stripSeparators(dialString); @@ -727,9 +733,9 @@ public class GSMPhone extends PhoneBase { "dialing w/ mmi '" + mmi + "'..."); if (mmi == null) { - return mCT.dial(newDialString); + return mCT.dial(newDialString, uusInfo); } else if (mmi.isTemporaryModeCLIR()) { - return mCT.dial(mmi.dialingNumber, mmi.getCLIRMode()); + return mCT.dial(mmi.dialingNumber, mmi.getCLIRMode(), uusInfo); } else { mPendingMMIs.add(mmi); mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java index 87530e42874af6f62a92556b03e7f138e7bded38..06f310c54a3879ae8443e90eea3a91298f0f256d 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java @@ -37,6 +37,7 @@ import com.android.internal.telephony.DriverCall; import com.android.internal.telephony.EventLogTags; import com.android.internal.telephony.Phone; import com.android.internal.telephony.TelephonyProperties; +import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.gsm.CallFailCause; import com.android.internal.telephony.gsm.GSMPhone; import com.android.internal.telephony.gsm.GsmCall; @@ -65,7 +66,7 @@ public final class GsmCallTracker extends CallTracker { RegistrantList voiceCallStartedRegistrants = new RegistrantList(); - // connections dropped durin last poll + // connections dropped during last poll ArrayList droppedDuringPoll = new ArrayList(MAX_CONNECTIONS); @@ -167,7 +168,7 @@ public final class GsmCallTracker extends CallTracker { * clirMode is one of the CLIR_ constants */ Connection - dial (String dialString, int clirMode) throws CallStateException { + dial (String dialString, int clirMode, UUSInfo uusInfo) throws CallStateException { // note that this triggers call state changed notif clearDisconnected(); @@ -213,7 +214,7 @@ public final class GsmCallTracker extends CallTracker { // Always unmute when initiating a new call setMute(false); - cm.dial(pendingMO.address, clirMode, obtainCompleteMessage()); + cm.dial(pendingMO.address, clirMode, uusInfo, obtainCompleteMessage()); } updatePhoneState(); @@ -222,10 +223,19 @@ public final class GsmCallTracker extends CallTracker { return pendingMO; } + Connection + dial(String dialString) throws CallStateException { + return dial(dialString, CommandsInterface.CLIR_DEFAULT, null); + } + + Connection + dial(String dialString, UUSInfo uusInfo) throws CallStateException { + return dial(dialString, CommandsInterface.CLIR_DEFAULT, uusInfo); + } Connection - dial (String dialString) throws CallStateException { - return dial(dialString, CommandsInterface.CLIR_DEFAULT); + dial(String dialString, int clirMode) throws CallStateException { + return dial(dialString, clirMode, null); } void diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java index 4788a01306576abfba306a580c3b7292d2c0478f..7dc25044eb169abbf3d0323a662e9e0693395682 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java @@ -73,6 +73,7 @@ public class GsmConnection extends Connection { DisconnectCause cause = DisconnectCause.NOT_DISCONNECTED; PostDialState postDialState = PostDialState.NOT_STARTED; int numberPresentation = Connection.PRESENTATION_ALLOWED; + UUSInfo uusInfo; Handler h; @@ -126,6 +127,7 @@ public class GsmConnection extends Connection { isIncoming = dc.isMT; createTime = System.currentTimeMillis(); numberPresentation = dc.numberPresentation; + uusInfo = dc.uusInfo; this.index = index; @@ -356,6 +358,9 @@ public class GsmConnection extends Connection { case CallFailCause.FDN_BLOCKED: return DisconnectCause.FDN_BLOCKED; + case CallFailCause.UNOBTAINABLE_NUMBER: + return DisconnectCause.UNOBTAINABLE_NUMBER; + case CallFailCause.ERROR_UNSPECIFIED: case CallFailCause.NORMAL_CLEARING: default: @@ -728,4 +733,9 @@ public class GsmConnection extends Connection { public int getNumberPresentation() { return numberPresentation; } + + @Override + public UUSInfo getUUSInfo() { + return uusInfo; + } } diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java index d893ec4c4837c739f482062ddccc4d90eaedf24b..09d46dd6e8b27ecbfe46e450df47beb510e41b78 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java @@ -134,7 +134,7 @@ public class GsmDataConnection extends DataConnection { cause = FailCause.INSUFFICIENT_RESOURCES; break; case PDP_FAIL_MISSING_UKNOWN_APN: - cause = FailCause.MISSING_UKNOWN_APN; + cause = FailCause.MISSING_UNKNOWN_APN; break; case PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE: cause = FailCause.UNKNOWN_PDP_ADDRESS; diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index cbfb550109bef04ed2e78567a09f8b5bcec270e6..9bc0b2692cbd8c2fb231ecad412194db5cd91da0 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -45,7 +45,6 @@ import android.provider.Telephony; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.telephony.gsm.GsmCellLocation; -import android.text.TextUtils; import android.util.EventLog; import android.util.Log; @@ -150,9 +149,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { static final String APN_ID = "apn_id"; private boolean canSetPreferApn = false; - // for tracking retrys on the default APN + // for tracking retries on the default APN private RetryManager mDefaultRetryManager; - // for tracking retrys on a secondary APN + // for tracking retries on a secondary APN private RetryManager mSecondaryRetryManager; BroadcastReceiver mIntentReceiver = new BroadcastReceiver () @@ -189,8 +188,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; if (!enabled) { - // when wifi got disabeled, the NETWORK_STATE_CHANGED_ACTION - // quit and wont report disconnected til next enalbing. + // when wifi got disabled, the NETWORK_STATE_CHANGED_ACTION + // quit and won't report disconnected til next enabling. mIsWifiConnected = false; } } @@ -447,7 +446,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { waitingApns = buildWaitingApns(); if (waitingApns.isEmpty()) { if (DBG) log("No APN found"); - notifyNoData(GsmDataConnection.FailCause.MISSING_UKNOWN_APN); + notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN); return false; } else { log ("Create from allApns : " + apnListToString(allApns)); @@ -1125,7 +1124,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { SystemProperties.set("gsm.defaultpdpcontext.active", "true"); if (canSetPreferApn && preferredApn == null) { - Log.d(LOG_TAG, "PREFERED APN is null"); + Log.d(LOG_TAG, "PREFERRED APN is null"); preferredApn = mActiveApn; setPreferredApn(preferredApn.id); } @@ -1275,7 +1274,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (allApns.isEmpty()) { if (DBG) log("No APN found for carrier: " + operator); preferredApn = null; - notifyNoData(GsmDataConnection.FailCause.MISSING_UKNOWN_APN); + notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN); } else { preferredApn = getPreferredApn(); Log.d(LOG_TAG, "Get PreferredAPN"); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java index bcbd127497b21b70cc01d3ff1f127c8885aad8d3..aa16fa30633b37ea306fa671572235685db172a8 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java @@ -39,7 +39,7 @@ import java.util.regex.Matcher; * {@hide} * */ -public final class GsmMmiCode extends Handler implements MmiCode { +public final class GsmMmiCode extends Handler implements MmiCode { static final String LOG_TAG = "GSM"; //***** Constants @@ -51,7 +51,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { static final String ACTION_REGISTER = "**"; static final String ACTION_ERASURE = "##"; - // Supp Service cocdes from TS 22.030 Annex B + // Supp Service codes from TS 22.030 Annex B //Called line presentation static final String SC_CLIP = "30"; @@ -154,7 +154,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { /** * Some dial strings in GSM are defined to do non-call setup - * things, such as modify or query supplementry service settings (eg, call + * things, such as modify or query supplementary service settings (eg, call * forwarding). These are generally referred to as "MMI codes". * We look to see if the dial string contains a valid MMI code (potentially * with a dial string at the end as well) and return info here. @@ -457,12 +457,13 @@ public final class GsmMmiCode extends Handler implements MmiCode { && !PhoneNumberUtils.isEmergencyNumber(dialString) && (phone.isInCall() || !((dialString.length() == 2 && dialString.charAt(0) == '1') - /* While contrary to TS 22.030, there is strong precendence + /* While contrary to TS 22.030, there is strong precedence * for treating "0" and "00" as call setup strings. */ || dialString.equals("0") || dialString.equals("00")))); } + /** * @return true if the Service Code is PIN/PIN2/PUK/PUK2-related */ @@ -472,13 +473,12 @@ public final class GsmMmiCode extends Handler implements MmiCode { } /** - * *See TS 22.030 Annex B + * See TS 22.030 Annex B. * In temporary mode, to suppress CLIR for a single call, enter: - * " * 31 # SEND " + * " * 31 # [called number] SEND " * In temporary mode, to invoke CLIR for a single call enter: - * " # 31 # SEND " + * " # 31 # [called number] SEND " */ - boolean isTemporaryModeCLIR() { return sc != null && sc.equals(SC_CLIR) && dialingNumber != null @@ -779,7 +779,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { // Note that unlike most everything else, the USSD complete // response does not complete this MMI code...we wait for // an unsolicited USSD "Notify" or "Request". - // The matching up of this is doene in GSMPhone. + // The matching up of this is done in GSMPhone. phone.mCM.sendUSSD(ussdMessage, obtainMessage(EVENT_USSD_COMPLETE, this)); @@ -832,8 +832,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { if (ar.exception != null) { state = State.FAILED; - message = context.getText( - com.android.internal.R.string.mmiError); + message = getErrorMessage(ar); phone.onMMIDone(this); } @@ -852,6 +851,19 @@ public final class GsmMmiCode extends Handler implements MmiCode { } //***** Private instance methods + private CharSequence getErrorMessage(AsyncResult ar) { + + if (ar.exception instanceof CommandException) { + CommandException.Error err = ((CommandException)(ar.exception)).getCommandError(); + if (err == CommandException.Error.FDN_CHECK_FAILURE) { + Log.i(LOG_TAG, "FDN_CHECK_FAILURE"); + return context.getText(com.android.internal.R.string.mmiFdnError); + } + } + + return context.getText(com.android.internal.R.string.mmiError); + } + private CharSequence getScString() { if (sc != null) { if (isServiceCodeCallBarring(sc)) { @@ -904,6 +916,9 @@ public final class GsmMmiCode extends Handler implements MmiCode { sb.append("\n"); sb.append(context.getText( com.android.internal.R.string.needPuk2)); + } else if (err == CommandException.Error.FDN_CHECK_FAILURE) { + Log.i(LOG_TAG, "FDN_CHECK_FAILURE"); + sb.append(context.getText(com.android.internal.R.string.mmiFdnError)); } else { sb.append(context.getText( com.android.internal.R.string.mmiError)); @@ -953,7 +968,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { if (ar.exception != null) { state = State.FAILED; - sb.append(context.getText(com.android.internal.R.string.mmiError)); + sb.append(getErrorMessage(ar)); } else { int clirArgs[]; @@ -1123,7 +1138,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { if (ar.exception != null) { state = State.FAILED; - sb.append(context.getText(com.android.internal.R.string.mmiError)); + sb.append(getErrorMessage(ar)); } else { CallForwardInfo infos[]; @@ -1141,7 +1156,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { // Each bit in the service class gets its own result line // The service classes may be split up over multiple - // CallForwardInfos. So, for each service classs, find out + // CallForwardInfos. So, for each service class, find out // which CallForwardInfo represents it and then build // the response text based on that @@ -1175,7 +1190,7 @@ public final class GsmMmiCode extends Handler implements MmiCode { if (ar.exception != null) { state = State.FAILED; - sb.append(context.getText(com.android.internal.R.string.mmiError)); + sb.append(getErrorMessage(ar)); } else { int[] ints = (int[])ar.result; diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java index 6ae316d0f08ea4aafed88ef22ee73c589c1949ae..d7205169f7af93236f4b915a55528cff69cf539c 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java @@ -94,6 +94,13 @@ final class GsmSMSDispatcher extends SMSDispatcher { SmsMessage sms = (SmsMessage) smsb; boolean handled = false; + if (sms.isTypeZero()) { + // As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be + // Displayed/Stored/Notified. They should only be acknowledged. + Log.d(TAG, "Received short message type 0, Dont display or store it. Send Ack"); + return Intents.RESULT_SMS_HANDLED; + } + // Special case the message waiting indicator messages if (sms.isMWISetMessage()) { mGsmPhone.updateMessageWaitingIndicator(true); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java index 50b8eba927011635bebad294a7cce32e2c634eff..d539f6f1ae80e477b8d2e6faa6d9038ec9c472a5 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java @@ -40,7 +40,6 @@ import android.provider.Settings.SettingNotFoundException; import android.provider.Telephony.Intents; import android.telephony.ServiceState; import android.telephony.SignalStrength; -import android.telephony.TelephonyManager; import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; import android.util.Config; @@ -130,7 +129,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { */ private boolean mNeedToRegForSimLoaded; - /** Started the recheck process after finding gprs should registerd but not. */ + /** Started the recheck process after finding gprs should registered but not. */ private boolean mStartedGprsRegCheck = false; /** Already sent the event-log for no gprs register. */ @@ -415,7 +414,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } // Release any temporary cell lock, which could have been - // aquired to allow a single-shot location update. + // acquired to allow a single-shot location update. disableSingleLocationUpdate(); break; @@ -500,9 +499,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker { break; case EVENT_CHECK_REPORT_GPRS: - if (ss != null && !isGprsConsistant(gprsState, ss.getState())) { + if (ss != null && !isGprsConsistent(gprsState, ss.getState())) { - // Can't register data sevice while voice service is ok + // Can't register data service while voice service is ok // i.e. CREG is ok while CGREG is not // possible a network or baseband side error GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation()); @@ -1027,7 +1026,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { phone.notifyLocationChanged(); } - if (! isGprsConsistant(gprsState, ss.getState())) { + if (! isGprsConsistent(gprsState, ss.getState())) { if (!mStartedGprsRegCheck && !mReportedGprsNoReg) { mStartedGprsRegCheck = true; @@ -1044,13 +1043,13 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } /** - * Check if GPRS got registred while voice is registered + * Check if GPRS got registered while voice is registered. * * @param gprsState for GPRS registration state, i.e. CGREG in GSM * @param serviceState for voice registration state, i.e. CREG in GSM * @return false if device only register to voice but not gprs */ - private boolean isGprsConsistant (int gprsState, int serviceState) { + private boolean isGprsConsistent(int gprsState, int serviceState) { return !((serviceState == ServiceState.STATE_IN_SERVICE) && (gprsState != ServiceState.STATE_IN_SERVICE)); } @@ -1105,13 +1104,13 @@ final class GsmServiceStateTracker extends ServiceStateTracker { long nextTime; - // TODO Done't poll signal strength if screen is off + // TODO Don't poll signal strength if screen is off sendMessageDelayed(msg, POLL_PERIOD_MILLIS); } /** - * send signal-strength-changed notification if changed - * Called both for solicited and unsolicited signal stength updates + * Send signal-strength-changed notification if changed. + * Called both for solicited and unsolicited signal strength updates. */ private void onSignalStrengthResult(AsyncResult ar) { SignalStrength oldSignalStrength = mSignalStrength; @@ -1332,7 +1331,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { /** * @return true if phone is camping on a technology (eg UMTS) - * that could support voice and data simultaniously. + * that could support voice and data simultaneously. */ boolean isConcurrentVoiceAndData() { return (networkType >= DATA_ACCESS_UMTS); diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index d627bafbafe9ea41b733a55885c1909e51192232..12c6b8897b768ffe6e59338236dfbb86d745a63b 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -110,6 +110,14 @@ public class SmsMessage extends SmsMessageBase{ } } + /** + * 3GPP TS 23.040 9.2.3.9 specifies that Type Zero messages are indicated + * by TP_PID field set to value 0x40 + */ + public boolean isTypeZero() { + return (protocolIdentifier == 0x40); + } + /** * TS 27.005 3.4.1 lines[0] and lines[1] are the two lines read from the * +CMT unsolicited response (PDU mode, of course) diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java index 11b3fd6fa12cfc02af21abf14de497ffb34688cb..a120f5234124f5c2977bedcae35227cbaa1cb23c 100644 --- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java +++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java @@ -29,6 +29,7 @@ import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.DataCallState; import com.android.internal.telephony.IccCard; import com.android.internal.telephony.Phone; +import com.android.internal.telephony.UUSInfo; import com.android.internal.telephony.gsm.CallFailCause; import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; import com.android.internal.telephony.gsm.SuppServiceNotification; @@ -491,6 +492,23 @@ public final class SimulatedCommands extends BaseCommands resultSuccess(result, null); } + /** + * returned message + * retMsg.obj = AsyncResult ar + * ar.exception carries exception on failure + * ar.userObject contains the orignal value of result.obj + * ar.result is null on success and failure + * + * CLIR_DEFAULT == on "use subscription default value" + * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation) + * CLIR_INVOCATION == on "CLIR invocation" (restrict CLI presentation) + */ + public void dial(String address, int clirMode, UUSInfo uusInfo, Message result) { + simulatedCallState.onDial(address); + + resultSuccess(result, null); + } + /** * returned message * retMsg.obj = AsyncResult ar diff --git a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java index 02590d373899b9e6eb4c833449284d0e72dfb4f2..a74c5c2a321b513d1d453ead172bf56931357180 100644 --- a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java +++ b/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java @@ -16,13 +16,16 @@ package com.android.internal.telephony; +import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import android.text.SpannableStringBuilder; import android.telephony.PhoneNumberUtils; +import android.telephony.TelephonyManager; +import android.content.Context; import junit.framework.TestCase; -public class PhoneNumberUtilsTest extends TestCase { +public class PhoneNumberUtilsTest extends AndroidTestCase { @SmallTest public void testExtractNetworkPortion() throws Exception { @@ -82,6 +85,16 @@ public class PhoneNumberUtilsTest extends TestCase { assertEquals("17005550020", PhoneNumberUtils.calledPartyBCDToString(b, 0, 7)); + b[0] = (byte) 0x80; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55; + b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0; + assertEquals("17005550020", + PhoneNumberUtils.calledPartyBCDToString(b, 0, 7)); + + b[0] = (byte) 0x90; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55; + b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0; + assertEquals("+17005550020", + PhoneNumberUtils.calledPartyBCDToString(b, 0, 7)); + b[0] = (byte) 0x91; b[1] = (byte) 0x71; b[2] = (byte) 0x00; b[3] = (byte) 0x55; b[4] = (byte) 0x05; b[5] = (byte) 0x20; b[6] = (byte) 0xF0; assertEquals("+17005550020", @@ -472,4 +485,20 @@ public class PhoneNumberUtilsTest extends TestCase { PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+18475797000", PhoneNumberUtils.FORMAT_UNKNOWN,PhoneNumberUtils.FORMAT_UNKNOWN)); } + + /** + * Basic checks for the VoiceMail number. + */ + @SmallTest + public void testWithNumberNotEqualToVoiceMail() throws Exception { + assertFalse(PhoneNumberUtils.isVoiceMailNumber("911")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber("tel:911")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber("+18001234567")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber("")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber(null)); + TelephonyManager mTelephonyManager = + (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE); + String mVoiceMailNumber = mTelephonyManager.getDefault().getVoiceMailNumber(); + assertTrue(PhoneNumberUtils.isVoiceMailNumber(mVoiceMailNumber)); + } } diff --git a/telephony/tests/telephonytests/src/com/android/telephonytest/unit/CallerInfoUnitTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/CallerInfoTest.java similarity index 98% rename from telephony/tests/telephonytests/src/com/android/telephonytest/unit/CallerInfoUnitTest.java rename to telephony/tests/telephonytests/src/com/android/internal/telephony/CallerInfoTest.java index 0f24f155046a53648d33311244caa7d983f68038..1e5dafb3d45fe6802a1fa0d2ede5165301ee3e41 100644 --- a/telephony/tests/telephonytests/src/com/android/telephonytest/unit/CallerInfoUnitTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/CallerInfoTest.java @@ -14,7 +14,8 @@ * limitations under the License. */ -package com.android.telephonytest.unit; +package com.android.internal.telephony; + import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; @@ -33,7 +34,7 @@ import android.util.StringBuilderPrinter; * */ -public class CallerInfoUnitTest extends AndroidTestCase { +public class CallerInfoTest extends AndroidTestCase { private CallerInfo mInfo; private Context mContext; diff --git a/telephony/tests/telephonytests/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java b/telephony/tests/telephonytests/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java deleted file mode 100644 index 2d3c548d02a45ef686cd021f01316996727b4559..0000000000000000000000000000000000000000 --- a/telephony/tests/telephonytests/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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. - */ - -package com.android.telephonytest.unit; -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Log; - -import android.telephony.PhoneNumberUtils; -import android.telephony.TelephonyManager; - -/* - * Check the PhoneNumberUtils utility class works as expected. - * - */ - -public class PhoneNumberUtilsUnitTest extends AndroidTestCase { - private String mVoiceMailNumber; - private static final String TAG = "PhoneNumberUtilsUnitTest"; - - @Override - protected void setUp() throws Exception { - super.setUp(); - // FIXME: Why are we getting a security exception here? The - // permission is declared in the manifest.... - // mVoiceMailNumber = TelephonyManager.getDefault().getVoiceMailNumber(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - /** - * Basic checks for the VoiceMail number. - * Assumes READ_PHONE_STATE permission and we don't have it. - */ - // TODO: Figure out why we don't have the permission declared in the manifest. - @SmallTest - public void testWithNumberNotEqualToVoiceMail() throws Exception { - assertFalse(PhoneNumberUtils.isVoiceMailNumber("911")); - assertFalse(PhoneNumberUtils.isVoiceMailNumber("tel:911")); - assertFalse(PhoneNumberUtils.isVoiceMailNumber("+18001234567")); - assertFalse(PhoneNumberUtils.isVoiceMailNumber("")); - assertFalse(PhoneNumberUtils.isVoiceMailNumber(null)); - // FIXME: - // assertTrue(PhoneNumberUtils.isVoiceMailNumber(mVoiceMailNumber)); - } - -} diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index 4964f0394678f4f0e44172319c36b4a7e84dd2a2..3e77b9b296c4df832156d3bbe8077ec5a750f261 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -267,6 +267,26 @@ public class MockPackageManager extends PackageManager { public Drawable getApplicationIcon(String packageName) throws NameNotFoundException { throw new UnsupportedOperationException(); } + + @Override + public Drawable getActivityLogo(ComponentName activityName) throws NameNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public Drawable getActivityLogo(Intent intent) throws NameNotFoundException { + throw new UnsupportedOperationException(); + } + + @Override + public Drawable getApplicationLogo(ApplicationInfo info) { + throw new UnsupportedOperationException(); + } + + @Override + public Drawable getApplicationLogo(String packageName) throws NameNotFoundException { + throw new UnsupportedOperationException(); + } @Override public CharSequence getText(String packageName, int resid, ApplicationInfo appInfo) { diff --git a/tests/DpiTest/Android.mk b/tests/DpiTest/Android.mk index 3596c39a6b288fef054e4ea937f8d832d099227b..5463a1777c5ed4826d669fd3f3c6f6c6b636e391 100644 --- a/tests/DpiTest/Android.mk +++ b/tests/DpiTest/Android.mk @@ -7,4 +7,6 @@ LOCAL_PACKAGE_NAME := DensityTest LOCAL_MODULE_TAGS := tests +LOCAL_AAPT_FLAGS = -c 120dpi -c 240dpi -c 160dpi + include $(BUILD_PACKAGE) diff --git a/tests/DpiTest/res/values-xlarge-long/strings.xml b/tests/DpiTest/res/values-xlarge-long/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..86ab66002de8d4de7cf527120543f1c08bb06ed3 --- /dev/null +++ b/tests/DpiTest/res/values-xlarge-long/strings.xml @@ -0,0 +1,19 @@ + + + + + DpiTest: XLarge Long + diff --git a/tests/DpiTest/res/values-xlarge-notlong/strings.xml b/tests/DpiTest/res/values-xlarge-notlong/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..1eebbf432270411faa66fa64000f993ed158b9e0 --- /dev/null +++ b/tests/DpiTest/res/values-xlarge-notlong/strings.xml @@ -0,0 +1,19 @@ + + + + + DpiTest: XLarge NotLong + diff --git a/tests/DpiTest/res/values-xlarge/strings.xml b/tests/DpiTest/res/values-xlarge/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..7e5d4b065b15f37f6a43559ba6c953782ebeec2b --- /dev/null +++ b/tests/DpiTest/res/values-xlarge/strings.xml @@ -0,0 +1,19 @@ + + + + + DpiTest: XLarge + diff --git a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java index cde2c719933fc4f1b3a70f8152177f200a38fdc4..6192a3c59b592c2c97ab5ef9c47ad2b8bbef3f20 100644 --- a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java +++ b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java @@ -56,7 +56,8 @@ public class DpiTestActivity extends Activity { ApplicationInfo ai = app.getPackageManager().getApplicationInfo( "com.google.android.test.dpi", 0); if (noCompat) { - ai.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS + ai.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS + | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS | ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java index f548145e11ea82dd7feb39b8a68fb6c3d07b44a3..e7a09d13dec0307e93105ba9d9316b8b05384b13 100644 --- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java +++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java @@ -205,6 +205,8 @@ public class NotificationTestList extends TestActivity Notification n = new Notification(); n.flags |= Notification.FLAG_SHOW_LIGHTS; n.ledARGB = 0xff0000ff; + n.ledOnMS = 1; + n.ledOffMS = 0; mNM.notify(1, n); } }, @@ -215,6 +217,8 @@ public class NotificationTestList extends TestActivity Notification n = new Notification(); n.flags |= Notification.FLAG_SHOW_LIGHTS; n.ledARGB = 0xffff0000; + n.ledOnMS = 1; + n.ledOffMS = 0; mNM.notify(1, n); } }, @@ -225,6 +229,20 @@ public class NotificationTestList extends TestActivity Notification n = new Notification(); n.flags |= Notification.FLAG_SHOW_LIGHTS; n.ledARGB = 0xffffff00; + n.ledOnMS = 1; + n.ledOffMS = 0; + mNM.notify(1, n); + } + }, + + new Test("Lights off") { + public void run() + { + Notification n = new Notification(); + n.flags |= Notification.FLAG_SHOW_LIGHTS; + n.ledARGB = 0x00000000; + n.ledOnMS = 0; + n.ledOffMS = 0; mNM.notify(1, n); } }, @@ -234,7 +252,7 @@ public class NotificationTestList extends TestActivity { Notification n = new Notification(); n.flags |= Notification.FLAG_SHOW_LIGHTS; - n.ledARGB = 0xffffff00; + n.ledARGB = 0xff0000ff; n.ledOnMS = 1300; n.ledOffMS = 1300; mNM.notify(1, n); @@ -246,7 +264,7 @@ public class NotificationTestList extends TestActivity { Notification n = new Notification(); n.flags |= Notification.FLAG_SHOW_LIGHTS; - n.ledARGB = 0xffffff00; + n.ledARGB = 0xff0000ff; n.ledOnMS = 300; n.ledOffMS = 300; mNM.notify(1, n); diff --git a/tests/framework-tests/src/Android.mk b/tests/framework-tests/src/Android.mk index 54e33a4ce1914600c3080f148b623713f5d93ebf..f537b52cffdb2faf5f408af7459c753d6be5add9 100644 --- a/tests/framework-tests/src/Android.mk +++ b/tests/framework-tests/src/Android.mk @@ -5,6 +5,6 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_MODULE := framework-tests -LOCAL_JAVA_LIBRARIES := android.policy_phone android.test.runner +LOCAL_JAVA_LIBRARIES := android.policy android.test.runner include $(BUILD_JAVA_LIBRARY) diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index fc655a7abbb7e966d537fe1c56e9fe10d7146943..4d2d046bd921eb5198841179968bbc2c6f1e2aed 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -766,6 +766,11 @@ bool AaptGroupEntry::getScreenLayoutSizeName(const char* name, (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) | ResTable_config::SCREENSIZE_LARGE; return true; + } else if (strcmp(name, "xlarge") == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) + | ResTable_config::SCREENSIZE_XLARGE; + return true; } return false; diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp index fc658f5b54fba746e80492774f740c7c3e2c5896..f17f66b31f8e9d95415dbac7f95ad5db3a0ae2d5 100644 --- a/tools/aidl/aidl.cpp +++ b/tools/aidl/aidl.cpp @@ -55,7 +55,7 @@ test_document(document_item_type* d) printf("parcelable %s %s;\n", b->package, b->name.data); } else { - printf("UNKNOWN d=0x%08x d->item_type=%ld\n", (long)d, d->item_type); + printf("UNKNOWN d=0x%08lx d->item_type=%d\n", (long)d, d->item_type); } d = d->next; } diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java index ce522c848f69aff33120c16429f6a66aada8ba8e..ce40b5d0c122701000abdbfa78e16ff8290707e9 100644 --- a/vpn/java/android/net/vpn/VpnManager.java +++ b/vpn/java/android/net/vpn/VpnManager.java @@ -85,7 +85,8 @@ public class VpnManager { // TODO(oam): Test VPN when EFS is enabled (will do later)... public static String getProfilePath() { - return Environment.getDataDirectory().getPath() + PROFILES_PATH; + // This call will return the correct path if Encrypted FS is enabled or not. + return Environment.getSecureDataDirectory().getPath() + PROFILES_PATH; } /**