Merge "ACodec: read max pts gap and max fps keys for image encoders" into qt-qpr1-dev
am: 16639a6e00
Change-Id: I2b9a85c45dc8d7fe5a6c4993cb6679ff29b8db5d
diff --git a/camera/Android.bp b/camera/Android.bp
index 2800595..b288bcf 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -86,6 +86,7 @@
"aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl",
"aidl/android/hardware/camera2/ICameraDeviceUser.aidl",
],
+ path: "aidl",
}
// Extra AIDL files that are used by framework.jar but not libcamera_client
@@ -96,4 +97,5 @@
"aidl/android/hardware/ICamera.aidl",
"aidl/android/hardware/ICameraClient.aidl",
],
+ path: "aidl",
}
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index ecaba3a..334f879 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -25,7 +25,6 @@
"libgui",
"libbinder",
"libhidlbase",
- "libhidltransport",
"android.hardware.camera.common@1.0",
"android.hardware.camera.provider@2.4",
"android.hardware.camera.provider@2.5",
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index a2ee65d..d8220eb 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -107,7 +107,6 @@
],
shared_libs: [
- "libhwbinder",
"libfmq",
"libhidlbase",
"libhardware",
@@ -143,7 +142,6 @@
vendor: true,
srcs: ["ndk_vendor/tests/AImageReaderVendorTest.cpp"],
shared_libs: [
- "libhwbinder",
"libcamera2ndk_vendor",
"libcamera_metadata",
"libmediandk",
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index 7aa655f..df28842 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -368,6 +368,7 @@
int64_t startWhenNsec = systemTime(CLOCK_MONOTONIC);
int64_t endWhenNsec = startWhenNsec + seconds_to_nanoseconds(gTimeLimitSec);
DisplayInfo mainDpyInfo;
+ bool firstFrame = true;
assert((rawFp == NULL && muxer != NULL) || (rawFp != NULL && muxer == NULL));
@@ -384,6 +385,11 @@
int64_t ptsUsec;
uint32_t flags;
+ if (firstFrame) {
+ ATRACE_NAME("first_frame");
+ firstFrame = false;
+ }
+
if (systemTime(CLOCK_MONOTONIC) > endWhenNsec) {
if (gVerbose) {
printf("Time limit reached\n");
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 6eb2e9f..0c8d44a 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -17,7 +17,6 @@
frameworks/av/media/libstagefright \
frameworks/av/media/libstagefright/include \
frameworks/native/include/media/openmax \
- external/jpeg \
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
@@ -154,9 +153,9 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- filters/argbtorgba.rs \
- filters/nightvision.rs \
- filters/saturation.rs \
+ filters/argbtorgba.rscript \
+ filters/nightvision.rscript \
+ filters/saturation.rscript \
mediafilter.cpp \
LOCAL_SHARED_LIBRARIES := \
diff --git a/cmds/stagefright/filters/argbtorgba.rs b/cmds/stagefright/filters/argbtorgba.rscript
similarity index 100%
rename from cmds/stagefright/filters/argbtorgba.rs
rename to cmds/stagefright/filters/argbtorgba.rscript
diff --git a/cmds/stagefright/filters/nightvision.rs b/cmds/stagefright/filters/nightvision.rscript
similarity index 100%
rename from cmds/stagefright/filters/nightvision.rs
rename to cmds/stagefright/filters/nightvision.rscript
diff --git a/cmds/stagefright/filters/saturation.rs b/cmds/stagefright/filters/saturation.rscript
similarity index 100%
rename from cmds/stagefright/filters/saturation.rs
rename to cmds/stagefright/filters/saturation.rscript
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index d6db1d4..6dce472 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -34,7 +34,6 @@
"android.hardware.drm@1.2",
"libhidlallocatorutils",
"libhidlbase",
- "libhidltransport",
],
cflags: [
diff --git a/drm/mediacas/plugins/clearkey/Android.bp b/drm/mediacas/plugins/clearkey/Android.bp
new file mode 100644
index 0000000..0113cb8
--- /dev/null
+++ b/drm/mediacas/plugins/clearkey/Android.bp
@@ -0,0 +1,55 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_library_shared {
+ name: "libclearkeycasplugin",
+
+ srcs: [
+ "ClearKeyCasPlugin.cpp",
+ "ClearKeyFetcher.cpp",
+ "ClearKeyLicenseFetcher.cpp",
+ "ClearKeySessionLibrary.cpp",
+ "ecm.cpp",
+ "ecm_generator.cpp",
+ "JsonAssetLoader.cpp",
+ "protos/license_protos.proto",
+ ],
+
+ proprietary: true,
+ relative_install_path: "mediacas",
+
+ shared_libs: [
+ "libutils",
+ "liblog",
+ "libcrypto",
+ "libstagefright_foundation",
+ "libprotobuf-cpp-lite",
+ ],
+
+ header_libs: ["media_plugin_headers"],
+
+ static_libs: ["libjsmn"],
+
+ proto: {
+ type: "full",
+ export_proto_headers: true,
+ },
+
+ include_dirs: [
+ "frameworks/av/include",
+ "frameworks/native/include/media",
+ ],
+}
diff --git a/drm/mediacas/plugins/clearkey/Android.mk b/drm/mediacas/plugins/clearkey/Android.mk
deleted file mode 100644
index 4b139a8..0000000
--- a/drm/mediacas/plugins/clearkey/Android.mk
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- ClearKeyCasPlugin.cpp \
- ClearKeyFetcher.cpp \
- ClearKeyLicenseFetcher.cpp \
- ClearKeySessionLibrary.cpp \
- ecm.cpp \
- ecm_generator.cpp \
- JsonAssetLoader.cpp \
- protos/license_protos.proto \
-
-LOCAL_MODULE := libclearkeycasplugin
-
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := mediacas
-
-LOCAL_SHARED_LIBRARIES := \
- libutils \
- liblog \
- libcrypto \
- libstagefright_foundation \
- libprotobuf-cpp-lite \
-
-LOCAL_HEADER_LIBRARIES := \
- media_plugin_headers
-
-LOCAL_STATIC_LIBRARIES := \
- libjsmn \
-
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-
-define proto_includes
-$(call local-generated-sources-dir)/proto/$(LOCAL_PATH)
-endef
-
-LOCAL_C_INCLUDES += \
- external/jsmn \
- frameworks/av/include \
- frameworks/native/include/media \
- $(call proto_includes)
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
- $(call proto_includes)
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-#########################################################################
-# Build unit tests
-
-include $(LOCAL_PATH)/tests/Android.mk
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
index eaa3390..cb69f91 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
@@ -89,7 +89,7 @@
// asset_id change. If it sends an EcmContainer with 2 Ecms with different
// asset_ids (old and new) then it might be best to prefetch the Emm.
if ((asset_.id() != 0) && (*asset_id != asset_.id())) {
- ALOGW("Asset_id change from %llu to %" PRIu64, asset_.id(), *asset_id);
+ ALOGW("Asset_id change from %" PRIu64 " to %" PRIu64, asset_.id(), *asset_id);
asset_.Clear();
}
diff --git a/drm/mediacas/plugins/clearkey/ecm.cpp b/drm/mediacas/plugins/clearkey/ecm.cpp
index 9fde13a..b3b5218 100644
--- a/drm/mediacas/plugins/clearkey/ecm.cpp
+++ b/drm/mediacas/plugins/clearkey/ecm.cpp
@@ -17,6 +17,8 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ecm"
+#include <inttypes.h>
+
#include "ecm.h"
#include "ecm_generator.h"
#include "protos/license_protos.pb.h"
@@ -76,7 +78,7 @@
return status;
}
if (asset.id() != asset_from_emm.id()) {
- ALOGE("Asset_id from Emm (%llu) does not match asset_id from Ecm (%llu).",
+ ALOGE("Asset_id from Emm (%" PRIu64 ") does not match asset_id from Ecm (%" PRIu64 ").",
asset_from_emm.id(), asset.id());
return CLEARKEY_STATUS_INVALID_PARAMETER;
}
diff --git a/drm/mediacas/plugins/clearkey/tests/Android.bp b/drm/mediacas/plugins/clearkey/tests/Android.bp
new file mode 100644
index 0000000..575863c
--- /dev/null
+++ b/drm/mediacas/plugins/clearkey/tests/Android.bp
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_test {
+ name: "ClearKeyFetcherTest",
+
+ srcs: ["ClearKeyFetcherTest.cpp"],
+
+ vendor: true,
+
+ // LOCAL_LDFLAGS is needed here for the test to use the plugin, because
+ // the plugin is not in standard library search path. Without this .so
+ // loading fails at run-time (linking is okay).
+ ldflags: [
+ "-Wl,--rpath,${ORIGIN}/../../../system/vendor/lib/mediacas",
+ "-Wl,--enable-new-dtags",
+ ],
+
+ shared_libs: [
+ "libutils",
+ "libclearkeycasplugin",
+ "libstagefright_foundation",
+ "libprotobuf-cpp-lite",
+ "liblog",
+ ],
+
+ include_dirs: [
+ "frameworks/av/drm/mediacas/plugins/clearkey",
+ "frameworks/av/include",
+ "frameworks/native/include/media",
+ ],
+}
diff --git a/drm/mediacas/plugins/clearkey/tests/Android.mk b/drm/mediacas/plugins/clearkey/tests/Android.mk
deleted file mode 100644
index e1545af..0000000
--- a/drm/mediacas/plugins/clearkey/tests/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- ClearKeyFetcherTest.cpp
-
-LOCAL_MODULE := ClearKeyFetcherTest
-LOCAL_VENDOR_MODULE := true
-
-# LOCAL_LDFLAGS is needed here for the test to use the plugin, because
-# the plugin is not in standard library search path. Without this .so
-# loading fails at run-time (linking is okay).
-LOCAL_LDFLAGS := \
- -Wl,--rpath,\$${ORIGIN}/../../../system/vendor/lib/mediacas -Wl,--enable-new-dtags
-
-LOCAL_SHARED_LIBRARIES := \
- libutils libclearkeycasplugin libstagefright_foundation libprotobuf-cpp-lite liblog
-
-LOCAL_C_INCLUDES += \
- $(TOP)/frameworks/av/drm/mediacas/plugins/clearkey \
- $(TOP)/frameworks/av/include \
- $(TOP)/frameworks/native/include/media \
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_NATIVE_TEST)
-
-
-
diff --git a/drm/mediacas/plugins/mock/Android.bp b/drm/mediacas/plugins/mock/Android.bp
new file mode 100644
index 0000000..e8a3c6f
--- /dev/null
+++ b/drm/mediacas/plugins/mock/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_library_shared {
+ name: "libmockcasplugin",
+
+ srcs: [
+ "MockCasPlugin.cpp",
+ "MockSessionLibrary.cpp",
+ ],
+
+ proprietary: true,
+ relative_install_path: "mediacas",
+
+ shared_libs: [
+ "libutils",
+ "liblog",
+ ],
+
+ header_libs: ["media_plugin_headers"],
+
+ include_dirs: [
+ "frameworks/av/include",
+ "frameworks/native/include/media",
+ ],
+}
diff --git a/drm/mediacas/plugins/mock/Android.mk b/drm/mediacas/plugins/mock/Android.mk
deleted file mode 100644
index a1d61da..0000000
--- a/drm/mediacas/plugins/mock/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- MockCasPlugin.cpp \
- MockSessionLibrary.cpp \
-
-LOCAL_MODULE := libmockcasplugin
-
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := mediacas
-
-LOCAL_SHARED_LIBRARIES := \
- libutils liblog
-
-LOCAL_HEADER_LIBRARIES := media_plugin_headers
-
-LOCAL_C_INCLUDES += \
- $(TOP)/frameworks/av/include \
- $(TOP)/frameworks/native/include/media \
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
index e91e918..a153ce2 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
@@ -48,7 +48,6 @@
"libcrypto",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
"liblog",
"libprotobuf-cpp-lite",
"libutils",
diff --git a/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp b/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
index 99fd883..a510487 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
@@ -38,7 +38,7 @@
configureRpcThreadpool(8, true /* callerWillJoin */);
// Setup hwbinder service
- LazyServiceRegistrar serviceRegistrar;
+ auto serviceRegistrar = LazyServiceRegistrar::getInstance();
// Setup hwbinder service
CHECK_EQ(serviceRegistrar.registerService(drmFactory, "clearkey"), android::NO_ERROR)
diff --git a/include/media/ExtendedAudioBufferProvider.h b/include/media/ExtendedAudioBufferProvider.h
index d653cc3..99d3c13 120000
--- a/include/media/ExtendedAudioBufferProvider.h
+++ b/include/media/ExtendedAudioBufferProvider.h
@@ -1 +1 @@
-../../media/libmedia/include/media/ExtendedAudioBufferProvider.h
\ No newline at end of file
+../../media/libaudioclient/include/media/ExtendedAudioBufferProvider.h
\ No newline at end of file
diff --git a/include/media/SingleStateQueue.h b/include/media/SingleStateQueue.h
deleted file mode 120000
index 619f6ee..0000000
--- a/include/media/SingleStateQueue.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/SingleStateQueue.h
\ No newline at end of file
diff --git a/include/media/nbaio/SingleStateQueue.h b/include/media/nbaio/SingleStateQueue.h
new file mode 120000
index 0000000..d3e0553
--- /dev/null
+++ b/include/media/nbaio/SingleStateQueue.h
@@ -0,0 +1 @@
+../../../media/libnbaio/include_mono/media/nbaio/SingleStateQueue.h
\ No newline at end of file
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 5f19f74..1b1f149 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -28,7 +28,7 @@
#include <media/AudioResamplerPublic.h>
#include <media/AudioTimestamp.h>
#include <media/Modulo.h>
-#include <media/SingleStateQueue.h>
+#include <media/nbaio/SingleStateQueue.h>
namespace android {
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index 33b36b8..f5f021b 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -13,8 +13,6 @@
libcutils \
liblog \
libhidlbase \
- libhidltransport \
- libhwbinder \
libmedia \
libmedialogservice \
libmediautils \
@@ -34,13 +32,11 @@
frameworks/av/services/audiopolicy/service \
frameworks/av/services/medialog \
frameworks/av/services/oboeservice \
- frameworks/av/services/radio \
frameworks/av/services/soundtrigger \
frameworks/av/media/libaaudio/include \
frameworks/av/media/libaaudio/src \
frameworks/av/media/libaaudio/src/binding \
frameworks/av/media/libmedia \
- $(call include-path-for, audio-utils) \
external/sonic \
# If AUDIOSERVER_MULTILIB in device.mk is non-empty then it is used to control
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index dfb1a3f..3f3ef69 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -2,7 +2,7 @@
class core
user audioserver
# media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
- group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock
+ group audio camera drmrpc media mediadrm net_bt net_bt_admin net_bw_acct wakelock
capabilities BLOCK_SUSPEND
ioprio rt 4
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
diff --git a/media/bufferpool/1.0/Android.bp b/media/bufferpool/1.0/Android.bp
index c7ea70f..f817c76 100644
--- a/media/bufferpool/1.0/Android.bp
+++ b/media/bufferpool/1.0/Android.bp
@@ -16,8 +16,6 @@
"libcutils",
"libfmq",
"libhidlbase",
- "libhwbinder",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.media.bufferpool@1.0",
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
index e8a69c9..97f114a 100644
--- a/media/bufferpool/2.0/Android.bp
+++ b/media/bufferpool/2.0/Android.bp
@@ -16,8 +16,6 @@
"libcutils",
"libfmq",
"libhidlbase",
- "libhwbinder",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.media.bufferpool@2.0",
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
index 36053f6..54c8c47 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
@@ -517,9 +517,11 @@
if (layout.planes[layout.PLANE_Y].colInc == 1
&& layout.planes[layout.PLANE_U].colInc == 1
&& layout.planes[layout.PLANE_V].colInc == 1
+ && yStride == align(width, 16)
&& uStride == vStride
&& yStride == 2 * vStride) {
- // I420 compatible - planes are already set up above
+ // I420 compatible with yStride being equal to aligned width
+ // planes are already set up above
break;
}
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index f1f1536..bdff29a 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -80,8 +80,6 @@
"libcodec2_vndk",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libstagefright_bufferpool@2.0.1",
"libstagefright_bufferqueue_helper",
diff --git a/media/codec2/hidl/client/Android.bp b/media/codec2/hidl/client/Android.bp
index e184223..89c1c4a 100644
--- a/media/codec2/hidl/client/Android.bp
+++ b/media/codec2/hidl/client/Android.bp
@@ -17,7 +17,6 @@
"libcutils",
"libgui",
"libhidlbase",
- "libhidltransport",
"liblog",
"libstagefright_bufferpool@2.0.1",
"libui",
diff --git a/media/codec2/hidl/services/Android.bp b/media/codec2/hidl/services/Android.bp
index 216525e..0403a1f 100644
--- a/media/codec2/hidl/services/Android.bp
+++ b/media/codec2/hidl/services/Android.bp
@@ -17,8 +17,6 @@
"libcodec2_hidl@1.0",
"libcodec2_vndk",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libstagefright_omx",
"libstagefright_xmlparser",
diff --git a/media/libaaudio/Android.bp b/media/libaaudio/Android.bp
index 16958f9..140052f 100644
--- a/media/libaaudio/Android.bp
+++ b/media/libaaudio/Android.bp
@@ -24,7 +24,7 @@
ndk_library {
name: "libaaudio",
// deliberately includes symbols from AAudioTesting.h
- symbol_file: "libaaudio.map.txt",
+ symbol_file: "src/libaaudio.map.txt",
first_version: "26",
unversioned_until: "current",
}
@@ -32,6 +32,5 @@
cc_library_headers {
name: "libaaudio_headers",
export_include_dirs: ["include"],
- version_script: "libaaudio.map.txt",
}
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
index 4090286..56c0170 100644
--- a/media/libaaudio/src/Android.bp
+++ b/media/libaaudio/src/Android.bp
@@ -10,14 +10,71 @@
"legacy",
"utility",
],
+ header_libs: ["libaaudio_headers"],
+ export_header_lib_headers: ["libaaudio_headers"],
+ version_script: "libaaudio.map.txt",
+
+ srcs: [
+ "core/AAudioAudio.cpp",
+ ],
+
+ cflags: [
+ "-Wno-unused-parameter",
+ "-Wall",
+ "-Werror",
+
+ // By default, all symbols are hidden.
+ // "-fvisibility=hidden",
+ // AAUDIO_API is used to explicitly export a function or a variable as a visible symbol.
+ "-DAAUDIO_API=__attribute__((visibility(\"default\")))",
+ ],
+
+ shared_libs: [
+ "libaaudio_internal",
+ "libaudioclient",
+ "libaudioutils",
+ "liblog",
+ "libcutils",
+ "libutils",
+ "libbinder",
+ ],
+}
+
+cc_library {
+ name: "libaaudio_internal",
+
+ local_include_dirs: [
+ "binding",
+ "client",
+ "core",
+ "fifo",
+ "legacy",
+ "utility",
+ ],
+
export_include_dirs: ["."],
header_libs: ["libaaudio_headers"],
export_header_lib_headers: ["libaaudio_headers"],
+ shared_libs: [
+ "libaudioclient",
+ "libaudioutils",
+ "liblog",
+ "libcutils",
+ "libutils",
+ "libbinder",
+ ],
+
+ cflags: [
+ "-Wno-unused-parameter",
+ "-Wall",
+ "-Werror",
+ ],
+
srcs: [
+ "core/AudioGlobal.cpp",
"core/AudioStream.cpp",
"core/AudioStreamBuilder.cpp",
- "core/AAudioAudio.cpp",
"core/AAudioStreamParameters.cpp",
"legacy/AudioStreamLegacy.cpp",
"legacy/AudioStreamRecord.cpp",
@@ -54,25 +111,4 @@
"flowgraph/SourceI16.cpp",
"flowgraph/SourceI24.cpp",
],
-
- cflags: [
- "-Wno-unused-parameter",
- "-Wall",
- "-Werror",
-
- // By default, all symbols are hidden.
- // "-fvisibility=hidden",
- // AAUDIO_API is used to explicitly export a function or a variable as a visible symbol.
- "-DAAUDIO_API=__attribute__((visibility(\"default\")))",
- ],
-
- shared_libs: [
- "libaudioclient",
- "libaudioutils",
- "liblog",
- "libcutils",
- "libutils",
- "libbinder",
- "libaudiomanager",
- ],
}
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 52eadd4..fb276c2 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -36,6 +36,7 @@
#include "binding/AAudioStreamConfiguration.h"
#include "binding/IAAudioService.h"
#include "binding/AAudioServiceMessage.h"
+#include "core/AudioGlobal.h"
#include "core/AudioStreamBuilder.h"
#include "fifo/FifoBuffer.h"
#include "utility/AudioClock.h"
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 44d5122..8040e6a 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -27,6 +27,7 @@
#include <aaudio/AAudioTesting.h>
#include "AudioClock.h"
+#include "AudioGlobal.h"
#include "AudioStreamBuilder.h"
#include "AudioStream.h"
#include "binding/AAudioCommon.h"
@@ -45,63 +46,14 @@
return AAUDIO_ERROR_NULL; \
}
-#define AAUDIO_CASE_ENUM(name) case name: return #name
-
AAUDIO_API const char * AAudio_convertResultToText(aaudio_result_t returnCode) {
- switch (returnCode) {
- AAUDIO_CASE_ENUM(AAUDIO_OK);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_DISCONNECTED);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_ILLEGAL_ARGUMENT);
- // reserved
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_INTERNAL);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_STATE);
- // reserved
- // reserved
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_HANDLE);
- // reserved
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNIMPLEMENTED);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNAVAILABLE);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_FREE_HANDLES);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_MEMORY);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_NULL);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_TIMEOUT);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_WOULD_BLOCK);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_FORMAT);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_OUT_OF_RANGE);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_SERVICE);
- AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_RATE);
- }
- return "Unrecognized AAudio error.";
+ return AudioGlobal_convertResultToText(returnCode);
}
AAUDIO_API const char * AAudio_convertStreamStateToText(aaudio_stream_state_t state) {
- switch (state) {
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNINITIALIZED);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNKNOWN);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_OPEN);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTING);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTED);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSING);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSED);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHING);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHED);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPING);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPED);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_DISCONNECTED);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSING);
- AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSED);
- }
- return "Unrecognized AAudio state.";
+ return AudioGlobal_convertStreamStateToText(state);
}
-#undef AAUDIO_CASE_ENUM
-
-
-/******************************************
- * Static globals.
- */
-static aaudio_policy_t s_MMapPolicy = AAUDIO_UNSPECIFIED;
-
static AudioStream *convertAAudioStreamToAudioStream(AAudioStream* stream)
{
return (AudioStream*) stream;
@@ -543,23 +495,11 @@
}
AAUDIO_API aaudio_policy_t AAudio_getMMapPolicy() {
- return s_MMapPolicy;
+ return AudioGlobal_getMMapPolicy();
}
AAUDIO_API aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy) {
- aaudio_result_t result = AAUDIO_OK;
- switch(policy) {
- case AAUDIO_UNSPECIFIED:
- case AAUDIO_POLICY_NEVER:
- case AAUDIO_POLICY_AUTO:
- case AAUDIO_POLICY_ALWAYS:
- s_MMapPolicy = policy;
- break;
- default:
- result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
- break;
- }
- return result;
+ return AudioGlobal_setMMapPolicy(policy);
}
AAUDIO_API bool AAudioStream_isMMapUsed(AAudioStream* stream)
diff --git a/media/libaaudio/src/core/AudioGlobal.cpp b/media/libaaudio/src/core/AudioGlobal.cpp
new file mode 100644
index 0000000..e6d9a0d
--- /dev/null
+++ b/media/libaaudio/src/core/AudioGlobal.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 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 <aaudio/AAudio.h>
+#include <aaudio/AAudioTesting.h>
+
+#include "AudioGlobal.h"
+
+/******************************************
+ * Static globals.
+ */
+namespace aaudio {
+
+static aaudio_policy_t g_MMapPolicy = AAUDIO_UNSPECIFIED;
+
+aaudio_policy_t AudioGlobal_getMMapPolicy() {
+ return g_MMapPolicy;
+}
+
+aaudio_result_t AudioGlobal_setMMapPolicy(aaudio_policy_t policy) {
+ aaudio_result_t result = AAUDIO_OK;
+ switch(policy) {
+ case AAUDIO_UNSPECIFIED:
+ case AAUDIO_POLICY_NEVER:
+ case AAUDIO_POLICY_AUTO:
+ case AAUDIO_POLICY_ALWAYS:
+ g_MMapPolicy = policy;
+ break;
+ default:
+ result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
+ break;
+ }
+ return result;
+}
+
+#define AAUDIO_CASE_ENUM(name) case name: return #name
+
+const char* AudioGlobal_convertResultToText(aaudio_result_t returnCode) {
+ switch (returnCode) {
+ AAUDIO_CASE_ENUM(AAUDIO_OK);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_DISCONNECTED);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_ILLEGAL_ARGUMENT);
+ // reserved
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_INTERNAL);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_STATE);
+ // reserved
+ // reserved
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_HANDLE);
+ // reserved
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNIMPLEMENTED);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNAVAILABLE);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_FREE_HANDLES);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_MEMORY);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_NULL);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_TIMEOUT);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_WOULD_BLOCK);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_FORMAT);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_OUT_OF_RANGE);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_SERVICE);
+ AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_RATE);
+ }
+ return "Unrecognized AAudio error.";
+}
+
+const char* AudioGlobal_convertStreamStateToText(aaudio_stream_state_t state) {
+ switch (state) {
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNINITIALIZED);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNKNOWN);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_OPEN);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTING);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTED);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSING);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSED);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHING);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHED);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPING);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPED);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_DISCONNECTED);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSING);
+ AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSED);
+ }
+ return "Unrecognized AAudio state.";
+}
+
+#undef AAUDIO_CASE_ENUM
+
+} // namespace aaudio
diff --git a/media/libaaudio/src/core/AudioGlobal.h b/media/libaaudio/src/core/AudioGlobal.h
new file mode 100644
index 0000000..312cef2
--- /dev/null
+++ b/media/libaaudio/src/core/AudioGlobal.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2019 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 AAUDIO_AUDIOGLOBAL_H
+#define AAUDIO_AUDIOGLOBAL_H
+
+#include <aaudio/AAudio.h>
+#include <aaudio/AAudioTesting.h>
+
+
+namespace aaudio {
+
+aaudio_policy_t AudioGlobal_getMMapPolicy();
+aaudio_result_t AudioGlobal_setMMapPolicy(aaudio_policy_t policy);
+
+const char* AudioGlobal_convertResultToText(aaudio_result_t returnCode);
+const char* AudioGlobal_convertStreamStateToText(aaudio_stream_state_t state);
+
+}
+
+#endif // AAUDIO_AUDIOGLOBAL_H
+
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 9b77223..5303631 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -25,8 +25,9 @@
#include "AudioStreamBuilder.h"
#include "AudioStream.h"
#include "AudioClock.h"
+#include "AudioGlobal.h"
-using namespace aaudio;
+namespace aaudio {
// Sequential number assigned to streams solely for debugging purposes.
@@ -51,7 +52,7 @@
|| getState() == AAUDIO_STREAM_STATE_UNINITIALIZED
|| getState() == AAUDIO_STREAM_STATE_DISCONNECTED),
"~AudioStream() - still in use, state = %s",
- AAudio_convertStreamStateToText(getState()));
+ AudioGlobal_convertStreamStateToText(getState()));
mPlayerBase->clearParentReference(); // remove reference to this AudioStream
}
@@ -155,7 +156,7 @@
case AAUDIO_STREAM_STATE_CLOSED:
default:
ALOGW("safePause() stream not running, state = %s",
- AAudio_convertStreamStateToText(getState()));
+ AudioGlobal_convertStreamStateToText(getState()));
return AAUDIO_ERROR_INVALID_STATE;
}
@@ -240,7 +241,7 @@
case AAUDIO_STREAM_STATE_CLOSED:
default:
ALOGW("%s() stream not running, state = %s", __func__,
- AAudio_convertStreamStateToText(getState()));
+ AudioGlobal_convertStreamStateToText(getState()));
return AAUDIO_ERROR_INVALID_STATE;
}
@@ -488,3 +489,5 @@
void AudioStream::MyPlayerBase::destroy() {
unregisterWithAudioManager();
}
+
+} // namespace aaudio
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 08f4958..44f45b3 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -27,6 +27,7 @@
#include "binding/AAudioBinderClient.h"
#include "client/AudioStreamInternalCapture.h"
#include "client/AudioStreamInternalPlay.h"
+#include "core/AudioGlobal.h"
#include "core/AudioStream.h"
#include "core/AudioStreamBuilder.h"
#include "legacy/AudioStreamRecord.h"
@@ -112,7 +113,7 @@
}
// The API setting is the highest priority.
- aaudio_policy_t mmapPolicy = AAudio_getMMapPolicy();
+ aaudio_policy_t mmapPolicy = AudioGlobal_getMMapPolicy();
// If not specified then get from a system property.
if (mmapPolicy == AAUDIO_UNSPECIFIED) {
mmapPolicy = AAudioProperty_getMMapPolicy();
diff --git a/media/libaaudio/libaaudio.map.txt b/media/libaaudio/src/libaaudio.map.txt
similarity index 100%
rename from media/libaaudio/libaaudio.map.txt
rename to media/libaaudio/src/libaaudio.map.txt
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 96ed56a..cdd02c0 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -24,6 +24,7 @@
#include <utils/Errors.h>
#include "aaudio/AAudio.h"
+#include "core/AudioGlobal.h"
#include <aaudio/AAudioTesting.h>
#include <math.h>
#include <system/audio-base.h>
@@ -355,7 +356,7 @@
case AAUDIO_STREAM_STATE_DISCONNECTED:
default:
ALOGE("can only flush stream when PAUSED, OPEN or STOPPED, state = %s",
- AAudio_convertStreamStateToText(state));
+ aaudio::AudioGlobal_convertStreamStateToText(state));
result = AAUDIO_ERROR_INVALID_STATE;
break;
}
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 6101e99..19cd0a0 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -11,7 +11,7 @@
defaults: ["libaaudio_tests_defaults"],
srcs: ["test_marshalling.cpp"],
shared_libs: [
- "libaaudio",
+ "libaaudio_internal",
"libbinder",
"libcutils",
"libutils",
@@ -23,7 +23,7 @@
defaults: ["libaaudio_tests_defaults"],
srcs: ["test_clock_model.cpp"],
shared_libs: [
- "libaaudio",
+ "libaaudio_internal",
"libaudioutils",
"libcutils",
"libutils",
@@ -34,7 +34,7 @@
name: "test_block_adapter",
defaults: ["libaaudio_tests_defaults"],
srcs: ["test_block_adapter.cpp"],
- shared_libs: ["libaaudio"],
+ shared_libs: ["libaaudio_internal"],
}
cc_test {
@@ -170,7 +170,7 @@
name: "test_atomic_fifo",
defaults: ["libaaudio_tests_defaults"],
srcs: ["test_atomic_fifo.cpp"],
- shared_libs: ["libaaudio"],
+ shared_libs: ["libaaudio_internal"],
}
cc_test {
@@ -178,7 +178,7 @@
defaults: ["libaaudio_tests_defaults"],
srcs: ["test_flowgraph.cpp"],
shared_libs: [
- "libaaudio",
+ "libaaudio_internal",
"libbinder",
"libcutils",
"libutils",
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 03bd6ce..c516d20 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -42,7 +42,7 @@
// AIDL files for audioclient interfaces
// The headers for these interfaces will be available to any modules that
// include libaudioclient, at the path "aidl/package/path/BnFoo.h"
- "aidl/android/media/IAudioRecord.aidl",
+ ":libaudioclient_aidl_private",
":libaudioclient_aidl",
"AudioEffect.cpp",
@@ -110,4 +110,15 @@
srcs: [
"aidl/android/media/IPlayer.aidl",
],
+ path: "aidl",
+}
+
+// Used to strip the "aidl/" from the path, so the build system can predict the
+// output filename.
+filegroup {
+ name: "libaudioclient_aidl_private",
+ srcs: [
+ "aidl/android/media/IAudioRecord.aidl",
+ ],
+ path: "aidl",
}
diff --git a/media/libmedia/include/media/ExtendedAudioBufferProvider.h b/media/libaudioclient/include/media/ExtendedAudioBufferProvider.h
similarity index 100%
rename from media/libmedia/include/media/ExtendedAudioBufferProvider.h
rename to media/libaudioclient/include/media/ExtendedAudioBufferProvider.h
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 584c2c0..5e22322 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -57,4 +57,10 @@
name: "libaudiohal_headers",
export_include_dirs: ["include"],
+
+ // This is needed because the stream interface includes media/MicrophoneInfo.h
+ // which is not in any library but has a dependency on headers from libbinder.
+ header_libs: ["libbinder_headers"],
+
+ export_header_lib_headers: ["libbinder_headers"],
}
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 88533da..d4a4f41 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -36,8 +36,6 @@
"libhardware",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libmedia_helper",
"libmediautils",
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 1d33590..8de6381 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -1,10 +1,3 @@
-cc_defaults {
- name: "libmedia_defaults",
- include_dirs: [
- "bionic/libc/private",
- ],
-}
-
cc_library_headers {
name: "libmedia_headers",
vendor_available: true,
@@ -47,6 +40,15 @@
clang: true,
}
+filegroup {
+ name: "libmedia_omx_aidl",
+ srcs: [
+ "aidl/android/IGraphicBufferSource.aidl",
+ "aidl/android/IOMXBufferSource.aidl",
+ ],
+ path: "aidl",
+}
+
cc_library_shared {
name: "libmedia_omx",
vendor_available: true,
@@ -56,8 +58,7 @@
double_loadable: true,
srcs: [
- "aidl/android/IGraphicBufferSource.aidl",
- "aidl/android/IOMXBufferSource.aidl",
+ ":libmedia_omx_aidl",
"IMediaCodecList.cpp",
"IOMX.cpp",
@@ -85,7 +86,6 @@
"libbinder",
"libcutils",
"libhidlbase",
- "libhidltransport",
"liblog",
"libstagefright_foundation",
"libui",
@@ -146,7 +146,6 @@
"libcutils",
"libgui",
"libhidlbase",
- "libhidltransport",
"liblog",
"libmedia_omx",
"libstagefright_foundation",
@@ -221,8 +220,6 @@
cc_library {
name: "libmedia",
- defaults: [ "libmedia_defaults" ],
-
srcs: [
"IDataSource.cpp",
"BufferingSettings.cpp",
@@ -268,6 +265,7 @@
},
header_libs: [
+ "bionic_libc_platform_headers",
"libstagefright_headers",
"media_ndk_headers",
],
@@ -333,8 +331,6 @@
cc_library_static {
name: "libmedia_player2_util",
- defaults: [ "libmedia_defaults" ],
-
srcs: [
"AudioParameter.cpp",
"BufferingSettings.cpp",
diff --git a/media/libmedia/MediaUtils.cpp b/media/libmedia/MediaUtils.cpp
index 31972fa..2efb30e 100644
--- a/media/libmedia/MediaUtils.cpp
+++ b/media/libmedia/MediaUtils.cpp
@@ -22,7 +22,7 @@
#include <sys/resource.h>
#include <unistd.h>
-#include <bionic_malloc.h>
+#include <bionic/malloc.h>
#include "MediaUtils.h"
diff --git a/media/libnbaio/Android.bp b/media/libnbaio/Android.bp
index a4df38d..04ddcff 100644
--- a/media/libnbaio/Android.bp
+++ b/media/libnbaio/Android.bp
@@ -1,4 +1,3 @@
-
cc_defaults {
name: "libnbaio_mono_defaults",
srcs: [
@@ -9,20 +8,27 @@
header_libs: [
"libaudioclient_headers",
"libaudio_system_headers",
- "libmedia_headers",
],
export_header_lib_headers: [
"libaudioclient_headers",
- "libmedia_headers",
],
shared_libs: [
"libaudioutils",
+ "libcutils",
"liblog",
"libutils",
],
+ export_shared_lib_headers: [
+ "libaudioutils",
+ ],
export_include_dirs: ["include_mono"],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
}
// libnbaio_mono is the part of libnbaio that is available for vendors to use. Vendor modules can't
@@ -53,20 +59,7 @@
// ],
// static_libs: ["libsndfile"],
- shared_libs: [
- "libaudioutils",
- "libbinder",
- "libcutils",
- "liblog",
- "libutils",
- ],
-
- cflags: [
- "-Werror",
- "-Wall",
- ],
-
- include_dirs: ["system/media/audio_utils/include"],
+ header_libs: ["libaudiohal_headers"],
export_include_dirs: ["include"],
}
diff --git a/media/libnbaio/include_mono/media/nbaio/MonoPipe.h b/media/libnbaio/include_mono/media/nbaio/MonoPipe.h
index c51d0fe..926d84a 100644
--- a/media/libnbaio/include_mono/media/nbaio/MonoPipe.h
+++ b/media/libnbaio/include_mono/media/nbaio/MonoPipe.h
@@ -19,7 +19,7 @@
#include <time.h>
#include <audio_utils/fifo.h>
-#include <media/SingleStateQueue.h>
+#include <media/nbaio/SingleStateQueue.h>
#include <media/nbaio/NBAIO.h>
namespace android {
diff --git a/media/libmedia/include/media/SingleStateQueue.h b/media/libnbaio/include_mono/media/nbaio/SingleStateQueue.h
similarity index 100%
rename from media/libmedia/include/media/SingleStateQueue.h
rename to media/libnbaio/include_mono/media/nbaio/SingleStateQueue.h
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 9170805..353044c8 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -220,7 +220,7 @@
],
header_libs:[
- "libnativeloader-dummy-headers",
+ "libnativeloader-headers",
"libstagefright_xmlparser_headers",
"media_ndk_headers",
],
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 3d58d4b..a267f7e 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -170,6 +170,7 @@
sp<IMediaCodecList> MediaCodecList::sRemoteList;
sp<MediaCodecList::BinderDeathObserver> MediaCodecList::sBinderDeathObserver;
+sp<IBinder> MediaCodecList::sMediaPlayer; // kept since linked to death
void MediaCodecList::BinderDeathObserver::binderDied(const wp<IBinder> &who __unused) {
Mutex::Autolock _l(sRemoteInitMutex);
@@ -181,15 +182,14 @@
sp<IMediaCodecList> MediaCodecList::getInstance() {
Mutex::Autolock _l(sRemoteInitMutex);
if (sRemoteList == nullptr) {
- sp<IBinder> binder =
- defaultServiceManager()->getService(String16("media.player"));
+ sMediaPlayer = defaultServiceManager()->getService(String16("media.player"));
sp<IMediaPlayerService> service =
- interface_cast<IMediaPlayerService>(binder);
+ interface_cast<IMediaPlayerService>(sMediaPlayer);
if (service.get() != nullptr) {
sRemoteList = service->getCodecList();
if (sRemoteList != nullptr) {
sBinderDeathObserver = new BinderDeathObserver();
- binder->linkToDeath(sBinderDeathObserver.get());
+ sMediaPlayer->linkToDeath(sBinderDeathObserver.get());
}
}
if (sRemoteList == nullptr) {
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/libstagefright/bqhelper/Android.bp
index db67034..6719bab 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/libstagefright/bqhelper/Android.bp
@@ -27,7 +27,6 @@
"libcutils",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
"liblog",
"libstagefright_foundation",
"libui",
@@ -39,7 +38,6 @@
"android.hidl.token@1.0-utils",
"libbase",
"libEGL",
- "libhwbinder",
"libnativewindow",
"libvndksupport",
],
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 1293a74..08e20cc 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -572,16 +572,17 @@
}
void SoftVorbis::onPortFlushCompleted(OMX_U32 portIndex) {
- if (portIndex == 0 && mState != NULL) {
- // Make sure that the next buffer output does not still
- // depend on fragments from the last one decoded.
-
+ if (portIndex == 0) {
mInputBufferCount = 0;
mNumFramesOutput = 0;
mSawInputEos = false;
mSignalledOutputEos = false;
mNumFramesLeftOnPage = -1;
- vorbis_dsp_restart(mState);
+ if (mState != NULL) {
+ // Make sure that the next buffer output does not still
+ // depend on fragments from the last one decoded.
+ vorbis_dsp_restart(mState);
+ }
}
}
@@ -603,6 +604,7 @@
mSawInputEos = false;
mSignalledOutputEos = false;
mSignalledError = false;
+ mNumFramesLeftOnPage = -1;
mOutputPortSettingsChange = NONE;
}
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 359df3d..cf91405 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -269,10 +269,21 @@
Rect bounds(mCropWidth, mCropHeight);
- void *dst;
- CHECK_EQ(0, mapper.lock(buf->handle,
- GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_RARELY,
- bounds, &dst));
+ void *dst = NULL;
+ struct android_ycbcr ycbcr;
+ if ( !mConverter &&
+ (mColorFormat == OMX_COLOR_FormatYUV420Planar ||
+ mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
+ mColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar ||
+ mColorFormat == OMX_COLOR_FormatYUV420Planar16)) {
+ CHECK_EQ(0, mapper.lockYCbCr(buf->handle,
+ GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_RARELY,
+ bounds, &ycbcr));
+ } else {
+ CHECK_EQ(0, mapper.lock(buf->handle,
+ GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_RARELY,
+ bounds, &dst));
+ }
// TODO move the other conversions also into ColorConverter, and
// fix cropping issues (when mCropLeft/Top != 0 or mWidth != mCropWidth)
@@ -289,12 +300,10 @@
const uint8_t *src_u = (const uint8_t *)data + mStride * mHeight + mCropTop * mStride / 4;
const uint8_t *src_v = (const uint8_t *)src_u + mStride * mHeight / 4;
- uint8_t *dst_y = (uint8_t *)dst;
- size_t dst_y_size = buf->stride * buf->height;
+ uint8_t *dst_y = (uint8_t *)ycbcr.y;
+ uint8_t *dst_v = (uint8_t *)ycbcr.cr;
+ uint8_t *dst_u = (uint8_t *)ycbcr.cb;
size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
- size_t dst_c_size = dst_c_stride * buf->height / 2;
- uint8_t *dst_v = dst_y + dst_y_size;
- uint8_t *dst_u = dst_v + dst_c_size;
dst_y += mCropTop * buf->stride + mCropLeft;
dst_v += (mCropTop/2) * dst_c_stride + mCropLeft/2;
@@ -321,12 +330,10 @@
const uint8_t *src_u = (const uint8_t *)data + mStride * mHeight + mCropTop * mStride / 4;
const uint8_t *src_v = (const uint8_t *)src_u + mStride * mHeight / 4;
- uint8_t *dst_y = (uint8_t *)dst;
- size_t dst_y_size = buf->stride * buf->height;
+ uint8_t *dst_y = (uint8_t *)ycbcr.y;
+ uint8_t *dst_v = (uint8_t *)ycbcr.cr;
+ uint8_t *dst_u = (uint8_t *)ycbcr.cb;
size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
- size_t dst_c_size = dst_c_stride * buf->height / 2;
- uint8_t *dst_v = dst_y + dst_y_size;
- uint8_t *dst_u = dst_v + dst_c_size;
dst_y += mCropTop * buf->stride + mCropLeft;
dst_v += (mCropTop / 2) * dst_c_stride + mCropLeft / 2;
@@ -361,13 +368,10 @@
src_y += mCropLeft + mCropTop * mWidth;
src_uv += (mCropLeft + mCropTop * mWidth) / 2;
- uint8_t *dst_y = (uint8_t *)dst;
-
- size_t dst_y_size = buf->stride * buf->height;
+ uint8_t *dst_y = (uint8_t *)ycbcr.y;
+ uint8_t *dst_v = (uint8_t *)ycbcr.cr;
+ uint8_t *dst_u = (uint8_t *)ycbcr.cb;
size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
- size_t dst_c_size = dst_c_stride * buf->height / 2;
- uint8_t *dst_v = dst_y + dst_y_size;
- uint8_t *dst_u = dst_v + dst_c_size;
dst_y += mCropTop * buf->stride + mCropLeft;
dst_v += (mCropTop/2) * dst_c_stride + mCropLeft/2;
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
index 7a67e55..b1f62c7 100644
--- a/media/libstagefright/filters/Android.bp
+++ b/media/libstagefright/filters/Android.bp
@@ -8,7 +8,7 @@
"MediaFilter.cpp",
"RSFilter.cpp",
"SaturationFilter.cpp",
- "saturationARGB.rs",
+ "saturationARGB.rscript",
"SimpleFilter.cpp",
"ZeroFilter.cpp",
],
diff --git a/media/libstagefright/filters/saturation.rs b/media/libstagefright/filters/saturation.rscript
similarity index 100%
rename from media/libstagefright/filters/saturation.rs
rename to media/libstagefright/filters/saturation.rscript
diff --git a/media/libstagefright/filters/saturationARGB.rs b/media/libstagefright/filters/saturationARGB.rscript
similarity index 100%
rename from media/libstagefright/filters/saturationARGB.rs
rename to media/libstagefright/filters/saturationARGB.rscript
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
index fb51cc5..a8adff5 100644
--- a/media/libstagefright/foundation/AString.cpp
+++ b/media/libstagefright/foundation/AString.cpp
@@ -365,8 +365,6 @@
// static
AString AString::FromParcel(const Parcel &parcel) {
size_t size = static_cast<size_t>(parcel.readInt32());
- // The static analyzer incorrectly reports a false-positive here in c++17.
- // https://bugs.llvm.org/show_bug.cgi?id=38176 . NOLINTNEXTLINE
return AString(static_cast<const char *>(parcel.readInplace(size)), size);
}
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecList.h b/media/libstagefright/include/media/stagefright/MediaCodecList.h
index e44b0a4..e681d25 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecList.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecList.h
@@ -83,6 +83,7 @@
};
static sp<BinderDeathObserver> sBinderDeathObserver;
+ static sp<IBinder> sMediaPlayer;
static sp<IMediaCodecList> sCodecList;
static sp<IMediaCodecList> sRemoteList;
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index 7d03d98..7d612b4 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -45,7 +45,6 @@
"libdl",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
"libvndksupport",
"android.hardware.media.omx@1.0",
"android.hardware.graphics.bufferqueue@1.0",
diff --git a/media/mtp/PosixAsyncIO.cpp b/media/mtp/PosixAsyncIO.cpp
index 72c07cc..8205e3b 100644
--- a/media/mtp/PosixAsyncIO.cpp
+++ b/media/mtp/PosixAsyncIO.cpp
@@ -47,10 +47,10 @@
CHECK(aiocbp->queued);
int ret;
if (aiocbp->read) {
- ret = TEMP_FAILURE_RETRY(pread(aiocbp->aio_fildes,
+ ret = TEMP_FAILURE_RETRY(pread64(aiocbp->aio_fildes,
aiocbp->aio_buf, aiocbp->aio_nbytes, aiocbp->aio_offset));
} else {
- ret = TEMP_FAILURE_RETRY(pwrite(aiocbp->aio_fildes,
+ ret = TEMP_FAILURE_RETRY(pwrite64(aiocbp->aio_fildes,
aiocbp->aio_buf, aiocbp->aio_nbytes, aiocbp->aio_offset));
}
{
@@ -139,7 +139,7 @@
return 0;
}
-void aio_prepare(struct aiocb *aiocbp, void* buf, size_t count, off_t offset) {
+void aio_prepare(struct aiocb *aiocbp, void* buf, size_t count, off64_t offset) {
aiocbp->aio_buf = buf;
aiocbp->aio_offset = offset;
aiocbp->aio_nbytes = count;
diff --git a/media/mtp/PosixAsyncIO.h b/media/mtp/PosixAsyncIO.h
index 2bb5735..2bcae4c 100644
--- a/media/mtp/PosixAsyncIO.h
+++ b/media/mtp/PosixAsyncIO.h
@@ -32,7 +32,7 @@
int aio_fildes;
void *aio_buf;
- off_t aio_offset;
+ off64_t aio_offset;
size_t aio_nbytes;
// Used internally
@@ -61,7 +61,7 @@
ssize_t aio_return(struct aiocb *);
// Helper method for setting aiocb members
-void aio_prepare(struct aiocb *, void*, size_t, off_t);
+void aio_prepare(struct aiocb *, void*, size_t, off64_t);
#endif // POSIXASYNCIO_H
diff --git a/media/tests/benchmark/.clang-format b/media/tests/benchmark/.clang-format
new file mode 100644
index 0000000..bf1e355
--- /dev/null
+++ b/media/tests/benchmark/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+Standard: Cpp11
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IncludeBlocks: Preserve
+IndentWidth: 4
+ContinuationIndentWidth: 8
+PointerAlignment: Right
+TabWidth: 4
+UseTab: Never
diff --git a/media/tests/benchmark/Android.bp b/media/tests/benchmark/Android.bp
new file mode 100644
index 0000000..8a7a59f
--- /dev/null
+++ b/media/tests/benchmark/Android.bp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+subdirs = [
+ "src",
+ "tests",
+]
\ No newline at end of file
diff --git a/media/tests/benchmark/README.md b/media/tests/benchmark/README.md
new file mode 100644
index 0000000..8db3fd3
--- /dev/null
+++ b/media/tests/benchmark/README.md
@@ -0,0 +1,60 @@
+# Benchmark tests
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/tests/benchmark/
+```
+
+The binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+adb push $(OUT)/data/nativetest64/* /data/local/tmp/
+
+Eg. adb push $(OUT)/data/nativetest64/extractorTest/extractorTest /data/local/tmp/
+
+To run the binary, follow the commands mentioned below under each module.
+
+The resource files for the tests are taken from [here](https://drive.google.com/open?id=1ghMr17BBJ7n0pqbm7oREiTN_MNemJUqy)
+
+## Extractor
+
+The test extracts elementary stream and benchmarks the extractors available in NDK.
+
+Push the resource files to /sdcard/res on the device.
+
+You can use a different location, but you have to modify the rest of the instructions to replace /sdcard/res with wherever you chose to put the files.
+
+The path to these files on the device is required to be given for the test.
+
+```
+adb shell /data/local/tmp/extractorTest -P /sdcard/res/
+```
+
+## Decoder
+
+The test decodes input stream and benchmarks the decoders available in NDK.
+
+Setup steps are same as extractor.
+
+```
+adb shell /data/local/tmp/decoderTest -P /sdcard/res/
+```
+
+## Muxer
+
+The test muxes elementary stream and benchmarks the muxers available in NDK.
+
+Setup steps are same as extractor.
+
+```
+adb shell /data/local/tmp/muxerTest -P /sdcard/res/
+```
+
+## Encoder
+
+The test encodes input stream and benchmarks the encoders available in NDK.
+
+Setup steps are same as extractor.
+
+```
+adb shell /data/local/tmp/encoderTest -P /sdcard/res/
+```
diff --git a/media/tests/benchmark/src/native/common/Android.bp b/media/tests/benchmark/src/native/common/Android.bp
new file mode 100644
index 0000000..64ea1ee
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/Android.bp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_library_static {
+ name: "libbenchmark_common",
+ defaults: [
+ "libbenchmark-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: [
+ "BenchmarkCommon.cpp",
+ "Timer.cpp",
+ ],
+
+ export_include_dirs: ["."],
+
+ ldflags: ["-Wl,-Bsymbolic"]
+}
+
+cc_defaults {
+ name: "libbenchmark_common-defaults",
+
+ defaults: [
+ "libbenchmark-defaults",
+ ],
+
+ static_libs: [
+ "libbenchmark_common",
+ ],
+}
+
+cc_defaults {
+ name: "libbenchmark-defaults",
+
+ header_libs: [
+ "media_ndk_headers",
+ ],
+
+ shared_libs: [
+ "libmediandk",
+ "liblog",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ]
+}
+
+// public dependency for native implementation
+// to be used by code under media/benchmark/* only
+cc_defaults {
+ name: "libbenchmark_soft_sanitize_all-defaults",
+
+ sanitize: {
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ address: true,
+ }
+}
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp b/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
new file mode 100644
index 0000000..bbc8790
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2019 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 "BenchmarkCommon"
+
+#include "BenchmarkCommon.h"
+#include <iostream>
+
+void CallBackHandle::ioThread() {
+ ALOGV("In %s mIsDone : %d, mSawError : %d ", __func__, mIsDone, mSawError);
+ while (!mIsDone && !mSawError) {
+ auto task = mIOQueue.pop();
+ task();
+ }
+}
+
+void OnInputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index) {
+ ALOGV("OnInputAvailableCB: index(%d)", index);
+ CallBackHandle *self = (CallBackHandle *)userdata;
+ self->getTimer()->addInputTime();
+ self->mIOQueue.push([self, codec, index]() { self->onInputAvailable(codec, index); });
+}
+
+void OnOutputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index,
+ AMediaCodecBufferInfo *bufferInfo) {
+ ALOGV("OnOutputAvailableCB: index(%d), (%d, %d, %lld, 0x%x)", index, bufferInfo->offset,
+ bufferInfo->size, (long long)bufferInfo->presentationTimeUs, bufferInfo->flags);
+ CallBackHandle *self = (CallBackHandle *)userdata;
+ self->getTimer()->addOutputTime();
+ AMediaCodecBufferInfo bufferInfoCopy = *bufferInfo;
+ self->mIOQueue.push([self, codec, index, bufferInfoCopy]() {
+ AMediaCodecBufferInfo bc = bufferInfoCopy;
+ self->onOutputAvailable(codec, index, &bc);
+ });
+}
+
+void OnFormatChangedCB(AMediaCodec *codec, void *userdata, AMediaFormat *format) {
+ ALOGV("OnFormatChangedCB: format(%s)", AMediaFormat_toString(format));
+ CallBackHandle *self = (CallBackHandle *)userdata;
+ self->mIOQueue.push([self, codec, format]() { self->onFormatChanged(codec, format); });
+}
+
+void OnErrorCB(AMediaCodec *codec, void *userdata, media_status_t err, int32_t actionCode,
+ const char *detail) {
+ (void)codec;
+ ALOGV("OnErrorCB: err(%d), actionCode(%d), detail(%s)", err, actionCode, detail);
+ CallBackHandle *self = (CallBackHandle *)userdata;
+ self->mSawError = true;
+}
+
+AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string codecName,
+ bool isEncoder) {
+ ALOGV("In %s", __func__);
+ if (!mime) {
+ ALOGE("Please specify a mime type to create codec");
+ return nullptr;
+ }
+
+ AMediaCodec *codec;
+ if (!codecName.empty()) {
+ codec = AMediaCodec_createCodecByName(codecName.c_str());
+ if (!codec) {
+ ALOGE("Unable to create codec by name: %s", codecName.c_str());
+ return nullptr;
+ }
+ } else {
+ if (isEncoder) {
+ codec = AMediaCodec_createEncoderByType(mime);
+ } else {
+ codec = AMediaCodec_createDecoderByType(mime);
+ }
+ if (!codec) {
+ ALOGE("Unable to create codec by mime: %s", mime);
+ return nullptr;
+ }
+ }
+
+ /* Configure codec with the given format*/
+ const char *s = AMediaFormat_toString(format);
+ ALOGV("Input format: %s\n", s);
+
+ media_status_t status = AMediaCodec_configure(codec, format, nullptr, nullptr, isEncoder);
+ if (status != AMEDIA_OK) {
+ ALOGE("AMediaCodec_configure failed %d", status);
+ return nullptr;
+ }
+ return codec;
+}
\ No newline at end of file
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.h b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
new file mode 100644
index 0000000..7b87c04
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2019 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 __BENCHMARK_COMMON_H__
+#define __BENCHMARK_COMMON_H__
+
+#include <utils/Log.h>
+
+#include <inttypes.h>
+#include <mutex>
+#include <queue>
+#include <thread>
+
+#include <media/NdkMediaCodec.h>
+#include <media/NdkMediaError.h>
+
+#include "Timer.h"
+
+using namespace std;
+
+constexpr uint32_t kQueueDequeueTimeoutUs = 1000;
+constexpr uint32_t kMaxCSDStrlen = 16;
+constexpr uint32_t kMaxBufferSize = 1024 * 1024 * 16;
+
+template <typename T>
+class CallBackQueue {
+ public:
+ CallBackQueue() {}
+ ~CallBackQueue() {}
+
+ void push(T elem) {
+ bool needsNotify = false;
+ {
+ lock_guard<mutex> lock(mMutex);
+ needsNotify = mQueue.empty();
+ mQueue.push(move(elem));
+ }
+ if (needsNotify) mQueueNotEmptyCondition.notify_one();
+ }
+
+ T pop() {
+ unique_lock<mutex> lock(mMutex);
+ if (mQueue.empty()) {
+ mQueueNotEmptyCondition.wait(lock, [this]() { return !mQueue.empty(); });
+ }
+ auto result = mQueue.front();
+ mQueue.pop();
+ return result;
+ }
+
+ private:
+ mutex mMutex;
+ queue<T> mQueue;
+ condition_variable mQueueNotEmptyCondition;
+};
+
+class CallBackHandle {
+ public:
+ CallBackHandle() : mSawError(false), mIsDone(false), mTimer(nullptr) {}
+
+ virtual ~CallBackHandle() {
+ if (mIOThread.joinable()) mIOThread.join();
+ if (mTimer) delete mTimer;
+ }
+
+ void ioThread();
+
+ // Implementation in child class (Decoder/Encoder)
+ virtual void onInputAvailable(AMediaCodec *codec, int32_t index) {
+ (void)codec;
+ (void)index;
+ }
+ virtual void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) {
+ (void)codec;
+ (void)format;
+ }
+ virtual void onOutputAvailable(AMediaCodec *codec, int32_t index,
+ AMediaCodecBufferInfo *bufferInfo) {
+ (void)codec;
+ (void)index;
+ (void)bufferInfo;
+ }
+
+ virtual Timer *getTimer() { return mTimer; }
+
+ // Keep a queue of all function callbacks.
+ typedef function<void()> IOTask;
+ CallBackQueue<IOTask> mIOQueue;
+ thread mIOThread;
+ bool mSawError;
+ bool mIsDone;
+
+ private:
+ Timer *mTimer;
+};
+
+// Async API's callback
+void OnInputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index);
+
+void OnOutputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index,
+ AMediaCodecBufferInfo *bufferInfo);
+
+void OnFormatChangedCB(AMediaCodec *codec, void *userdata, AMediaFormat *format);
+
+void OnErrorCB(AMediaCodec *codec, void * /* userdata */, media_status_t err, int32_t actionCode,
+ const char *detail);
+
+// Utility to create and configure AMediaCodec
+AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string codecName,
+ bool isEncoder);
+
+#endif // __BENCHMARK_COMMON_H__
diff --git a/media/tests/benchmark/src/native/common/Timer.cpp b/media/tests/benchmark/src/native/common/Timer.cpp
new file mode 100644
index 0000000..0487123
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/Timer.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 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 "Timer"
+
+#include <iostream>
+#include <stdint.h>
+#include <utils/Log.h>
+
+#include "Timer.h"
+
+/**
+ * Dumps the stats of the operation for a given input media.
+ *
+ * \param operation describes the operation performed on the input media
+ * (i.e. extract/mux/decode/encode)
+ * \param inputReference input media
+ * \param duarationUs is a duration of the input media in microseconds.
+ */
+void Timer::dumpStatistics(std::string operation, std::string inputReference, int64_t duarationUs) {
+ ALOGV("In %s", __func__);
+ if (!mOutputTimer.size()) {
+ ALOGE("No output produced");
+ return;
+ }
+ nsecs_t totalTimeTakenNs = getTotalTime();
+ nsecs_t timeTakenPerSec = (totalTimeTakenNs * 1000000) / duarationUs;
+ nsecs_t timeToFirstFrameNs = *mOutputTimer.begin() - mStartTimeNs;
+ // get min and max output intervals.
+ nsecs_t intervalNs;
+ nsecs_t minTimeTakenNs = INT64_MAX;
+ nsecs_t maxTimeTakenNs = 0;
+ nsecs_t prevIntervalNs = mStartTimeNs;
+ for (int32_t idx = 0; idx < mOutputTimer.size() - 1; idx++) {
+ intervalNs = mOutputTimer.at(idx) - prevIntervalNs;
+ prevIntervalNs = mOutputTimer.at(idx);
+ if (minTimeTakenNs > intervalNs) minTimeTakenNs = intervalNs;
+ else if (maxTimeTakenNs < intervalNs) maxTimeTakenNs = intervalNs;
+ }
+
+ // Print the Stats
+ std::cout << "Input Reference : " << inputReference << endl;
+ std::cout << "Setup Time in nano sec : " << mInitTimeNs << endl;
+ std::cout << "Average Time in nano sec : " << totalTimeTakenNs / mOutputTimer.size() << endl;
+ std::cout << "Time to first frame in nano sec : " << timeToFirstFrameNs << endl;
+ std::cout << "Time taken (in nano sec) to " << operation
+ << " 1 sec of content : " << timeTakenPerSec << endl;
+ std::cout << "Minimum Time in nano sec : " << minTimeTakenNs << endl;
+ std::cout << "Maximum Time in nano sec : " << maxTimeTakenNs << endl;
+ std::cout << "Destroy Time in nano sec : " << mDeInitTimeNs << endl;
+}
diff --git a/media/tests/benchmark/src/native/common/Timer.h b/media/tests/benchmark/src/native/common/Timer.h
new file mode 100644
index 0000000..92af86f
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/Timer.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 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 __TIMER_H__
+#define __TIMER_H__
+
+#include <sys/time.h>
+#include <algorithm>
+#include <numeric>
+#include <vector>
+#include <utils/Timers.h>
+
+using namespace std;
+
+class Timer {
+ public:
+ Timer() {
+ mInitTimeNs = 0;
+ mDeInitTimeNs = 0;
+ }
+
+ ~Timer() {
+ if (!mInputTimer.empty()) mInputTimer.clear();
+ if (!mOutputTimer.empty()) mOutputTimer.clear();
+ }
+
+ private:
+ nsecs_t mInitTimeNs;
+ nsecs_t mDeInitTimeNs;
+ nsecs_t mStartTimeNs;
+ std::vector<nsecs_t> mInputTimer;
+ std::vector<nsecs_t> mOutputTimer;
+
+ public:
+ nsecs_t getCurTime() { return systemTime(CLOCK_MONOTONIC); }
+
+ void setInitTime(nsecs_t initTime) { mInitTimeNs = initTime; }
+
+ void setDeInitTime(nsecs_t deInitTime) { mDeInitTimeNs = deInitTime; }
+
+ void setStartTime() { mStartTimeNs = systemTime(CLOCK_MONOTONIC); }
+
+ void addInputTime() { mInputTimer.push_back(systemTime(CLOCK_MONOTONIC)); }
+
+ void addOutputTime() { mOutputTimer.push_back(systemTime(CLOCK_MONOTONIC)); }
+
+ void resetTimers() {
+ if (!mInputTimer.empty()) mInputTimer.clear();
+ if (!mOutputTimer.empty()) mOutputTimer.clear();
+ }
+
+ std::vector<nsecs_t> getOutputTimer() { return mOutputTimer; }
+
+ nsecs_t getInitTime() { return mInitTimeNs; }
+
+ nsecs_t getDeInitTime() { return mDeInitTimeNs; }
+
+ nsecs_t getTimeDiff(nsecs_t sTime, nsecs_t eTime) { return (eTime - sTime); }
+
+ nsecs_t getTotalTime() {
+ if (mOutputTimer.empty()) return -1;
+ return (*(mOutputTimer.end() - 1) - mStartTimeNs);
+ }
+
+ void dumpStatistics(std::string operation, std::string inputReference, int64_t duarationUs);
+};
+
+#endif // __TIMER_H__
diff --git a/media/tests/benchmark/src/native/decoder/Android.bp b/media/tests/benchmark/src/native/decoder/Android.bp
new file mode 100644
index 0000000..f2d3db5
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/Android.bp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_library_static {
+ name: "libbenchmark_decoder",
+ defaults: [
+ "libbenchmark_common-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["Decoder.cpp"],
+
+ static_libs: ["libbenchmark_extractor"],
+
+ export_include_dirs: ["."],
+
+ ldflags: ["-Wl,-Bsymbolic"]
+}
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.cpp b/media/tests/benchmark/src/native/decoder/Decoder.cpp
new file mode 100644
index 0000000..eeea60f
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/Decoder.cpp
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2019 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 "decoder"
+
+#include <iostream>
+
+#include "Decoder.h"
+
+tuple<ssize_t, uint32_t, int64_t> readSampleData(uint8_t *inputBuffer, int32_t &offset,
+ vector<AMediaCodecBufferInfo> &frameInfo,
+ uint8_t *buf, int32_t frameID, size_t bufSize) {
+ ALOGV("In %s", __func__);
+ if (frameID == (int32_t)frameInfo.size()) {
+ return make_tuple(0, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM, 0);
+ }
+ uint32_t flags = frameInfo[frameID].flags;
+ int64_t timestamp = frameInfo[frameID].presentationTimeUs;
+ ssize_t bytesCount = frameInfo[frameID].size;
+ if (bufSize < bytesCount) {
+ ALOGE("Error : insufficient resource");
+ return make_tuple(0, AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE, 0);
+ }
+
+ memcpy(buf, inputBuffer + offset, bytesCount);
+ offset += bytesCount;
+ return make_tuple(bytesCount, flags, timestamp);
+}
+
+void Decoder::onInputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx) {
+ ALOGV("In %s", __func__);
+ if (mediaCodec == mCodec && mediaCodec) {
+ if (mSawInputEOS || bufIdx < 0) return;
+ if (mSignalledError) {
+ CallBackHandle::mSawError = true;
+ mDecoderDoneCondition.notify_one();
+ return;
+ }
+
+ size_t bufSize;
+ uint8_t *buf = AMediaCodec_getInputBuffer(mCodec, bufIdx, &bufSize);
+ if (!buf) {
+ mSignalledError = true;
+ mDecoderDoneCondition.notify_one();
+ return;
+ }
+
+ ssize_t bytesRead = 0;
+ uint32_t flag = 0;
+ int64_t presentationTimeUs = 0;
+ tie(bytesRead, flag, presentationTimeUs) = readSampleData(
+ mInputBuffer, mOffset, mFrameMetaData, buf, mNumInputFrame, bufSize);
+ if (flag == AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE) {
+ mSignalledError = true;
+ mDecoderDoneCondition.notify_one();
+ return;
+ }
+
+ if (flag == AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) mSawInputEOS = true;
+ ALOGV("%s bytesRead : %zd presentationTimeUs : %" PRId64 " mSawInputEOS : %s", __FUNCTION__,
+ bytesRead, presentationTimeUs, mSawInputEOS ? "TRUE" : "FALSE");
+
+ int status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */, bytesRead,
+ presentationTimeUs, flag);
+ if (AMEDIA_OK != status) {
+ mSignalledError = true;
+ mDecoderDoneCondition.notify_one();
+ return;
+ }
+ mNumInputFrame++;
+ }
+}
+
+void Decoder::onOutputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx,
+ AMediaCodecBufferInfo *bufferInfo) {
+ ALOGV("In %s", __func__);
+ if (mediaCodec == mCodec && mediaCodec) {
+ if (mSawOutputEOS || bufIdx < 0) return;
+ if (mSignalledError) {
+ CallBackHandle::mSawError = true;
+ mDecoderDoneCondition.notify_one();
+ return;
+ }
+
+ if (mOutFp != nullptr) {
+ size_t bufSize;
+ uint8_t *buf = AMediaCodec_getOutputBuffer(mCodec, bufIdx, &bufSize);
+ if (buf) {
+ fwrite(buf, sizeof(char), bufferInfo->size, mOutFp);
+ ALOGV("bytes written into file %d\n", bufferInfo->size);
+ }
+ }
+
+ AMediaCodec_releaseOutputBuffer(mCodec, bufIdx, false);
+ mSawOutputEOS = (0 != (bufferInfo->flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM));
+ mNumOutputFrame++;
+ ALOGV("%s index : %d mSawOutputEOS : %s count : %u", __FUNCTION__, bufIdx,
+ mSawOutputEOS ? "TRUE" : "FALSE", mNumOutputFrame);
+
+ if (mSawOutputEOS) {
+ CallBackHandle::mIsDone = true;
+ mDecoderDoneCondition.notify_one();
+ }
+ }
+}
+
+void Decoder::onFormatChanged(AMediaCodec *mediaCodec, AMediaFormat *format) {
+ ALOGV("In %s", __func__);
+ if (mediaCodec == mCodec && mediaCodec) {
+ ALOGV("%s { %s }", __FUNCTION__, AMediaFormat_toString(format));
+ mFormat = format;
+ }
+}
+
+void Decoder::setupDecoder() {
+ if (!mFormat) mFormat = mExtractor->getFormat();
+ if (!mTimer) mTimer = new Timer();
+}
+
+int32_t Decoder::decode(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo,
+ string &codecName, bool asyncMode, FILE *outFp) {
+ ALOGV("In %s", __func__);
+ mInputBuffer = inputBuffer;
+ mFrameMetaData = frameInfo;
+ mOffset = 0;
+ mOutFp = outFp;
+
+ const char *mime = nullptr;
+ AMediaFormat_getString(mFormat, AMEDIAFORMAT_KEY_MIME, &mime);
+ if (!mime) return AMEDIA_ERROR_INVALID_OBJECT;
+
+ int64_t sTime = mTimer->getCurTime();
+ mCodec = createMediaCodec(mFormat, mime, codecName, false /*isEncoder*/);
+ if (!mCodec) return AMEDIA_ERROR_INVALID_OBJECT;
+
+ if (asyncMode) {
+ AMediaCodecOnAsyncNotifyCallback aCB = {OnInputAvailableCB, OnOutputAvailableCB,
+ OnFormatChangedCB, OnErrorCB};
+ AMediaCodec_setAsyncNotifyCallback(mCodec, aCB, this);
+
+ CallBackHandle *callbackHandle = new CallBackHandle();
+ callbackHandle->mIOThread = thread(&CallBackHandle::ioThread, this);
+ }
+
+ AMediaCodec_start(mCodec);
+ int64_t eTime = mTimer->getCurTime();
+ int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
+ mTimer->setInitTime(timeTaken);
+
+ mTimer->setStartTime();
+ if (!asyncMode) {
+ while (!mSawOutputEOS && !mSignalledError) {
+ /* Queue input data */
+ if (!mSawInputEOS) {
+ ssize_t inIdx = AMediaCodec_dequeueInputBuffer(mCodec, kQueueDequeueTimeoutUs);
+ if (inIdx < 0 && inIdx != AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
+ ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
+ return AMEDIA_ERROR_IO;
+ } else if (inIdx >= 0) {
+ mTimer->addInputTime();
+ onInputAvailable(mCodec, inIdx);
+ }
+ }
+
+ /* Dequeue output data */
+ AMediaCodecBufferInfo info;
+ ssize_t outIdx = AMediaCodec_dequeueOutputBuffer(mCodec, &info, kQueueDequeueTimeoutUs);
+ if (outIdx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
+ mFormat = AMediaCodec_getOutputFormat(mCodec);
+ const char *s = AMediaFormat_toString(mFormat);
+ ALOGI("Output format: %s\n", s);
+ } else if (outIdx >= 0) {
+ mTimer->addOutputTime();
+ onOutputAvailable(mCodec, outIdx, &info);
+ } else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
+ outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
+ ALOGE("AMediaCodec_dequeueOutputBuffer returned invalid index %zd\n", outIdx);
+ return AMEDIA_ERROR_IO;
+ }
+ }
+ } else {
+ unique_lock<mutex> lock(mMutex);
+ mDecoderDoneCondition.wait(lock, [this]() { return (mSawOutputEOS || mSignalledError); });
+ }
+
+ if (codecName.empty()) {
+ char *decName;
+ AMediaCodec_getName(mCodec, &decName);
+ codecName.assign(decName);
+ AMediaCodec_releaseName(mCodec, decName);
+ }
+ return AMEDIA_OK;
+}
+
+void Decoder::deInitCodec() {
+ int64_t sTime = mTimer->getCurTime();
+ if (mFormat) {
+ AMediaFormat_delete(mFormat);
+ mFormat = nullptr;
+ }
+ if (!mCodec) return;
+ AMediaCodec_stop(mCodec);
+ AMediaCodec_delete(mCodec);
+ int64_t eTime = mTimer->getCurTime();
+ int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
+ mTimer->setDeInitTime(timeTaken);
+}
+
+void Decoder::dumpStatistics(string inputReference) {
+ int64_t durationUs = mExtractor->getClipDuration();
+ string operation = "decode";
+ mTimer->dumpStatistics(operation, inputReference, durationUs);
+}
+
+void Decoder::resetDecoder() {
+ if (mTimer) mTimer->resetTimers();
+ if (mInputBuffer) mInputBuffer = nullptr;
+ if (!mFrameMetaData.empty()) mFrameMetaData.clear();
+}
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.h b/media/tests/benchmark/src/native/decoder/Decoder.h
new file mode 100644
index 0000000..7f64de3
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/Decoder.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2019 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 __DECODER_H__
+#define __DECODER_H__
+
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <thread>
+
+#include "BenchmarkCommon.h"
+#include "Extractor.h"
+#include "Timer.h"
+
+class Decoder : public CallBackHandle {
+ public:
+ Decoder()
+ : mCodec(nullptr),
+ mFormat(nullptr),
+ mExtractor(nullptr),
+ mTimer(nullptr),
+ mNumInputFrame(0),
+ mNumOutputFrame(0),
+ mSawInputEOS(false),
+ mSawOutputEOS(false),
+ mSignalledError(false),
+ mInputBuffer(nullptr),
+ mOutFp(nullptr) {
+ mExtractor = new Extractor();
+ }
+
+ virtual ~Decoder() {
+ if (mTimer) delete mTimer;
+ if (mExtractor) delete mExtractor;
+ }
+
+ Timer *getTimer() override { return mTimer; }
+
+ Extractor *getExtractor() { return mExtractor; }
+
+ // Decoder related utilities
+ void setupDecoder();
+
+ void deInitCodec();
+
+ void resetDecoder();
+
+ // Async callback APIs
+ void onInputAvailable(AMediaCodec *codec, int32_t index) override;
+
+ void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) override;
+
+ void onOutputAvailable(AMediaCodec *codec, int32_t index,
+ AMediaCodecBufferInfo *bufferInfo) override;
+
+ // Process the frames and give decoded output
+ int32_t decode(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo,
+ string &codecName, bool asyncMode, FILE *outFp = nullptr);
+
+ void dumpStatistics(string inputReference);
+
+ private:
+ AMediaCodec *mCodec;
+ AMediaFormat *mFormat;
+
+ Extractor *mExtractor;
+
+ Timer *mTimer;
+
+ int32_t mNumInputFrame;
+ int32_t mNumOutputFrame;
+
+ bool mSawInputEOS;
+ bool mSawOutputEOS;
+ bool mSignalledError;
+
+ int32_t mOffset;
+ uint8_t *mInputBuffer;
+ vector<AMediaCodecBufferInfo> mFrameMetaData;
+ FILE *mOutFp;
+
+ /* Asynchronous locks */
+ mutex mMutex;
+ condition_variable mDecoderDoneCondition;
+};
+
+// Read input samples
+tuple<ssize_t, uint32_t, int64_t> readSampleData(uint8_t *inputBuffer, int32_t &offset,
+ vector<AMediaCodecBufferInfo> &frameSizes,
+ uint8_t *buf, int32_t frameID, size_t bufSize);
+
+#endif // __DECODER_H__
diff --git a/media/tests/benchmark/src/native/encoder/Android.bp b/media/tests/benchmark/src/native/encoder/Android.bp
new file mode 100644
index 0000000..c14c319
--- /dev/null
+++ b/media/tests/benchmark/src/native/encoder/Android.bp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_library_static {
+ name: "libbenchmark_encoder",
+ defaults: [
+ "libbenchmark_common-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["Encoder.cpp"],
+
+ static_libs: ["libbenchmark_extractor",
+ "libbenchmark_decoder",
+ ],
+
+ export_include_dirs: ["."],
+
+ ldflags: ["-Wl,-Bsymbolic"]
+}
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.cpp b/media/tests/benchmark/src/native/encoder/Encoder.cpp
new file mode 100644
index 0000000..73a559a
--- /dev/null
+++ b/media/tests/benchmark/src/native/encoder/Encoder.cpp
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2019 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 "encoder"
+
+#include <fstream>
+
+#include "Encoder.h"
+
+void Encoder::onInputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx) {
+ ALOGV("In %s", __func__);
+ if (mediaCodec == mCodec && mediaCodec) {
+ if (mSawInputEOS || bufIdx < 0) return;
+ if (mSignalledError) {
+ CallBackHandle::mSawError = true;
+ mEncoderDoneCondition.notify_one();
+ return;
+ }
+
+ size_t bufSize = 0;
+ char *buf = (char *)AMediaCodec_getInputBuffer(mCodec, bufIdx, &bufSize);
+ if (!buf) {
+ mSignalledError = true;
+ mEncoderDoneCondition.notify_one();
+ return;
+ }
+
+ if (mInputBufferSize < mOffset) {
+ ALOGE("Out of bound access of input buffer\n");
+ mSignalledError = true;
+ mEncoderDoneCondition.notify_one();
+ return;
+ }
+ size_t bytesRead = mParams.frameSize;
+ if (mInputBufferSize - mOffset < mParams.frameSize) {
+ bytesRead = mInputBufferSize - mOffset;
+ }
+ if (bufSize < bytesRead) {
+ ALOGE("bytes to read %zu bufSize %zu \n", bytesRead, bufSize);
+ mSignalledError = true;
+ mEncoderDoneCondition.notify_one();
+ return;
+ }
+ if (bytesRead < mParams.frameSize && mNumInputFrame < mParams.numFrames - 1) {
+ ALOGE("Partial frame at frameID %d bytesRead %zu frameSize %d total numFrames %d\n",
+ mNumInputFrame, bytesRead, mParams.frameSize, mParams.numFrames);
+ mSignalledError = true;
+ mEncoderDoneCondition.notify_one();
+ return;
+ }
+ mEleStream->read(buf, bytesRead);
+ size_t bytesgcount = mEleStream->gcount();
+ if (bytesgcount != bytesRead) {
+ ALOGE("bytes to read %zu actual bytes read %zu \n", bytesRead, bytesgcount);
+ mSignalledError = true;
+ mEncoderDoneCondition.notify_one();
+ return;
+ }
+
+ uint32_t flag = 0;
+ if (mNumInputFrame == mParams.numFrames - 1 || bytesRead == 0) {
+ ALOGD("Sending EOS on input Last frame\n");
+ flag |= AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
+ }
+
+ uint64_t presentationTimeUs;
+ if (!strncmp(mMime, "video/", 6)) {
+ presentationTimeUs = mNumInputFrame * (1000000 / mParams.frameRate);
+ } else {
+ presentationTimeUs =
+ (uint64_t)mNumInputFrame * mParams.frameSize * 1000000 / mParams.sampleRate;
+ }
+
+ if (flag == AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) mSawInputEOS = true;
+ ALOGV("%s bytesRead : %zd presentationTimeUs : %" PRIu64 " mSawInputEOS : %s", __FUNCTION__,
+ bytesRead, presentationTimeUs, mSawInputEOS ? "TRUE" : "FALSE");
+
+ int status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */, bytesRead,
+ presentationTimeUs, flag);
+ if (AMEDIA_OK != status) {
+ mSignalledError = true;
+ mEncoderDoneCondition.notify_one();
+ return;
+ }
+ mNumInputFrame++;
+ mOffset += bytesRead;
+ }
+}
+
+void Encoder::onOutputAvailable(AMediaCodec *mediaCodec, int32_t bufIdx,
+ AMediaCodecBufferInfo *bufferInfo) {
+ ALOGV("In %s", __func__);
+ if (mediaCodec == mCodec && mediaCodec) {
+ if (mSawOutputEOS || bufIdx < 0) return;
+ if (mSignalledError) {
+ CallBackHandle::mSawError = true;
+ mEncoderDoneCondition.notify_one();
+ return;
+ }
+
+ AMediaCodec_releaseOutputBuffer(mCodec, bufIdx, false);
+ mSawOutputEOS = (0 != (bufferInfo->flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM));
+ mNumOutputFrame++;
+ ALOGV("%s index : %d mSawOutputEOS : %s count : %u", __FUNCTION__, bufIdx,
+ mSawOutputEOS ? "TRUE" : "FALSE", mNumOutputFrame);
+ if (mSawOutputEOS) {
+ CallBackHandle::mIsDone = true;
+ mEncoderDoneCondition.notify_one();
+ }
+ }
+}
+
+void Encoder::onFormatChanged(AMediaCodec *mediaCodec, AMediaFormat *format) {
+ ALOGV("In %s", __func__);
+ if (mediaCodec == mCodec && mediaCodec) {
+ ALOGV("%s { %s }", __FUNCTION__, AMediaFormat_toString(format));
+ mFormat = format;
+ }
+}
+
+void Encoder::setupEncoder() {
+ if (!mFormat) mFormat = AMediaFormat_new();
+ if (!mTimer) mTimer = new Timer();
+}
+
+void Encoder::deInitCodec() {
+ int64_t sTime = mTimer->getCurTime();
+ if (mFormat) {
+ AMediaFormat_delete(mFormat);
+ mFormat = nullptr;
+ }
+ AMediaCodec_stop(mCodec);
+ AMediaCodec_delete(mCodec);
+ int64_t eTime = mTimer->getCurTime();
+ int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
+ mTimer->setDeInitTime(timeTaken);
+}
+
+void Encoder::resetEncoder() {
+ if (mTimer) mTimer->resetTimers();
+ if (mEleStream) mEleStream = nullptr;
+ if (mMime) mMime = nullptr;
+ mInputBufferSize = 0;
+ memset(&mParams, 0, sizeof mParams);
+}
+
+void Encoder::dumpStatistics(string inputReference, int64_t durationUs) {
+ string operation = "encode";
+ mTimer->dumpStatistics(operation, inputReference, durationUs);
+}
+
+int32_t Encoder::encode(string &codecName, ifstream &eleStream, size_t eleSize,
+ bool asyncMode, encParameter encParams, char *mime) {
+ ALOGV("In %s", __func__);
+ mEleStream = &eleStream;
+ mInputBufferSize = eleSize;
+ mParams = encParams;
+ mOffset = 0;
+ mMime = mime;
+ AMediaFormat_setString(mFormat, AMEDIAFORMAT_KEY_MIME, mMime);
+
+ // Set Format
+ if (!strncmp(mMime, "video/", 6)) {
+ AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_WIDTH, mParams.width);
+ AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_HEIGHT, mParams.height);
+ AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_FRAME_RATE, mParams.frameRate);
+ AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_BIT_RATE, mParams.bitrate);
+ AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, 1);
+ if (mParams.profile && mParams.level) {
+ AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_PROFILE, mParams.profile);
+ AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_LEVEL, mParams.level);
+ }
+ } else {
+ AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_SAMPLE_RATE, mParams.sampleRate);
+ AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mParams.numChannels);
+ AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_BIT_RATE, mParams.bitrate);
+ }
+ const char *s = AMediaFormat_toString(mFormat);
+ ALOGV("Input format: %s\n", s);
+
+ int64_t sTime = mTimer->getCurTime();
+ mCodec = createMediaCodec(mFormat, mMime, codecName, true /*isEncoder*/);
+ if (!mCodec) return AMEDIA_ERROR_INVALID_OBJECT;
+ int64_t eTime = mTimer->getCurTime();
+ int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
+
+ if (!strncmp(mMime, "video/", 6)) {
+ mParams.frameSize = mParams.width * mParams.height * 3 / 2;
+ } else {
+ mParams.frameSize = 4096;
+ // Get mInputMaxBufSize
+ AMediaFormat *inputFormat = AMediaCodec_getInputFormat(mCodec);
+ AMediaFormat_getInt32(inputFormat, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, &mParams.maxFrameSize);
+ if (mParams.maxFrameSize < 0) {
+ ALOGE("Invalid mParams.maxFrameSize %d\n", mParams.maxFrameSize);
+ return AMEDIA_ERROR_INVALID_PARAMETER;
+ }
+ if (mParams.frameSize > mParams.maxFrameSize) {
+ mParams.frameSize = mParams.maxFrameSize;
+ }
+ }
+ mParams.numFrames = (mInputBufferSize + mParams.frameSize - 1) / mParams.frameSize;
+
+ sTime = mTimer->getCurTime();
+ if (asyncMode) {
+ AMediaCodecOnAsyncNotifyCallback aCB = {OnInputAvailableCB, OnOutputAvailableCB,
+ OnFormatChangedCB, OnErrorCB};
+ AMediaCodec_setAsyncNotifyCallback(mCodec, aCB, this);
+ CallBackHandle *callbackHandle = new CallBackHandle();
+ callbackHandle->mIOThread = thread(&CallBackHandle::ioThread, this);
+ }
+ AMediaCodec_start(mCodec);
+ eTime = mTimer->getCurTime();
+ timeTaken += mTimer->getTimeDiff(sTime, eTime);
+ mTimer->setInitTime(timeTaken);
+
+ mTimer->setStartTime();
+ if (!asyncMode) {
+ while (!mSawOutputEOS && !mSignalledError) {
+ // Queue input data
+ if (!mSawInputEOS) {
+ ssize_t inIdx = AMediaCodec_dequeueInputBuffer(mCodec, kQueueDequeueTimeoutUs);
+ if (inIdx < 0 && inIdx != AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
+ ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
+ return AMEDIA_ERROR_IO;
+ } else if (inIdx >= 0) {
+ mTimer->addInputTime();
+ onInputAvailable(mCodec, inIdx);
+ }
+ }
+
+ // Dequeue output data
+ AMediaCodecBufferInfo info;
+ ssize_t outIdx = AMediaCodec_dequeueOutputBuffer(mCodec, &info, kQueueDequeueTimeoutUs);
+ if (outIdx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
+ mFormat = AMediaCodec_getOutputFormat(mCodec);
+ const char *s = AMediaFormat_toString(mFormat);
+ ALOGI("Output format: %s\n", s);
+ } else if (outIdx >= 0) {
+ mTimer->addOutputTime();
+ onOutputAvailable(mCodec, outIdx, &info);
+ } else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
+ outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
+ ALOGE("AMediaCodec_dequeueOutputBuffer returned invalid index %zd\n", outIdx);
+ return AMEDIA_ERROR_IO;
+ }
+ }
+ } else {
+ unique_lock<mutex> lock(mMutex);
+ mEncoderDoneCondition.wait(lock, [this]() { return (mSawOutputEOS || mSignalledError); });
+ }
+
+ if (codecName.empty()) {
+ char *encName;
+ AMediaCodec_getName(mCodec, &encName);
+ codecName.assign(encName);
+ AMediaCodec_releaseName(mCodec, encName);
+ }
+ return AMEDIA_OK;
+}
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.h b/media/tests/benchmark/src/native/encoder/Encoder.h
new file mode 100644
index 0000000..903d52b
--- /dev/null
+++ b/media/tests/benchmark/src/native/encoder/Encoder.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 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 __ENCODER_H__
+#define __ENCODER_H__
+
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <thread>
+
+#include "BenchmarkCommon.h"
+#include "Timer.h"
+
+struct encParameter {
+ int32_t bitrate = -1;
+ int32_t numFrames = -1;
+ int32_t frameSize = -1;
+ int32_t sampleRate = 0;
+ int32_t numChannels = 0;
+ int32_t maxFrameSize = -1;
+ int32_t width = 0;
+ int32_t height = 0;
+ int32_t frameRate = -1;
+ int32_t profile = 0;
+ int32_t level = 0;
+};
+
+class Encoder : public CallBackHandle {
+ public:
+ Encoder()
+ : mCodec(nullptr),
+ mFormat(nullptr),
+ mTimer(nullptr),
+ mNumInputFrame(0),
+ mNumOutputFrame(0),
+ mSawInputEOS(false),
+ mSawOutputEOS(false),
+ mSignalledError(false) {}
+
+ virtual ~Encoder() {
+ if (mTimer) delete mTimer;
+ }
+
+ Timer *getTimer() override { return mTimer; }
+
+ // Encoder related utilities
+ void setupEncoder();
+
+ void deInitCodec();
+
+ void resetEncoder();
+
+ // Async callback APIs
+ void onInputAvailable(AMediaCodec *codec, int32_t index) override;
+
+ void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) override;
+
+ void onOutputAvailable(AMediaCodec *codec, int32_t index,
+ AMediaCodecBufferInfo *bufferInfo) override;
+
+ // Process the frames and give encoded output
+ int32_t encode(std::string &codecName, std::ifstream &eleStream, size_t eleSize, bool asyncMode,
+ encParameter encParams, char *mime);
+
+ void dumpStatistics(string inputReference, int64_t durationUs);
+
+ private:
+ AMediaCodec *mCodec;
+ AMediaFormat *mFormat;
+
+ Timer *mTimer;
+
+ int32_t mNumInputFrame;
+ int32_t mNumOutputFrame;
+ bool mSawInputEOS;
+ bool mSawOutputEOS;
+ bool mSignalledError;
+
+ char *mMime;
+ int32_t mOffset;
+ std::ifstream *mEleStream;
+ size_t mInputBufferSize;
+ encParameter mParams;
+
+ // Asynchronous locks
+ std::mutex mMutex;
+ std::condition_variable mEncoderDoneCondition;
+};
+#endif // __ENCODER_H__
diff --git a/media/tests/benchmark/src/native/extractor/Android.bp b/media/tests/benchmark/src/native/extractor/Android.bp
new file mode 100644
index 0000000..2fbe4e8
--- /dev/null
+++ b/media/tests/benchmark/src/native/extractor/Android.bp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_library_static {
+ name: "libbenchmark_extractor",
+ defaults: [
+ "libbenchmark_common-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["Extractor.cpp"],
+
+ export_include_dirs: ["."],
+
+ ldflags: ["-Wl,-Bsymbolic"]
+}
diff --git a/media/tests/benchmark/src/native/extractor/Extractor.cpp b/media/tests/benchmark/src/native/extractor/Extractor.cpp
new file mode 100644
index 0000000..0726ae3
--- /dev/null
+++ b/media/tests/benchmark/src/native/extractor/Extractor.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2019 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 "extractor"
+
+#include <iostream>
+
+#include "Extractor.h"
+
+int32_t Extractor::initExtractor(int32_t fd, size_t fileSize) {
+ mTimer = new Timer();
+
+ mFrameBuf = (uint8_t *)calloc(kMaxBufferSize, sizeof(uint8_t));
+ if (!mFrameBuf) return -1;
+
+ int64_t sTime = mTimer->getCurTime();
+
+ mExtractor = AMediaExtractor_new();
+ if (!mExtractor) return AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE;
+ media_status_t status = AMediaExtractor_setDataSourceFd(mExtractor, fd, 0, fileSize);
+ if (status != AMEDIA_OK) return status;
+
+ int64_t eTime = mTimer->getCurTime();
+ int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
+ mTimer->setInitTime(timeTaken);
+
+ return AMediaExtractor_getTrackCount(mExtractor);
+}
+
+void *Extractor::getCSDSample(AMediaCodecBufferInfo &frameInfo, int32_t csdIndex) {
+ char csdName[kMaxCSDStrlen];
+ void *csdBuffer = nullptr;
+ frameInfo.presentationTimeUs = 0;
+ frameInfo.flags = AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG;
+ snprintf(csdName, sizeof(csdName), "csd-%d", csdIndex);
+
+ size_t size;
+ bool csdFound = AMediaFormat_getBuffer(mFormat, csdName, &csdBuffer, &size);
+ if (!csdFound) return nullptr;
+ frameInfo.size = (int32_t)size;
+
+ return csdBuffer;
+}
+
+int32_t Extractor::getFrameSample(AMediaCodecBufferInfo &frameInfo) {
+ int32_t size = AMediaExtractor_readSampleData(mExtractor, mFrameBuf, kMaxBufferSize);
+ if (size < 0) return -1;
+
+ frameInfo.flags = AMediaExtractor_getSampleFlags(mExtractor);
+ frameInfo.size = size;
+ frameInfo.presentationTimeUs = AMediaExtractor_getSampleTime(mExtractor);
+ AMediaExtractor_advance(mExtractor);
+
+ return 0;
+}
+
+int32_t Extractor::setupTrackFormat(int32_t trackId) {
+ AMediaExtractor_selectTrack(mExtractor, trackId);
+ mFormat = AMediaExtractor_getTrackFormat(mExtractor, trackId);
+ if (!mFormat) return AMEDIA_ERROR_INVALID_OBJECT;
+
+ bool durationFound = AMediaFormat_getInt64(mFormat, AMEDIAFORMAT_KEY_DURATION, &mDurationUs);
+ if (!durationFound) return AMEDIA_ERROR_INVALID_OBJECT;
+
+ return AMEDIA_OK;
+}
+
+int32_t Extractor::extract(int32_t trackId) {
+ int32_t status = setupTrackFormat(trackId);
+ if (status != AMEDIA_OK) return status;
+
+ int32_t idx = 0;
+ AMediaCodecBufferInfo frameInfo;
+ while (1) {
+ memset(&frameInfo, 0, sizeof(AMediaCodecBufferInfo));
+ void *csdBuffer = getCSDSample(frameInfo, idx);
+ if (!csdBuffer || !frameInfo.size) break;
+ idx++;
+ }
+
+ mTimer->setStartTime();
+ while (1) {
+ int32_t status = getFrameSample(frameInfo);
+ if (status || !frameInfo.size) break;
+ mTimer->addOutputTime();
+ }
+
+ if (mFormat) {
+ AMediaFormat_delete(mFormat);
+ mFormat = nullptr;
+ }
+
+ AMediaExtractor_unselectTrack(mExtractor, trackId);
+
+ return AMEDIA_OK;
+}
+
+void Extractor::dumpStatistics(string inputReference) {
+ string operation = "extract";
+ mTimer->dumpStatistics(operation, inputReference, mDurationUs);
+}
+
+void Extractor::deInitExtractor() {
+ if (mFrameBuf) {
+ free(mFrameBuf);
+ mFrameBuf = nullptr;
+ }
+
+ int64_t sTime = mTimer->getCurTime();
+ if (mExtractor) {
+ // TODO: (b/140128505) Multiple calls result in DoS.
+ // Uncomment call to AMediaExtractor_delete() once this is resolved
+ // AMediaExtractor_delete(mExtractor);
+ mExtractor = nullptr;
+ }
+ int64_t eTime = mTimer->getCurTime();
+ int64_t deInitTime = mTimer->getTimeDiff(sTime, eTime);
+ mTimer->setDeInitTime(deInitTime);
+}
diff --git a/media/tests/benchmark/src/native/extractor/Extractor.h b/media/tests/benchmark/src/native/extractor/Extractor.h
new file mode 100644
index 0000000..361bcd7
--- /dev/null
+++ b/media/tests/benchmark/src/native/extractor/Extractor.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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 __EXTRACTOR_H__
+#define __EXTRACTOR_H__
+
+#include <media/NdkMediaExtractor.h>
+
+#include "BenchmarkCommon.h"
+#include "Timer.h"
+
+class Extractor {
+ public:
+ Extractor()
+ : mFormat(nullptr),
+ mExtractor(nullptr),
+ mTimer(nullptr),
+ mFrameBuf{nullptr},
+ mDurationUs{0} {}
+
+ ~Extractor() {
+ if (mTimer) delete mTimer;
+ }
+
+ int32_t initExtractor(int32_t fd, size_t fileSize);
+
+ int32_t setupTrackFormat(int32_t trackId);
+
+ void *getCSDSample(AMediaCodecBufferInfo &frameInfo, int32_t csdIndex);
+
+ int32_t getFrameSample(AMediaCodecBufferInfo &frameInfo);
+
+ int32_t extract(int32_t trackId);
+
+ void dumpStatistics(std::string inputReference);
+
+ void deInitExtractor();
+
+ AMediaFormat *getFormat() { return mFormat; }
+
+ uint8_t *getFrameBuf() { return mFrameBuf; }
+
+ int64_t getClipDuration() { return mDurationUs; }
+
+ private:
+ AMediaFormat *mFormat;
+ AMediaExtractor *mExtractor;
+ Timer *mTimer;
+ uint8_t *mFrameBuf;
+ int64_t mDurationUs;
+};
+
+#endif // __EXTRACTOR_H__
\ No newline at end of file
diff --git a/media/tests/benchmark/src/native/muxer/Android.bp b/media/tests/benchmark/src/native/muxer/Android.bp
new file mode 100644
index 0000000..6ef2a2e
--- /dev/null
+++ b/media/tests/benchmark/src/native/muxer/Android.bp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_library_static {
+ name: "libbenchmark_muxer",
+ defaults: [
+ "libbenchmark_common-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["Muxer.cpp"],
+
+ static_libs: ["libbenchmark_extractor"],
+
+ export_include_dirs: ["."],
+
+ ldflags: ["-Wl,-Bsymbolic"]
+}
diff --git a/media/tests/benchmark/src/native/muxer/Muxer.cpp b/media/tests/benchmark/src/native/muxer/Muxer.cpp
new file mode 100644
index 0000000..877f7ad
--- /dev/null
+++ b/media/tests/benchmark/src/native/muxer/Muxer.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 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 "muxer"
+
+#include <fstream>
+#include <iostream>
+
+#include "Muxer.h"
+
+int32_t Muxer::initMuxer(int32_t fd, MUXER_OUTPUT_T outputFormat) {
+ if (!mFormat) mFormat = mExtractor->getFormat();
+ if (!mTimer) mTimer = new Timer();
+
+ int64_t sTime = mTimer->getCurTime();
+ mMuxer = AMediaMuxer_new(fd, (OutputFormat)outputFormat);
+ if (!mMuxer) {
+ cout << "[ WARN ] Test Skipped. Unable to create muxer \n";
+ return AMEDIA_ERROR_INVALID_OBJECT;
+ }
+ /*
+ * AMediaMuxer_addTrack returns the index of the new track or a negative value
+ * in case of failure, which can be interpreted as a media_status_t.
+ */
+ ssize_t index = AMediaMuxer_addTrack(mMuxer, mFormat);
+ if (index < 0) {
+ cout << "[ WARN ] Test Skipped. Format not supported \n";
+ return index;
+ }
+ AMediaMuxer_start(mMuxer);
+ int64_t eTime = mTimer->getCurTime();
+ int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
+ mTimer->setInitTime(timeTaken);
+ return AMEDIA_OK;
+}
+
+void Muxer::deInitMuxer() {
+ int64_t sTime = mTimer->getCurTime();
+ if (mFormat) {
+ AMediaFormat_delete(mFormat);
+ mFormat = nullptr;
+ }
+ if (!mMuxer) return;
+ AMediaMuxer_stop(mMuxer);
+ AMediaMuxer_delete(mMuxer);
+ int64_t eTime = mTimer->getCurTime();
+ int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
+ mTimer->setDeInitTime(timeTaken);
+}
+
+void Muxer::resetMuxer() {
+ if (mTimer) mTimer->resetTimers();
+}
+
+void Muxer::dumpStatistics(string inputReference) {
+ string operation = "mux";
+ mTimer->dumpStatistics(operation, inputReference, mExtractor->getClipDuration());
+}
+
+int32_t Muxer::mux(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfos) {
+ // Mux frame data
+ size_t frameIdx = 0;
+ mTimer->setStartTime();
+ while (frameIdx < frameInfos.size()) {
+ AMediaCodecBufferInfo info = frameInfos.at(frameIdx);
+ media_status_t status = AMediaMuxer_writeSampleData(mMuxer, 0, inputBuffer, &info);
+ if (status != 0) {
+ ALOGE("Error in AMediaMuxer_writeSampleData");
+ return status;
+ }
+ mTimer->addOutputTime();
+ frameIdx++;
+ }
+ return AMEDIA_OK;
+}
diff --git a/media/tests/benchmark/src/native/muxer/Muxer.h b/media/tests/benchmark/src/native/muxer/Muxer.h
new file mode 100644
index 0000000..154fd20
--- /dev/null
+++ b/media/tests/benchmark/src/native/muxer/Muxer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 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 __MUXER_H__
+#define __MUXER_H__
+
+#include <media/NdkMediaMuxer.h>
+
+#include "BenchmarkCommon.h"
+#include "Timer.h"
+#include "Extractor.h"
+
+typedef enum {
+ MUXER_OUTPUT_FORMAT_MPEG_4 = 0,
+ MUXER_OUTPUT_FORMAT_WEBM = 1,
+ MUXER_OUTPUT_FORMAT_3GPP = 2,
+ MUXER_OUTPUT_FORMAT_OGG = 4,
+ MUXER_OUTPUT_FORMAT_INVALID = 5,
+} MUXER_OUTPUT_T;
+
+class Muxer {
+ public:
+ Muxer() : mFormat(nullptr), mMuxer(nullptr), mTimer(nullptr) { mExtractor = new Extractor(); }
+
+ virtual ~Muxer() {
+ if (mTimer) delete mTimer;
+ if (mExtractor) delete mExtractor;
+ }
+
+ Timer *getTimer() { return mTimer; }
+ Extractor *getExtractor() { return mExtractor; }
+
+ /* Muxer related utilities */
+ int32_t initMuxer(int32_t fd, MUXER_OUTPUT_T outputFormat);
+ void deInitMuxer();
+ void resetMuxer();
+
+ /* Process the frames and give Muxed output */
+ int32_t mux(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameSizes);
+
+ void dumpStatistics(string inputReference);
+
+ private:
+ AMediaFormat *mFormat;
+ AMediaMuxer *mMuxer;
+ Extractor *mExtractor;
+ Timer *mTimer;
+};
+
+#endif // __MUXER_H__
diff --git a/media/tests/benchmark/tests/Android.bp b/media/tests/benchmark/tests/Android.bp
new file mode 100644
index 0000000..fc21ef7
--- /dev/null
+++ b/media/tests/benchmark/tests/Android.bp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+cc_test {
+ name: "extractorTest",
+ gtest: true,
+ defaults: [
+ "libbenchmark_common-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["ExtractorTest.cpp"],
+
+ static_libs: ["libbenchmark_extractor"]
+}
+
+cc_test {
+ name: "decoderTest",
+ gtest: true,
+ defaults: [
+ "libbenchmark_common-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["DecoderTest.cpp"],
+
+ static_libs: [
+ "libbenchmark_extractor",
+ "libbenchmark_decoder",
+ ],
+}
+
+cc_test {
+ name: "muxerTest",
+ gtest: true,
+ defaults: [
+ "libbenchmark_common-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["MuxerTest.cpp"],
+
+ static_libs: [
+ "libbenchmark_extractor",
+ "libbenchmark_muxer",
+ ],
+}
+
+cc_test {
+ name: "encoderTest",
+ gtest: true,
+ defaults: [
+ "libbenchmark_common-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["EncoderTest.cpp"],
+
+ static_libs: [
+ "libbenchmark_extractor",
+ "libbenchmark_decoder",
+ "libbenchmark_encoder",
+ ],
+}
diff --git a/media/tests/benchmark/tests/BenchmarkTestEnvironment.h b/media/tests/benchmark/tests/BenchmarkTestEnvironment.h
new file mode 100644
index 0000000..ae2eee1
--- /dev/null
+++ b/media/tests/benchmark/tests/BenchmarkTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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 __BENCHMARK_TEST_ENVIRONMENT_H__
+#define __BENCHMARK_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class BenchmarkTestEnvironment : public ::testing::Environment {
+ public:
+ BenchmarkTestEnvironment() : res("/sdcard/media/") {}
+
+ // Parses the command line argument
+ int initFromOptions(int argc, char **argv);
+
+ void setRes(const char *_res) { res = _res; }
+
+ const string getRes() const { return res; }
+
+ private:
+ string res;
+};
+
+int BenchmarkTestEnvironment::initFromOptions(int argc, char **argv) {
+ static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+ while (true) {
+ int index = 0;
+ int c = getopt_long(argc, argv, "P:", options, &index);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'P': {
+ setRes(optarg);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "unrecognized option: %s\n\n"
+ "usage: %s <gtest options> <test options>\n\n"
+ "test options are:\n\n"
+ "-P, --path: Resource files directory location\n",
+ argv[optind ?: 1], argv[0]);
+ return 2;
+ }
+ return 0;
+}
+
+#endif // __BENCHMARK_TEST_ENVIRONMENT_H__
diff --git a/media/tests/benchmark/tests/DecoderTest.cpp b/media/tests/benchmark/tests/DecoderTest.cpp
new file mode 100644
index 0000000..6cb42d6
--- /dev/null
+++ b/media/tests/benchmark/tests/DecoderTest.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2019 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 "decoderTest"
+
+#include <fstream>
+#include <iostream>
+#include <limits>
+
+#include "Decoder.h"
+#include "BenchmarkTestEnvironment.h"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class DecoderTest : public ::testing::TestWithParam<tuple<string, string, bool>> {};
+
+TEST_P(DecoderTest, Decode) {
+ ALOGV("Decode the samples given by extractor");
+ tuple<string /* InputFile */, string /* CodecName */, bool /* asyncMode */> params = GetParam();
+
+ string inputFile = gEnv->getRes() + get<0>(params);
+ FILE *inputFp = fopen(inputFile.c_str(), "rb");
+ if (!inputFp) {
+ cout << "[ WARN ] Test Skipped. Unable to open input file for reading \n";
+ return;
+ }
+
+ Decoder *decoder = new Decoder();
+ Extractor *extractor = decoder->getExtractor();
+ if (!extractor) {
+ cout << "[ WARN ] Test Skipped. Extractor creation failed \n";
+ return;
+ }
+
+ // Read file properties
+ fseek(inputFp, 0, SEEK_END);
+ size_t fileSize = ftell(inputFp);
+ fseek(inputFp, 0, SEEK_SET);
+ int32_t fd = fileno(inputFp);
+
+ int32_t trackCount = extractor->initExtractor(fd, fileSize);
+ if (trackCount <= 0) {
+ cout << "[ WARN ] Test Skipped. initExtractor failed\n";
+ return;
+ }
+ for (int curTrack = 0; curTrack < trackCount; curTrack++) {
+ int32_t status = extractor->setupTrackFormat(curTrack);
+ if (status != 0) {
+ cout << "[ WARN ] Test Skipped. Track Format invalid \n";
+ return;
+ }
+
+ uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+ if (!inputBuffer) {
+ cout << "[ WARN ] Test Skipped. Insufficient memory \n";
+ return;
+ }
+ vector<AMediaCodecBufferInfo> frameInfo;
+ AMediaCodecBufferInfo info;
+ uint32_t inputBufferOffset = 0;
+ int32_t idx = 0;
+
+ // Get CSD data
+ while (1) {
+ void *csdBuffer = extractor->getCSDSample(info, idx);
+ if (!csdBuffer || !info.size) break;
+
+ // copy the meta data and buffer to be passed to decoder
+ if (inputBufferOffset + info.size > kMaxBufferSize) {
+ cout << "[ WARN ] Test Skipped. Memory allocated not sufficient\n";
+ free(inputBuffer);
+ return;
+ }
+ memcpy(inputBuffer + inputBufferOffset, csdBuffer, info.size);
+ frameInfo.push_back(info);
+ inputBufferOffset += info.size;
+ idx++;
+ }
+ // Get frame data
+ while (1) {
+ status = extractor->getFrameSample(info);
+ if (status || !info.size) break;
+ // copy the meta data and buffer to be passed to decoder
+ if (inputBufferOffset + info.size > kMaxBufferSize) {
+ cout << "[ WARN ] Test Skipped. Memory allocated not sufficient\n";
+ free(inputBuffer);
+ return;
+ }
+ memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+ frameInfo.push_back(info);
+ inputBufferOffset += info.size;
+ }
+
+ string codecName = get<1>(params);
+ bool asyncMode = get<2>(params);
+ decoder->setupDecoder();
+ status = decoder->decode(inputBuffer, frameInfo, codecName, asyncMode);
+ if (status != AMEDIA_OK) {
+ cout << "[ WARN ] Test Skipped. Decode returned error \n";
+ free(inputBuffer);
+ return;
+ }
+ decoder->deInitCodec();
+ cout << "codec : " << codecName << endl;
+ string inputReference = get<0>(params);
+ decoder->dumpStatistics(inputReference);
+ free(inputBuffer);
+ decoder->resetDecoder();
+ }
+ fclose(inputFp);
+ extractor->deInitExtractor();
+ delete decoder;
+}
+
+// TODO: (b/140549596)
+// Add wav files
+INSTANTIATE_TEST_SUITE_P(
+ AudioDecoderSyncTest, DecoderTest,
+ ::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", false),
+ make_tuple("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "", false),
+ make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", false),
+ make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", false),
+ make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "", false),
+ make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", false)));
+
+INSTANTIATE_TEST_SUITE_P(
+ AudioDecoderAsyncTest, DecoderTest,
+ ::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", true),
+ make_tuple("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "", true),
+ make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", true),
+ make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", true),
+ make_tuple("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "", true),
+ make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", true)));
+
+INSTANTIATE_TEST_SUITE_P(VideDecoderSyncTest, DecoderTest,
+ ::testing::Values(
+ // Hardware codecs
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm", "", false),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm", "", false),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm", "", false),
+ make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", "", false),
+ make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "", false),
+ make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp", "", false),
+ make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", "", false),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv", "", false),
+ // Software codecs
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm",
+ "c2.android.vp9.decoder", false),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm",
+ "c2.android.vp8.decoder", false),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm",
+ "c2.android.av1.decoder", false),
+ make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4",
+ "c2.android.mpeg2.decoder", false),
+ make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4",
+ "c2.android.mpeg4.decoder", false),
+ make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp",
+ "c2.android.h263.decoder", false),
+ make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts",
+ "c2.android.avc.decoder", false),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv",
+ "c2.android.hevc.decoder", false)));
+
+INSTANTIATE_TEST_SUITE_P(VideoDecoderAsyncTest, DecoderTest,
+ ::testing::Values(
+ // Hardware codecs
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm", "", true),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm", "", true),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm", "", true),
+ make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", "", true),
+ make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "", true),
+ make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp", "", true),
+ make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", "", true),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv", "", true),
+ // Software codecs
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm",
+ "c2.android.vp9.decoder", true),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm",
+ "c2.android.vp8.decoder", true),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_av1.webm",
+ "c2.android.av1.decoder", true),
+ make_tuple("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4",
+ "c2.android.mpeg2.decoder", true),
+ make_tuple("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4",
+ "c2.android.mpeg4.decoder", true),
+ make_tuple("crowd_352x288_25fps_6000kbps_h263.3gp",
+ "c2.android.h263.decoder", true),
+ make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts",
+ "c2.android.avc.decoder", true),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv",
+ "c2.android.hevc.decoder", true)));
+
+int main(int argc, char **argv) {
+ gEnv = new BenchmarkTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGD("Decoder Test result = %d\n", status);
+ }
+ return status;
+}
\ No newline at end of file
diff --git a/media/tests/benchmark/tests/EncoderTest.cpp b/media/tests/benchmark/tests/EncoderTest.cpp
new file mode 100644
index 0000000..574083d
--- /dev/null
+++ b/media/tests/benchmark/tests/EncoderTest.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2019 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 "encoderTest"
+
+#include <fstream>
+
+#include "BenchmarkTestEnvironment.h"
+#include "Encoder.h"
+#include "Decoder.h"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class EncoderTest : public ::testing::TestWithParam<tuple<string, string, bool>> {};
+
+TEST_P(EncoderTest, Encode) {
+ ALOGD("Encode test for all codecs");
+ tuple<string /* InputFile */, string /* CodecName */, bool /* asyncMode */> params = GetParam();
+
+ string inputFile = gEnv->getRes() + get<0>(params);
+ FILE *inputFp = fopen(inputFile.c_str(), "rb");
+ if (!inputFp) {
+ cout << "[ WARN ] Test Skipped. Unable to open input file for reading \n";
+ return;
+ }
+
+ Decoder *decoder = new Decoder();
+ Extractor *extractor = decoder->getExtractor();
+ if (!extractor) {
+ cout << "[ WARN ] Test Skipped. Extractor creation failed \n";
+ return;
+ }
+ // Read file properties
+ fseek(inputFp, 0, SEEK_END);
+ size_t fileSize = ftell(inputFp);
+ fseek(inputFp, 0, SEEK_SET);
+ int32_t fd = fileno(inputFp);
+
+ int32_t trackCount = extractor->initExtractor(fd, fileSize);
+ if (trackCount <= 0) {
+ cout << "[ WARN ] Test Skipped. initExtractor failed\n";
+ return;
+ }
+
+ Encoder *encoder = new Encoder();
+ for (int curTrack = 0; curTrack < trackCount; curTrack++) {
+ int32_t status = extractor->setupTrackFormat(curTrack);
+ if (status != 0) {
+ cout << "[ WARN ] Test Skipped. Track Format invalid \n";
+ return;
+ }
+
+ uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+ if (!inputBuffer) {
+ cout << "[ WARN ] Test Skipped. Insufficient memory \n";
+ return;
+ }
+ vector<AMediaCodecBufferInfo> frameInfo;
+ AMediaCodecBufferInfo info;
+ uint32_t inputBufferOffset = 0;
+ int32_t idx = 0;
+
+ // Get CSD data
+ while (1) {
+ void *csdBuffer = extractor->getCSDSample(info, idx);
+ if (!csdBuffer || !info.size) break;
+
+ // copy the meta data and buffer to be passed to decoder
+ if (inputBufferOffset + info.size > kMaxBufferSize) {
+ cout << "[ WARN ] Test Skipped. Memory allocated not sufficient\n";
+ free(inputBuffer);
+ return;
+ }
+ memcpy(inputBuffer + inputBufferOffset, csdBuffer, info.size);
+ frameInfo.push_back(info);
+ inputBufferOffset += info.size;
+ idx++;
+ }
+
+ // Get frame data
+ while (1) {
+ status = extractor->getFrameSample(info);
+ if (status || !info.size) break;
+ // copy the meta data and buffer to be passed to decoder
+ if (inputBufferOffset + info.size > kMaxBufferSize) {
+ cout << "[ WARN ] Test Skipped. Memory allocated not sufficient\n";
+ free(inputBuffer);
+ return;
+ }
+ memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+ frameInfo.push_back(info);
+ inputBufferOffset += info.size;
+ }
+
+ string decName = "";
+ string outputFileName = "decode.out";
+ FILE *outFp = fopen(outputFileName.c_str(), "wb");
+ if (outFp == nullptr) {
+ ALOGE("Unable to open output file for writing");
+ return;
+ }
+ decoder->setupDecoder();
+ status = decoder->decode(inputBuffer, frameInfo, decName, false /*asyncMode */, outFp);
+ if (status != AMEDIA_OK) {
+ cout << "[ WARN ] Test Skipped. Decode returned error \n";
+ return;
+ }
+
+ ifstream eleStream;
+ eleStream.open(outputFileName.c_str(), ifstream::binary | ifstream::ate);
+ ASSERT_EQ(eleStream.is_open(), true) << outputFileName.c_str() << " - file not found";
+ size_t eleSize = eleStream.tellg();
+ eleStream.seekg(0, ifstream::beg);
+
+ AMediaFormat *format = extractor->getFormat();
+ const char *mime = nullptr;
+ AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
+ if (!mime) {
+ ALOGE("Error in AMediaFormat_getString");
+ return;
+ }
+ // Get encoder params
+ encParameter encParams;
+ if (!strncmp(mime, "video/", 6)) {
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &encParams.width);
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &encParams.height);
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, &encParams.frameRate);
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &encParams.bitrate);
+ if (encParams.bitrate <= 0 || encParams.frameRate <= 0) {
+ encParams.frameRate = 25;
+ if (!strcmp(mime, "video/3gpp") || !strcmp(mime, "video/mp4v-es")) {
+ encParams.bitrate = 600000 /* 600 Kbps */;
+ } else {
+ encParams.bitrate = 8000000 /* 8 Mbps */;
+ }
+ }
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_PROFILE, &encParams.profile);
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_LEVEL, &encParams.level);
+ } else {
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &encParams.sampleRate);
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &encParams.numChannels);
+ encParams.bitrate =
+ encParams.sampleRate * encParams.numChannels * 16 /* bitsPerSample */;
+ }
+
+ encoder->setupEncoder();
+ string codecName = get<1>(params);
+ bool asyncMode = get<2>(params);
+ status = encoder->encode(codecName, eleStream, eleSize, asyncMode, encParams, (char *)mime);
+ ASSERT_EQ(status, 0);
+ encoder->deInitCodec();
+ cout << "codec : " << codecName << endl;
+ string inputReference = get<0>(params);
+ encoder->dumpStatistics(inputReference, extractor->getClipDuration());
+ eleStream.close();
+ if (outFp) fclose(outFp);
+
+ if (format) {
+ AMediaFormat_delete(format);
+ format = nullptr;
+ }
+ encoder->resetEncoder();
+ decoder->deInitCodec();
+ free(inputBuffer);
+ decoder->resetDecoder();
+ }
+ delete encoder;
+ fclose(inputFp);
+ extractor->deInitExtractor();
+ delete decoder;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ AudioEncoderSyncTest, EncoderTest,
+ ::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", false),
+ make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", false),
+ make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", false),
+ make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", false)));
+
+INSTANTIATE_TEST_SUITE_P(
+ AudioEncoderAsyncTest, EncoderTest,
+ ::testing::Values(make_tuple("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "", true),
+ make_tuple("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "", true),
+ make_tuple("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "", true),
+ make_tuple("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "", true)));
+
+INSTANTIATE_TEST_SUITE_P(VideEncoderSyncTest, EncoderTest,
+ ::testing::Values(
+ // Hardware codecs
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm", "", false),
+ make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", "", false),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv", "", false),
+ // Software codecs
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm",
+ "c2.android.vp9.encoder", false),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm",
+ "c2.android.vp8.encoder", false),
+ make_tuple("crowd_176x144_25fps_6000kbps_mpeg4.mp4",
+ "c2.android.mpeg4.encoder", false),
+ make_tuple("crowd_176x144_25fps_6000kbps_h263.3gp",
+ "c2.android.h263.encoder", false),
+ make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts",
+ "c2.android.avc.encoder", false),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv",
+ "c2.android.hevc.encoder", false)));
+
+INSTANTIATE_TEST_SUITE_P(VideoEncoderAsyncTest, EncoderTest,
+ ::testing::Values(
+ // Hardware codecs
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm", "", true),
+ make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts", "", true),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv", "", true),
+ // Software codecs
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp9.webm",
+ "c2.android.vp9.encoder", true),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_vp8.webm",
+ "c2.android.vp8.encoder", true),
+ make_tuple("crowd_176x144_25fps_6000kbps_mpeg4.mp4",
+ "c2.android.mpeg4.encoder", true),
+ make_tuple("crowd_176x144_25fps_6000kbps_h263.3gp",
+ "c2.android.h263.encoder", true),
+ make_tuple("crowd_1920x1080_25fps_6700kbps_h264.ts",
+ "c2.android.avc.encoder", true),
+ make_tuple("crowd_1920x1080_25fps_4000kbps_h265.mkv",
+ "c2.android.hevc.encoder", true)));
+
+int main(int argc, char **argv) {
+ gEnv = new BenchmarkTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGD("Encoder Test result = %d\n", status);
+ }
+ return status;
+}
diff --git a/media/tests/benchmark/tests/ExtractorTest.cpp b/media/tests/benchmark/tests/ExtractorTest.cpp
new file mode 100644
index 0000000..dd0d711
--- /dev/null
+++ b/media/tests/benchmark/tests/ExtractorTest.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 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 "extractorTest"
+
+#include <gtest/gtest.h>
+
+#include "Extractor.h"
+#include "BenchmarkTestEnvironment.h"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class ExtractorTest : public ::testing::TestWithParam<pair<string, int32_t>> {};
+
+TEST_P(ExtractorTest, Extract) {
+ Extractor *extractObj = new Extractor();
+
+ string inputFile = gEnv->getRes() + GetParam().first;
+ FILE *inputFp = fopen(inputFile.c_str(), "rb");
+ if (!inputFp) {
+ cout << "[ WARN ] Test Skipped. Unable to open input file for reading \n";
+ return;
+ }
+
+ // Read file properties
+ size_t fileSize = 0;
+ fseek(inputFp, 0, SEEK_END);
+ fileSize = ftell(inputFp);
+ fseek(inputFp, 0, SEEK_SET);
+ int32_t fd = fileno(inputFp);
+
+ int32_t trackCount = extractObj->initExtractor(fd, fileSize);
+ if (trackCount <= 0) {
+ cout << "[ WARN ] Test Skipped. initExtractor failed\n";
+ return;
+ }
+
+ int32_t trackID = GetParam().second;
+ int32_t status = extractObj->extract(trackID);
+ if (status != AMEDIA_OK) {
+ cout << "[ WARN ] Test Skipped. Extraction failed \n";
+ return;
+ }
+
+ extractObj->deInitExtractor();
+
+ extractObj->dumpStatistics(GetParam().first);
+
+ fclose(inputFp);
+ delete extractObj;
+}
+
+INSTANTIATE_TEST_SUITE_P(ExtractorTestAll, ExtractorTest,
+ ::testing::Values(make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", 0),
+ make_pair("crowd_1920x1080_25fps_6000kbps_h263.3gp", 0),
+ make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", 0),
+ make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", 0),
+ make_pair("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", 0),
+ make_pair("crowd_1920x1080_25fps_4000kbps_av1.webm", 0),
+ make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", 0),
+ make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", 0),
+ make_pair("bbb_44100hz_2ch_128kbps_aac_5mins.mp4", 0),
+ make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", 0),
+ make_pair("bbb_44100hz_2ch_600kbps_flac_5mins.flac", 0),
+ make_pair("bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", 0),
+ make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", 0),
+ make_pair("bbb_44100hz_2ch_80kbps_vorbis_5mins.mp4", 0),
+ make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm", 0)));
+
+int main(int argc, char **argv) {
+ gEnv = new BenchmarkTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGD(" Extractor Test result = %d\n", status);
+ }
+ return status;
+}
diff --git a/media/tests/benchmark/tests/MuxerTest.cpp b/media/tests/benchmark/tests/MuxerTest.cpp
new file mode 100644
index 0000000..e814f90
--- /dev/null
+++ b/media/tests/benchmark/tests/MuxerTest.cpp
@@ -0,0 +1,181 @@
+
+/*
+ * Copyright (C) 2019 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 "muxerTest"
+
+#include <fstream>
+#include <iostream>
+
+#include "Muxer.h"
+#include "BenchmarkTestEnvironment.h"
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/mux.out"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class MuxerTest : public ::testing::TestWithParam<pair<string, string>> {};
+
+static MUXER_OUTPUT_T getMuxerOutFormat(string fmt) {
+ static const struct {
+ string name;
+ MUXER_OUTPUT_T value;
+ } kFormatMaps[] = {{"mp4", MUXER_OUTPUT_FORMAT_MPEG_4},
+ {"webm", MUXER_OUTPUT_FORMAT_WEBM},
+ {"3gpp", MUXER_OUTPUT_FORMAT_3GPP},
+ {"ogg", MUXER_OUTPUT_FORMAT_OGG}};
+
+ MUXER_OUTPUT_T format = MUXER_OUTPUT_FORMAT_INVALID;
+ for (size_t i = 0; i < sizeof(kFormatMaps) / sizeof(kFormatMaps[0]); ++i) {
+ if (!fmt.compare(kFormatMaps[i].name)) {
+ format = kFormatMaps[i].value;
+ break;
+ }
+ }
+ return format;
+}
+
+TEST_P(MuxerTest, Mux) {
+ ALOGV("Mux the samples given by extractor");
+ string inputFile = gEnv->getRes() + GetParam().first;
+ FILE *inputFp = fopen(inputFile.c_str(), "rb");
+ if (!inputFp) {
+ cout << "[ WARN ] Test Skipped. Unable to open input file for reading \n";
+ return;
+ }
+ string fmt = GetParam().second;
+ MUXER_OUTPUT_T outputFormat = getMuxerOutFormat(fmt);
+ if (outputFormat == MUXER_OUTPUT_FORMAT_INVALID) {
+ ALOGE("output format is MUXER_OUTPUT_FORMAT_INVALID");
+ return;
+ }
+
+ Muxer *muxerObj = new Muxer();
+ Extractor *extractor = muxerObj->getExtractor();
+ if (!extractor) {
+ cout << "[ WARN ] Test Skipped. Extractor creation failed \n";
+ return;
+ }
+
+ // Read file properties
+ size_t fileSize = 0;
+ fseek(inputFp, 0, SEEK_END);
+ fileSize = ftell(inputFp);
+ fseek(inputFp, 0, SEEK_SET);
+ int32_t fd = fileno(inputFp);
+
+ int32_t trackCount = extractor->initExtractor(fd, fileSize);
+ if (trackCount <= 0) {
+ cout << "[ WARN ] Test Skipped. initExtractor failed\n";
+ return;
+ }
+
+ for (int curTrack = 0; curTrack < trackCount; curTrack++) {
+ int32_t status = extractor->setupTrackFormat(curTrack);
+ if (status != 0) {
+ cout << "[ WARN ] Test Skipped. Track Format invalid \n";
+ return;
+ }
+
+ uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+ if (!inputBuffer) {
+ std::cout << "[ WARN ] Test Skipped. Insufficient memory \n";
+ return;
+ }
+ // AMediaCodecBufferInfo : <size of frame> <flags> <presentationTimeUs> <offset>
+ vector<AMediaCodecBufferInfo> frameInfos;
+ AMediaCodecBufferInfo info;
+ uint32_t inputBufferOffset = 0;
+
+ // Get Frame Data
+ while (1) {
+ status = extractor->getFrameSample(info);
+ if (status || !info.size) break;
+ // copy the meta data and buffer to be passed to muxer
+ if (inputBufferOffset + info.size > kMaxBufferSize) {
+ cout << "[ WARN ] Test Skipped. Memory allocated not sufficient\n";
+ free(inputBuffer);
+ return;
+ }
+ memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+ info.offset = inputBufferOffset;
+ frameInfos.push_back(info);
+ inputBufferOffset += info.size;
+ }
+
+ string outputFileName = OUTPUT_FILE_NAME;
+ FILE *outputFp = fopen(outputFileName.c_str(), "w+b");
+ if (!outputFp) {
+ cout << "[ WARN ] Test Skipped. Unable to open output file for writing \n";
+ return;
+ }
+ int32_t fd = fileno(outputFp);
+ status = muxerObj->initMuxer(fd, outputFormat);
+ if (status != 0) {
+ cout << "[ WARN ] Test Skipped. initMuxer failed\n";
+ return;
+ }
+
+ status = muxerObj->mux(inputBuffer, frameInfos);
+ if (status != 0) {
+ cout << "[ WARN ] Test Skipped. Mux failed \n";
+ return;
+ }
+ muxerObj->deInitMuxer();
+ muxerObj->dumpStatistics(GetParam().first + "." + fmt.c_str());
+ free(inputBuffer);
+ fclose(outputFp);
+ muxerObj->resetMuxer();
+ }
+ fclose(inputFp);
+ extractor->deInitExtractor();
+ delete muxerObj;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ MuxerTestAll, MuxerTest,
+ ::testing::Values(make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", "webm"),
+ make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", "webm"),
+ make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "mp4"),
+ make_pair("crowd_352x288_25fps_6000kbps_h263.3gp", "mp4"),
+ make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "mp4"),
+ make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "mp4"),
+ make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "3gpp"),
+ make_pair("crowd_352x288_25fps_6000kbps_h263.3gp", "3gpp"),
+ make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "3gpp"),
+ make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "3gpp"),
+ make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm", "ogg"),
+ make_pair("bbb_44100hz_2ch_80kbps_vorbis_5mins.mp4", "webm"),
+ make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm", "webm"),
+ make_pair("bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "mp4"),
+ make_pair("bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "mp4"),
+ make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "mp4"),
+ make_pair("bbb_44100hz_2ch_128kbps_aac_5mins.mp4", "3gpp"),
+ make_pair("bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", "3gpp"),
+ make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "3gpp")));
+
+int main(int argc, char **argv) {
+ gEnv = new BenchmarkTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGV("Test result = %d\n", status);
+ }
+ return status;
+}
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index e2cd4e3..c0967d9 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -25,12 +25,14 @@
"ServiceUtilities.cpp",
"TimeCheck.cpp",
],
+ static_libs: [
+ "libc_malloc_debug_backtrace",
+ ],
shared_libs: [
"libbinder",
"libcutils",
"liblog",
"libutils",
- "libmemunreachable",
"libhidlbase",
"android.hardware.graphics.bufferqueue@1.0",
"android.hidl.token@1.0-utils",
@@ -44,16 +46,10 @@
"-Werror",
],
- product_variables: {
- product_is_iot: {
- cflags: ["-DTARGET_ANDROID_THINGS"],
- },
- },
-
- include_dirs: [
- // For android_mallopt definitions.
- "bionic/libc/private"
+ header_libs: [
+ "bionic_libc_platform_headers",
],
+
local_include_dirs: ["include"],
export_include_dirs: ["include"],
}
diff --git a/media/utils/MemoryLeakTrackUtil.cpp b/media/utils/MemoryLeakTrackUtil.cpp
index 2988b52..6166859 100644
--- a/media/utils/MemoryLeakTrackUtil.cpp
+++ b/media/utils/MemoryLeakTrackUtil.cpp
@@ -22,7 +22,7 @@
#include "media/MemoryLeakTrackUtil.h"
#include <sstream>
-#include <bionic_malloc.h>
+#include <bionic/malloc.h>
/*
* The code here originally resided in MediaPlayerService.cpp
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index bc8fff6..02141a8 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -179,18 +179,7 @@
// IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
bool ok = PermissionCache::checkCallingPermission(sModifyDefaultAudioEffectsAllowed);
-#ifdef TARGET_ANDROID_THINGS
- if (!ok) {
- // Use a secondary permission on Android Things to allow a more lenient level of protection.
- static const String16 sModifyDefaultAudioEffectsAndroidThingsAllowed(
- "com.google.android.things.permission.MODIFY_DEFAULT_AUDIO_EFFECTS");
- ok = PermissionCache::checkCallingPermission(
- sModifyDefaultAudioEffectsAndroidThingsAllowed);
- }
- if (!ok) ALOGE("com.google.android.things.permission.MODIFY_DEFAULT_AUDIO_EFFECTS");
-#else
if (!ok) ALOGE("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS");
-#endif
return ok;
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index bcd351d..3f4a24e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6354,7 +6354,9 @@
}
}
// compute volume for this track
- processVolume_l(track, last);
+ if (track->isReady()) { // check ready to prevent premature start.
+ processVolume_l(track, last);
+ }
}
// make sure the pause/flush/resume sequence is executed in the right order.
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index fe2eaee..f755fcd 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -79,7 +79,10 @@
}
}
- if (isPlaybackThread && (getFlags() & flags) != flags) {
+ const uint32_t mustMatchOutputFlags =
+ AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ if (isPlaybackThread && (((getFlags() ^ flags) & mustMatchOutputFlags)
+ || (getFlags() & flags) != flags)) {
return false;
}
// The only input flag that is allowed to be different is the fast flag.
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
index 6e72f2a..885b5fa 100644
--- a/services/audiopolicy/engine/config/Android.bp
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -3,7 +3,6 @@
export_include_dirs: ["include"],
include_dirs: [
"external/libxml2/include",
- "external/icu/icu4c/source/common",
],
srcs: [
"src/EngineConfig.cpp",
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index a6cda20..90939ce 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -29,7 +29,6 @@
#include <utils/Log.h>
#include <cutils/properties.h>
#include <binder/IPCThreadState.h>
-#include <binder/ActivityManager.h>
#include <binder/PermissionController.h>
#include <binder/IResultReceiver.h>
#include <utils/String16.h>
@@ -844,28 +843,26 @@
// ----------- AudioPolicyService::UidPolicy implementation ----------
void AudioPolicyService::UidPolicy::registerSelf() {
- ActivityManager am;
- am.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
+ status_t res = mAm.linkToDeath(this);
+ mAm.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
| ActivityManager::UID_OBSERVER_IDLE
| ActivityManager::UID_OBSERVER_ACTIVE
| ActivityManager::UID_OBSERVER_PROCSTATE,
ActivityManager::PROCESS_STATE_UNKNOWN,
String16("audioserver"));
- status_t res = am.linkToDeath(this);
if (!res) {
Mutex::Autolock _l(mLock);
mObserverRegistered = true;
} else {
ALOGE("UidPolicy::registerSelf linkToDeath failed: %d", res);
- am.unregisterUidObserver(this);
+ mAm.unregisterUidObserver(this);
}
}
void AudioPolicyService::UidPolicy::unregisterSelf() {
- ActivityManager am;
- am.unlinkToDeath(this);
- am.unregisterUidObserver(this);
+ mAm.unlinkToDeath(this);
+ mAm.unregisterUidObserver(this);
Mutex::Autolock _l(mLock);
mObserverRegistered = false;
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index e467f70..74aea0d 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -23,6 +23,7 @@
#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/SortedVector.h>
+#include <binder/ActivityManager.h>
#include <binder/BinderService.h>
#include <binder/IUidObserver.h>
#include <system/audio.h>
@@ -387,6 +388,7 @@
wp<AudioPolicyService> mService;
Mutex mLock;
+ ActivityManager mAm;
bool mObserverRegistered;
std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids;
std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids;
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 1c1f5e6..b26398e 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -86,9 +86,7 @@
"libfmq",
"libgui",
"libhardware",
- "libhwbinder",
"libhidlbase",
- "libhidltransport",
"libjpeg",
"libmedia_omx",
"libmemunreachable",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 2f88957..9ceb5bf 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2611,14 +2611,13 @@
void CameraService::UidPolicy::registerSelf() {
Mutex::Autolock _l(mUidLock);
- ActivityManager am;
if (mRegistered) return;
- am.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
+ status_t res = mAm.linkToDeath(this);
+ mAm.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE
| ActivityManager::UID_OBSERVER_IDLE
| ActivityManager::UID_OBSERVER_ACTIVE | ActivityManager::UID_OBSERVER_PROCSTATE,
ActivityManager::PROCESS_STATE_UNKNOWN,
String16("cameraserver"));
- status_t res = am.linkToDeath(this);
if (res == OK) {
mRegistered = true;
ALOGV("UidPolicy: Registered with ActivityManager");
@@ -2628,9 +2627,8 @@
void CameraService::UidPolicy::unregisterSelf() {
Mutex::Autolock _l(mUidLock);
- ActivityManager am;
- am.unregisterUidObserver(this);
- am.unlinkToDeath(this);
+ mAm.unregisterUidObserver(this);
+ mAm.unlinkToDeath(this);
mRegistered = false;
mActiveUids.clear();
ALOGV("UidPolicy: Unregistered with ActivityManager");
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 065157d..cf93a41 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -25,6 +25,7 @@
#include <cutils/multiuser.h>
#include <utils/Vector.h>
#include <utils/KeyedVector.h>
+#include <binder/ActivityManager.h>
#include <binder/AppOpsManager.h>
#include <binder/BinderService.h>
#include <binder/IAppOpsCallback.h>
@@ -564,6 +565,7 @@
Mutex mUidLock;
bool mRegistered;
+ ActivityManager mAm;
wp<CameraService> mService;
std::unordered_set<uid_t> mActiveUids;
// Monitored uid map to cached procState and refCount pair
diff --git a/services/camera/libcameraservice/tests/Android.mk b/services/camera/libcameraservice/tests/Android.mk
index b4e7c32..ec5e876 100644
--- a/services/camera/libcameraservice/tests/Android.mk
+++ b/services/camera/libcameraservice/tests/Android.mk
@@ -23,7 +23,6 @@
libcameraservice \
libhidlbase \
liblog \
- libhidltransport \
libcamera_client \
libcamera_metadata \
libutils \
diff --git a/services/mediacodec/Android.bp b/services/mediacodec/Android.bp
index 99a6d6b..36042a4 100644
--- a/services/mediacodec/Android.bp
+++ b/services/mediacodec/Android.bp
@@ -10,8 +10,6 @@
"libavservices_minijail",
"libbase",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libmedia_codecserviceregistrant",
],
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index ecc8408..d878d72 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -39,9 +39,7 @@
libbase \
libavservices_minijail_vendor \
libcutils \
- libhwbinder \
libhidlbase \
- libhidltransport \
libstagefright_omx \
libstagefright_xmlparser \
android.hardware.media.omx@1.0 \
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
index 227a29d..3e94596 100644
--- a/services/mediadrm/Android.mk
+++ b/services/mediadrm/Android.mk
@@ -27,7 +27,6 @@
libutils \
libhidlbase \
libhidlmemory \
- libhidltransport \
android.hardware.drm@1.0 \
android.hardware.drm@1.1 \
android.hardware.drm@1.2
diff --git a/services/oboeservice/Android.mk b/services/oboeservice/Android.mk
index 3d5f140..5e4cd39 100644
--- a/services/oboeservice/Android.mk
+++ b/services/oboeservice/Android.mk
@@ -14,7 +14,6 @@
$(call include-path-for, audio-utils) \
frameworks/native/include \
system/core/base/include \
- $(TOP)/frameworks/native/media/libaaudio/include/include \
$(TOP)/frameworks/av/media/libaaudio/include \
$(TOP)/frameworks/av/media/utils/include \
frameworks/native/include \
@@ -47,7 +46,7 @@
LOCAL_CFLAGS += -Wall -Werror
LOCAL_SHARED_LIBRARIES := \
- libaaudio \
+ libaaudio_internal \
libaudioflinger \
libaudioclient \
libbinder \
diff --git a/services/soundtrigger/Android.bp b/services/soundtrigger/Android.bp
index 3f02f48..1bbd591 100644
--- a/services/soundtrigger/Android.bp
+++ b/services/soundtrigger/Android.bp
@@ -31,10 +31,8 @@
"libaudioutils",
"libmediautils",
- "libhwbinder",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
"libbase",
"libaudiohal",
"libaudiohal_deathhandler",
diff --git a/tools/resampler_tools/Android.bp b/tools/resampler_tools/Android.bp
new file mode 100644
index 0000000..7549359
--- /dev/null
+++ b/tools/resampler_tools/Android.bp
@@ -0,0 +1,15 @@
+// Copyright 2005 The Android Open Source Project
+//
+// Android.mk for resampler_tools
+//
+
+cc_binary_host {
+ name: "fir",
+
+ srcs: ["fir.cpp"],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+}
diff --git a/tools/resampler_tools/Android.mk b/tools/resampler_tools/Android.mk
deleted file mode 100644
index bba5199..0000000
--- a/tools/resampler_tools/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-#
-# Android.mk for resampler_tools
-#
-
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- fir.cpp
-
-LOCAL_MODULE := fir
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_HOST_EXECUTABLE)