Merge "AmrnbEncoderTest: Added AndroidTest.xml to run test with atest"
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 4a31953..65d7a39 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1295,6 +1295,8 @@
mCallback->onError(err2, ACTION_CODE_FATAL);
return;
}
+ // We're not starting after flush.
+ (void)mSentConfigAfterResume.test_and_set();
err2 = mChannel->start(inputFormat, outputFormat);
if (err2 != OK) {
mCallback->onError(err2, ACTION_CODE_FATAL);
@@ -1523,18 +1525,26 @@
}
void CCodec::signalResume() {
- auto setResuming = [this] {
+ std::shared_ptr<Codec2Client::Component> comp;
+ auto setResuming = [this, &comp] {
Mutexed<State>::Locked state(mState);
if (state->get() != FLUSHED) {
return UNKNOWN_ERROR;
}
state->set(RESUMING);
+ comp = state->comp;
return OK;
};
if (tryAndReportOnError(setResuming) != OK) {
return;
}
+ mSentConfigAfterResume.clear();
+ {
+ Mutexed<Config>::Locked config(mConfig);
+ config->queryConfiguration(comp);
+ }
+
(void)mChannel->start(nullptr, nullptr);
{
@@ -1730,7 +1740,7 @@
// handle configuration changes in work done
Mutexed<Config>::Locked config(mConfig);
- bool changed = false;
+ bool changed = !mSentConfigAfterResume.test_and_set();
Config::Watcher<C2StreamInitDataInfo::output> initData =
config->watch<C2StreamInitDataInfo::output>();
if (!work->worklets.empty()
@@ -1762,7 +1772,9 @@
++stream;
}
- changed = config->updateConfiguration(updates, config->mOutputDomain);
+ if (config->updateConfiguration(updates, config->mOutputDomain)) {
+ changed = true;
+ }
// copy standard infos to graphic buffers if not already present (otherwise, we
// may overwrite the actual intermediate value with a final value)
diff --git a/media/codec2/sfplugin/CCodec.h b/media/codec2/sfplugin/CCodec.h
index b0b3c4f..a580d1d 100644
--- a/media/codec2/sfplugin/CCodec.h
+++ b/media/codec2/sfplugin/CCodec.h
@@ -17,6 +17,7 @@
#ifndef C_CODEC_H_
#define C_CODEC_H_
+#include <atomic>
#include <chrono>
#include <list>
#include <memory>
@@ -175,6 +176,7 @@
typedef CCodecConfig Config;
Mutexed<Config> mConfig;
Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue;
+ std::atomic_flag mSentConfigAfterResume;
friend class CCodecCallbackImpl;
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 375ce17..5f969db 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1277,6 +1277,24 @@
std::unique_ptr<C2Work> work,
const sp<AMessage> &outputFormat,
const C2StreamInitDataInfo::output *initData) {
+ if (outputFormat != nullptr) {
+ Mutexed<Output>::Locked output(mOutput);
+ ALOGD("[%s] onWorkDone: output format changed to %s",
+ mName, outputFormat->debugString().c_str());
+ output->buffers->setFormat(outputFormat);
+
+ AString mediaType;
+ if (outputFormat->findString(KEY_MIME, &mediaType)
+ && mediaType == MIMETYPE_AUDIO_RAW) {
+ int32_t channelCount;
+ int32_t sampleRate;
+ if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount)
+ && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
+ output->buffers->updateSkipCutBuffer(sampleRate, channelCount);
+ }
+ }
+ }
+
if ((work->input.ordinal.frameIndex - mFirstValidFrameIndex.load()).peek() < 0) {
// Discard frames from previous generation.
ALOGD("[%s] Discard frames from previous generation.", mName);
@@ -1454,24 +1472,6 @@
}
}
- if (outputFormat != nullptr) {
- Mutexed<Output>::Locked output(mOutput);
- ALOGD("[%s] onWorkDone: output format changed to %s",
- mName, outputFormat->debugString().c_str());
- output->buffers->setFormat(outputFormat);
-
- AString mediaType;
- if (outputFormat->findString(KEY_MIME, &mediaType)
- && mediaType == MIMETYPE_AUDIO_RAW) {
- int32_t channelCount;
- int32_t sampleRate;
- if (outputFormat->findInt32(KEY_CHANNEL_COUNT, &channelCount)
- && outputFormat->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
- output->buffers->updateSkipCutBuffer(sampleRate, channelCount);
- }
- }
- }
-
int32_t flags = 0;
if (worklet->output.flags & C2FrameData::FLAG_END_OF_STREAM) {
flags |= MediaCodec::BUFFER_FLAG_EOS;
diff --git a/media/libaudioprocessing/Android.bp b/media/libaudioprocessing/Android.bp
index 9b5d58c..e756ada 100644
--- a/media/libaudioprocessing/Android.bp
+++ b/media/libaudioprocessing/Android.bp
@@ -19,6 +19,25 @@
// uncomment to disable NEON on architectures that actually do support NEON, for benchmarking
// "-DUSE_NEON=false",
],
+
+ arch: {
+ x86: {
+ avx2: {
+ cflags: [
+ "-mavx2",
+ "-mfma",
+ ],
+ },
+ },
+ x86_64: {
+ avx2: {
+ cflags: [
+ "-mavx2",
+ "-mfma",
+ ],
+ },
+ },
+ },
}
cc_library_shared {
diff --git a/media/libaudioprocessing/AudioResamplerFirOps.h b/media/libaudioprocessing/AudioResamplerFirOps.h
index 2e4cee3..a3f5ff5 100644
--- a/media/libaudioprocessing/AudioResamplerFirOps.h
+++ b/media/libaudioprocessing/AudioResamplerFirOps.h
@@ -36,13 +36,20 @@
#include <arm_neon.h>
#endif
-#if defined(__SSSE3__) // Should be supported in x86 ABI for both 32 & 64-bit.
+#if defined(__AVX2__) // Should be supported in x86 ABI for both 32 & 64-bit.
+#define USE_AVX2 (true) // Inference AVX2/FMA Intrinsics
#define USE_SSE (true)
+#include <immintrin.h>
+#elif defined(__SSSE3__) // Should be supported in x86 ABI for both 32 & 64-bit.
+#define USE_SSE (true) // Inference SSE Intrinsics
+#define USE_AVX2 (false)
#include <tmmintrin.h>
#else
#define USE_SSE (false)
+#define USE_AVX2(false)
#endif
+
template<typename T, typename U>
struct is_same
{
diff --git a/media/libaudioprocessing/AudioResamplerFirProcessSSE.h b/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
index 30233b5..1c16bc4 100644
--- a/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
+++ b/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
@@ -80,11 +80,16 @@
posCoef1 = _mm_sub_ps(posCoef1, posCoef);
negCoef = _mm_sub_ps(negCoef, negCoef1);
+
+ #if USE_AVX2
+ posCoef = _mm_fmadd_ps(posCoef1, interp, posCoef);
+ negCoef = _mm_fmadd_ps(negCoef, interp, negCoef1);
+ #else
posCoef1 = _mm_mul_ps(posCoef1, interp);
negCoef = _mm_mul_ps(negCoef, interp);
-
posCoef = _mm_add_ps(posCoef1, posCoef);
negCoef = _mm_add_ps(negCoef, negCoef1);
+ #endif //USE_AVX2
}
switch (CHANNELS) {
case 1: {
@@ -94,11 +99,17 @@
sN += 4;
posSamp = _mm_shuffle_ps(posSamp, posSamp, 0x1B);
+
+ #if USE_AVX2
+ accL = _mm_fmadd_ps(posSamp, posCoef, accL);
+ accL = _mm_fmadd_ps(negSamp, negCoef, accL);
+ #else
posSamp = _mm_mul_ps(posSamp, posCoef);
negSamp = _mm_mul_ps(negSamp, negCoef);
-
accL = _mm_add_ps(accL, posSamp);
accL = _mm_add_ps(accL, negSamp);
+ #endif
+
} break;
case 2: {
__m128 posSamp0 = _mm_loadu_ps(sP);
@@ -114,15 +125,23 @@
__m128 negSampL = _mm_shuffle_ps(negSamp0, negSamp1, 0x88);
__m128 negSampR = _mm_shuffle_ps(negSamp0, negSamp1, 0xDD);
- posSampL = _mm_mul_ps(posSampL, posCoef);
- posSampR = _mm_mul_ps(posSampR, posCoef);
- negSampL = _mm_mul_ps(negSampL, negCoef);
- negSampR = _mm_mul_ps(negSampR, negCoef);
+ #if USE_AVX2
+ accL = _mm_fmadd_ps(posSampL, posCoef, accL);
+ accR = _mm_fmadd_ps(posSampR, posCoef, accR);
+ accL = _mm_fmadd_ps(negSampL, negCoef, accL);
+ accR = _mm_fmadd_ps(negSampR, negCoef, accR);
+ #else
+ posSampL = _mm_mul_ps(posSampL, posCoef);
+ posSampR = _mm_mul_ps(posSampR, posCoef);
+ negSampL = _mm_mul_ps(negSampL, negCoef);
+ negSampR = _mm_mul_ps(negSampR, negCoef);
- accL = _mm_add_ps(accL, posSampL);
- accR = _mm_add_ps(accR, posSampR);
- accL = _mm_add_ps(accL, negSampL);
- accR = _mm_add_ps(accR, negSampR);
+ accL = _mm_add_ps(accL, posSampL);
+ accR = _mm_add_ps(accR, posSampR);
+ accL = _mm_add_ps(accL, negSampL);
+ accR = _mm_add_ps(accR, negSampR);
+ #endif
+
} break;
}
} while (count -= 4);
@@ -144,9 +163,13 @@
outAccum = _mm_hadd_ps(accL, accR);
outAccum = _mm_hadd_ps(outAccum, outAccum);
}
-
+ #if USE_AVX2
+ outSamp = _mm_fmadd_ps(outAccum, vLR,outSamp);
+ #else
outAccum = _mm_mul_ps(outAccum, vLR);
outSamp = _mm_add_ps(outSamp, outAccum);
+ #endif
+
_mm_storel_pi(reinterpret_cast<__m64*>(out), outSamp);
}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
index cc9643d..53feae8 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
@@ -115,8 +115,7 @@
* Setup the high pass filter
*/
LoadConst_Float(0, /* Clear the history, value 0 */
- (LVM_FLOAT *)&pInstance->pData->HPFTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pInstance->pData->HPFTaps, /* Destination */
sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance, /* Initialise the filter */
&pInstance->pData->HPFTaps,
@@ -126,8 +125,7 @@
* Setup the band pass filter
*/
LoadConst_Float(0, /* Clear the history, value 0 */
- (LVM_FLOAT *)&pInstance->pData->BPFTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pInstance->pData->BPFTaps, /* Destination */
sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
&pInstance->pData->BPFTaps,
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
index 86a4ca2..1f0d39b 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
@@ -83,8 +83,7 @@
FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs,
&pPrivate->pFastData->HPTaps, &Coeffs);
LoadConst_Float(0,
- (LVM_FLOAT *)&pPrivate->pFastData->HPTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pPrivate->pFastData->HPTaps,
sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
}
@@ -116,8 +115,7 @@
FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs,
&pPrivate->pFastData->LPTaps, &Coeffs);
LoadConst_Float(0,
- (LVM_FLOAT *)&pPrivate->pFastData->LPTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pPrivate->pFastData->LPTaps,
sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
}
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
index 8b38a16..586539f 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
@@ -60,12 +60,10 @@
*/
LoadConst_Float(0,
- (LVM_FLOAT *)&pLVREV_Private->pFastData->HPTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pLVREV_Private->pFastData->HPTaps,
2);
LoadConst_Float(0,
- (LVM_FLOAT *)&pLVREV_Private->pFastData->LPTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pLVREV_Private->pFastData->LPTaps,
2);
if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
{
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
index ecf949d..431b7e3 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
@@ -91,8 +91,7 @@
Coeffs.B2 = (LVM_FLOAT)-pEqualiserCoefTable[Offset].B2;
LoadConst_Float((LVM_INT16)0, /* Value */
- (LVM_FLOAT *)&pData->EqualiserBiquadTaps, /* Destination Cast to void:\
- no dereferencing in function*/
+ (LVM_FLOAT *)&pData->EqualiserBiquadTaps, /* Destination */
/* Number of words */
(LVM_UINT16)(sizeof(pData->EqualiserBiquadTaps) / sizeof(LVM_FLOAT)));
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
index 68a7120..d0e6e09 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
@@ -109,8 +109,7 @@
Coeffs.B2 = (LVM_FLOAT)-pReverbCoefTable[Offset].B2;
LoadConst_Float(0, /* Value */
- (LVM_FLOAT *)&pData->ReverbBiquadTaps, /* Destination Cast to void:
- no dereferencing in function*/
+ (LVM_FLOAT *)&pData->ReverbBiquadTaps, /* Destination */
/* Number of words */
(LVM_UINT16)(sizeof(pData->ReverbBiquadTaps) / sizeof(LVM_FLOAT)));
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
index 9cfc9a0..7fd8444 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
@@ -87,8 +87,7 @@
/* Clear the taps */
LoadConst_Float(0, /* Value */
- (LVM_FLOAT *)&pData->SEBiquadTapsMid, /* Destination Cast to void:\
- no dereferencing in function*/
+ (LVM_FLOAT *)&pData->SEBiquadTapsMid, /* Destination */
/* Number of words */
(LVM_UINT16)(sizeof(pData->SEBiquadTapsMid) / sizeof(LVM_FLOAT)));
@@ -115,8 +114,7 @@
/* Clear the taps */
LoadConst_Float(0, /* Value */
- (LVM_FLOAT *)&pData->SEBiquadTapsSide, /* Destination Cast to void:\
- no dereferencing in function*/
+ (LVM_FLOAT *)&pData->SEBiquadTapsSide, /* Destination */
/* Number of words */
(LVM_UINT16)(sizeof(pData->SEBiquadTapsSide) / sizeof(LVM_FLOAT)));
/* Callbacks */
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 7689691..9e85475 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -276,7 +276,7 @@
std::shared_ptr<std::list<sp<ExtractorPlugin>>> newList(new std::list<sp<ExtractorPlugin>>());
- android_namespace_t *mediaNs = android_get_exported_namespace("com.android.media");
+ android_namespace_t *mediaNs = android_get_exported_namespace("com_android_media");
if (mediaNs != NULL) {
const android_dlextinfo dlextinfo = {
.flags = ANDROID_DLEXT_USE_NAMESPACE,
diff --git a/media/libstagefright/codecs/amrwbenc/test/AndroidTest.xml b/media/libstagefright/codecs/amrwbenc/test/AndroidTest.xml
new file mode 100644
index 0000000..46f147c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Test module config for Amr-wb Encoder unit test">
+ <option name="test-suite-tag" value="AmrwbEncoderTest" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="AmrwbEncoderTest->/data/local/tmp/AmrwbEncoderTest" />
+ <option name="push-file"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip?unzip=true"
+ value="/data/local/tmp/AmrwbEncoderTestRes/" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="AmrwbEncoderTest" />
+ <option name="native-test-flag" value="-P /data/local/tmp/AmrwbEncoderTestRes/" />
+ </test>
+</configuration>
diff --git a/media/libstagefright/codecs/amrwbenc/test/README.md b/media/libstagefright/codecs/amrwbenc/test/README.md
index ea2135f..78762cb 100644
--- a/media/libstagefright/codecs/amrwbenc/test/README.md
+++ b/media/libstagefright/codecs/amrwbenc/test/README.md
@@ -22,13 +22,18 @@
adb push ${OUT}/data/nativetest/AmrwbEncoderTest/AmrwbEncoderTest /data/local/tmp/
```
-The resource file for the tests is taken from [here](https://drive.google.com/drive/folders/13cM4tAaVFrmr-zGFqaAzFBbKs75pnm9b). Push these files into device for testing.
-Download amr-wb_encoder folder and push all the files in this folder to /data/local/tmp/ on the device.
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip). Download, unzip and push these files into device for testing.
+
```
-adb push amr-wb_encoder/. /data/local/tmp/
+adb push AmrwbEncoderTestRes/. /data/local/tmp/
```
usage: AmrwbEncoderTest -P \<path_to_folder\>
```
-adb shell /data/local/tmp/AmrwbEncoderTest -P /data/local/tmp/
+adb shell /data/local/tmp/AmrwbEncoderTest -P /data/local/tmp/AmrwbEncoderTestRes/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest AmrwbEncoderTest -- --enable-module-dynamic-download=true
```
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/AndroidTest.xml b/media/libstagefright/codecs/m4v_h263/dec/test/AndroidTest.xml
new file mode 100755
index 0000000..47e10ca
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Test module config for Mpeg4H263 Decoder unit tests">
+ <option name="test-suite-tag" value="Mpeg4H263DecoderTest" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="Mpeg4H263DecoderTest->/data/local/tmp/Mpeg4H263DecoderTest" />
+ <option name="push-file"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder.zip?unzip=true"
+ value="/data/local/tmp/Mpeg4H263DecoderTestRes/" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="Mpeg4H263DecoderTest" />
+ <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263DecoderTestRes/" />
+ </test>
+</configuration>
diff --git a/media/libstagefright/codecs/m4v_h263/dec/test/README.md b/media/libstagefright/codecs/m4v_h263/dec/test/README.md
index 3f46529..7e4aea1 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/test/README.md
+++ b/media/libstagefright/codecs/m4v_h263/dec/test/README.md
@@ -22,13 +22,18 @@
adb push ${OUT}/data/nativetest/Mpeg4H263DecoderTest/Mpeg4H263DecoderTest /data/local/tmp/
```
-The resource file for the tests is taken from [here](https://drive.google.com/drive/folders/13cM4tAaVFrmr-zGFqaAzFBbKs75pnm9b).
-Download Mpeg4H263Decoder folder and push all the files in this folder to /data/local/tmp/ on the device for testing.
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder.zip). Download, unzip and push these files into device for testing.
+
```
-adb push Mpeg4H263Decoder/. /data/local/tmp/
+adb push Mpeg4H263Decoder /data/local/tmp/
```
usage: Mpeg4H263DecoderTest -P \<path_to_folder\>
```
-adb shell /data/local/tmp/Mpeg4H263DecoderTest -P /data/local/tmp/
+adb shell /data/local/tmp/Mpeg4H263DecoderTest -P /data/local/tmp/Mpeg4H263Decoder/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest Mpeg4H263DecoderTest -- --enable-module-dynamic-download=true
```
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp b/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
new file mode 100644
index 0000000..b9a8117
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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: "Mpeg4H263EncoderTest",
+ gtest: true,
+
+ srcs : [ "Mpeg4H263EncoderTest.cpp" ],
+
+ shared_libs: [
+ "libutils",
+ "liblog",
+ ],
+
+ static_libs: [
+ "libstagefright_m4vh263enc",
+ ],
+
+ cflags: [
+ "-DOSCL_IMPORT_REF=",
+ "-Wall",
+ "-Werror",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ "unsigned-integer-overflow",
+ ],
+ cfi: true,
+ },
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml b/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml
new file mode 100644
index 0000000..5218932
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Test module config for MPEG4H263 encoder unit tests">
+ <option name="test-suite-tag" value="Mpeg4H263EncoderTest" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="Mpeg4H263EncoderTest->/data/local/tmp/Mpeg4H263EncoderTest/" />
+ <option name="push-file"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true"
+ value="/data/local/tmp/Mpeg4H263EncoderTestRes/" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="Mpeg4H263EncoderTest" />
+ <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263EncoderTestRes/" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
new file mode 100644
index 0000000..78c705a
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2020 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 "Mpeg4H263EncoderTest"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "mp4enc_api.h"
+
+#include "Mpeg4H263EncoderTestEnvironment.h"
+
+#define ENCODED_FILE "/data/local/tmp/Mpeg4H263Output"
+
+// assuming a worst case compression of 2X
+constexpr int16_t kCompressionRatio = 2;
+constexpr int8_t kIDRFrameRefreshIntervalInSec = 1;
+
+static Mpeg4H263EncoderTestEnvironment *gEnv = nullptr;
+
+class Mpeg4H263EncoderTest
+ : public ::testing::TestWithParam<tuple<string, bool, int32_t, int32_t, float, int32_t>> {
+ private:
+ void initEncoderParams();
+
+ public:
+ Mpeg4H263EncoderTest()
+ : mInputBuffer(nullptr),
+ mOutputBuffer(nullptr),
+ mFpInput(nullptr),
+ mFpOutput(nullptr),
+ mEncodeHandle(nullptr),
+ mEncodeControl(nullptr) {}
+
+ ~Mpeg4H263EncoderTest() {
+ if(mFpInput) {
+ fclose(mFpInput);
+ }
+ if(mFpOutput) {
+ fclose(mFpOutput);
+ }
+ if(mInputBuffer) free(mInputBuffer);
+ if(mOutputBuffer) free(mOutputBuffer);
+ if(mEncodeHandle) free(mEncodeHandle);
+ if(mEncodeControl) free(mEncodeControl);
+ }
+
+ void SetUp() override {
+ tuple<string /* fileName */, bool /* isMpeg4 */, int32_t /* frameWidth */,
+ int32_t /* frameHeight */, float /* frameRate */, int32_t /* bitRate */>
+ params = GetParam();
+ mFileName = gEnv->getRes() + get<0>(params);
+ mIsMpeg4 = get<1>(params);
+ mFrameWidth = get<2>(params);
+ mFrameHeight = get<3>(params);
+ mFrameRate = get<4>(params);
+ mBitRate = get<5>(params);
+
+ ASSERT_TRUE(mFrameWidth % 16 == 0) << "Frame Width should be multiple of 16";
+ ASSERT_TRUE(mFrameHeight % 16 == 0) << "Frame Height should be multiple of 16";
+ ASSERT_LE(mFrameWidth, (mIsMpeg4 ? 720 : 352))
+ << "Frame Width <= 720 for Mpeg4 and <= 352 for H263";
+ ASSERT_LE(mFrameHeight, (mIsMpeg4 ? 480 : 288))
+ << "Frame Height <= 480 for Mpeg4 and <= 288 for H263";
+ ASSERT_LE(mFrameRate, 30) << "Frame rate less than or equal to 30";
+ ASSERT_LE(mBitRate, 2048) << "Bit rate less than or equal to 2048 kbps";
+
+ mOutputBufferSize = ( mFrameWidth * mFrameHeight * 3/2 ) / kCompressionRatio;
+ mEncodeHandle = new VideoEncOptions;
+ ASSERT_NE(mEncodeHandle, nullptr) << "Failed to get Video Encoding options object";
+ memset(mEncodeHandle, 0, sizeof(VideoEncOptions));
+ mEncodeControl = new VideoEncControls;
+ ASSERT_NE(mEncodeControl, nullptr) << "Failed to get Video Encoding control object";
+ memset(mEncodeControl, 0, sizeof(VideoEncControls));
+ ASSERT_NO_FATAL_FAILURE(initEncoderParams())
+ << "Failed to get the default Encoding parameters!";
+ }
+
+ int64_t getTotalFrames();
+ void processEncoder(int32_t);
+ bool mIsMpeg4;
+ int32_t mFrameWidth, mFrameHeight, mBitRate;
+ int64_t mOutputBufferSize;
+ float mFrameRate;
+ string mFileName;
+ uint8_t *mInputBuffer, *mOutputBuffer;
+ FILE *mFpInput, *mFpOutput;
+ VideoEncOptions *mEncodeHandle;
+ VideoEncControls *mEncodeControl;
+};
+
+void Mpeg4H263EncoderTest::initEncoderParams() {
+ bool status = PVGetDefaultEncOption(mEncodeHandle, 0);
+ ASSERT_TRUE(status);
+
+ mEncodeHandle->rcType = VBR_1;
+ mEncodeHandle->vbvDelay = 5.0f;
+ mEncodeHandle->profile_level = CORE_PROFILE_LEVEL2;
+ mEncodeHandle->packetSize = 32;
+ mEncodeHandle->rvlcEnable = PV_OFF;
+ mEncodeHandle->numLayers = 1;
+ mEncodeHandle->timeIncRes = 1000;
+ mEncodeHandle->iQuant[0] = 15;
+ mEncodeHandle->pQuant[0] = 12;
+ mEncodeHandle->quantType[0] = 0;
+ mEncodeHandle->noFrameSkipped = PV_OFF;
+ mEncodeHandle->numIntraMB = 0;
+ mEncodeHandle->sceneDetect = PV_ON;
+ mEncodeHandle->searchRange = 16;
+ mEncodeHandle->mv8x8Enable = PV_OFF;
+ mEncodeHandle->gobHeaderInterval = 0;
+ mEncodeHandle->useACPred = PV_ON;
+ mEncodeHandle->intraDCVlcTh = 0;
+ if(!mIsMpeg4) {
+ mEncodeHandle->encMode = H263_MODE;
+ } else {
+ mEncodeHandle->encMode = COMBINE_MODE_WITH_ERR_RES;
+ }
+ mEncodeHandle->encWidth[0] = mFrameWidth;
+ mEncodeHandle->encHeight[0] = mFrameHeight;
+ mEncodeHandle->encFrameRate[0] = mFrameRate;
+ mEncodeHandle->bitRate[0] = mBitRate * 1024;
+ mEncodeHandle->tickPerSrc = mEncodeHandle->timeIncRes / mFrameRate;
+ if (kIDRFrameRefreshIntervalInSec == 0) {
+ // All I frames.
+ mEncodeHandle->intraPeriod = 1;
+ } else {
+ mEncodeHandle->intraPeriod = (kIDRFrameRefreshIntervalInSec * mFrameRate);
+ }
+}
+
+int64_t Mpeg4H263EncoderTest::getTotalFrames() {
+ int32_t frameSize = (mFrameWidth * mFrameHeight * 3) / 2;
+ struct stat buf;
+ stat(mFileName.c_str(), &buf);
+ size_t fileSize = buf.st_size;
+ int64_t totalFrames = (int64_t)(fileSize/frameSize);
+ return totalFrames;
+}
+
+void Mpeg4H263EncoderTest::processEncoder(int32_t numFramesToEncode) {
+ bool status;
+ int64_t numEncodedFrames = 0;
+ int32_t bytesRead;
+ int32_t frameSize = (mFrameWidth * mFrameHeight * 3) / 2;
+ while(numFramesToEncode != 0) {
+ bytesRead = fread(mInputBuffer, 1, frameSize, mFpInput);
+ // End of file.
+ if (bytesRead != frameSize) {
+ break;
+ }
+
+ VideoEncFrameIO videoIn, videoOut;
+ videoIn.height = mFrameHeight;
+ videoIn.pitch = mFrameWidth;
+ videoIn.timestamp = (numEncodedFrames * 1000) / mFrameRate; // in ms.
+ videoIn.yChan = mInputBuffer;
+ videoIn.uChan = videoIn.yChan + videoIn.height * videoIn.pitch;
+ videoIn.vChan = videoIn.uChan + ((videoIn.height * videoIn.pitch) >> 2);
+ uint32_t modTimeMs = 0;
+ int32_t dataLength = mOutputBufferSize;
+ int32_t nLayer = 0;
+ status = PVEncodeVideoFrame(mEncodeControl, &videoIn, &videoOut, &modTimeMs, mOutputBuffer,
+ &dataLength, &nLayer);
+ ASSERT_TRUE(status) << "Failed to Encode: " << mFileName;
+
+ MP4HintTrack hintTrack;
+ status = PVGetHintTrack(mEncodeControl, &hintTrack);
+ ASSERT_TRUE(status) << "Failed to get hint track!";
+ UChar *overrunBuffer = PVGetOverrunBuffer(mEncodeControl);
+ ASSERT_EQ(overrunBuffer, nullptr) << "Overrun of buffer!";
+
+ int64_t numBytes = fwrite(mOutputBuffer, 1, dataLength, mFpOutput);
+ ASSERT_EQ(numBytes, dataLength) << "Failed to write to the output file!";
+ numEncodedFrames++;
+ numFramesToEncode--;
+ }
+}
+
+TEST_P(Mpeg4H263EncoderTest, EncodeTest) {
+ mInputBuffer = (uint8_t *)malloc((mFrameWidth * mFrameWidth * 3) / 2);
+ ASSERT_NE(mInputBuffer, nullptr) << "Failed to allocate the input buffer!";
+
+ mOutputBuffer = (uint8_t *)malloc(mOutputBufferSize);
+ ASSERT_NE(mOutputBuffer, nullptr) << "Failed to allocate the output buffer!";
+
+ mFpInput = fopen(mFileName.c_str(), "rb");
+ ASSERT_NE(mFpInput, nullptr) << "Failed to open the input file: " << mFileName;
+
+ mFpOutput = fopen(ENCODED_FILE, "wb");
+ ASSERT_NE(mFpOutput, nullptr) << "Failed to open the output file:" << ENCODED_FILE;
+
+ bool status = PVInitVideoEncoder(mEncodeControl, mEncodeHandle);
+ ASSERT_TRUE(status) << "Failed to initialize the encoder!";
+
+ // Get VOL header.
+ int32_t size = mOutputBufferSize;
+ status = PVGetVolHeader(mEncodeControl, mOutputBuffer, &size, 0);
+ ASSERT_TRUE(status) << "Failed to get the VOL header!";
+
+ // Write the VOL header on the first frame.
+ int32_t numBytes = fwrite(mOutputBuffer, 1, size, mFpOutput);
+ ASSERT_EQ(numBytes, size) << "Failed to write the VOL header!";
+
+ int64_t totalFrames = getTotalFrames();
+ ASSERT_NO_FATAL_FAILURE(processEncoder(totalFrames)) << "Failed to Encode: " << mFileName;
+ status = PVCleanUpVideoEncoder(mEncodeControl);
+ ASSERT_TRUE(status) << "Failed to clean up the encoder resources!";
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EncodeTest, Mpeg4H263EncoderTest,
+ ::testing::Values(
+ make_tuple("bbb_352x288_420p_30fps_32frames.yuv", false, 352, 288, 25, 1024),
+ make_tuple("bbb_352x288_420p_30fps_32frames.yuv", true, 352, 288, 25, 1024),
+ make_tuple("bbb_352x288_420p_30fps_32frames.yuv", false, 176, 144, 25, 1024),
+ make_tuple("bbb_352x288_420p_30fps_32frames.yuv", true, 176, 144, 25, 1024),
+ make_tuple("football_qvga.yuv", false, 352, 288, 25, 1024),
+ make_tuple("football_qvga.yuv", true, 352, 288, 25, 1024),
+ make_tuple("football_qvga.yuv", false, 176, 144, 30, 1024),
+ make_tuple("football_qvga.yuv", true, 176, 144, 30, 1024)));
+
+int32_t main(int argc, char **argv) {
+ gEnv = new Mpeg4H263EncoderTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ uint8_t status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGI("Encoder Test Result = %d\n", status);
+ }
+ return status;
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
new file mode 100644
index 0000000..7ee36e0
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 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 __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
+#define __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class Mpeg4H263EncoderTestEnvironment : public::testing::Environment {
+ public:
+ Mpeg4H263EncoderTestEnvironment() : res("/data/local/tmp/Mpeg4H263EncoderTest/") {}
+
+ // Parses the command line arguments
+ int initFromOptions(int argc, char **argv);
+
+ void setRes(const char *_res) { res = _res; }
+
+ const string getRes() const { return res; }
+
+ private:
+ string res;
+};
+
+int Mpeg4H263EncoderTestEnvironment::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 // __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/README.md b/media/libstagefright/codecs/m4v_h263/enc/test/README.md
new file mode 100644
index 0000000..25de878
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/README.md
@@ -0,0 +1,38 @@
+## Media Testing ##
+---
+
+#### Mpeg4H263Encoder :
+The Mpeg4H263Encoder Test Suite validates the Mpeg4 and H263 encoder available in libstagefright.
+Run the following steps to build the test suite:
+```
+m Mpeg4H263EncoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/Mpeg4H263EncoderTest/Mpeg4H263EncoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/Mpeg4H263EncoderTest/Mpeg4H263EncoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip ) Download, unzip and push these files into device for testing.
+
+```
+adb push Mpeg4H263Encoder/. /data/local/tmp/
+```
+
+usage: Mpeg4H263EncoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/Mpeg4H263EncoderTest -P /data/local/tmp/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest Mpeg4H263EncoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/codecs/mp3dec/test/AndroidTest.xml b/media/libstagefright/codecs/mp3dec/test/AndroidTest.xml
new file mode 100644
index 0000000..7ff9732
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Test module config for Mp3 Decoder unit test">
+ <option name="test-suite-tag" value="Mp3DecoderTest" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="Mp3DecoderTest->/data/local/tmp/Mp3DecoderTest" />
+ <option name="push-file"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest.zip?unzip=true"
+ value="/data/local/tmp/Mp3DecoderTestRes/" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="Mp3DecoderTest" />
+ <option name="native-test-flag" value="-P /data/local/tmp/Mp3DecoderTestRes/" />
+ </test>
+</configuration>
diff --git a/media/libstagefright/codecs/mp3dec/test/README.md b/media/libstagefright/codecs/mp3dec/test/README.md
index 019239e..f59fec7 100644
--- a/media/libstagefright/codecs/mp3dec/test/README.md
+++ b/media/libstagefright/codecs/mp3dec/test/README.md
@@ -22,13 +22,18 @@
adb push ${OUT}/data/nativetest/Mp3DecoderTest/Mp3DecoderTest /data/local/tmp/
```
-The resource file for the tests is taken from [here](https://drive.google.com/drive/folders/13cM4tAaVFrmr-zGFqaAzFBbKs75pnm9b). Push these files into device for testing.
-Download mp3 folder and push all the files in this folder to /data/local/tmp/ on the device.
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest.zip). Download, unzip and push these files into device for testing.
+
```
-adb push mp3/. /data/local/tmp/
+adb push Mp3DecoderTestRes/. /data/local/tmp/
```
usage: Mp3DecoderTest -P \<path_to_folder\>
```
-adb shell /data/local/tmp/Mp3DecoderTest -P /data/local/tmp/
+adb shell /data/local/tmp/Mp3DecoderTest -P /data/local/tmp/Mp3DecoderTestRes/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest Mp3DecoderTest -- --enable-module-dynamic-download=true
```
diff --git a/media/libstagefright/flac/dec/test/Android.bp b/media/libstagefright/flac/dec/test/Android.bp
new file mode 100644
index 0000000..70ca80a
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/Android.bp
@@ -0,0 +1,50 @@
+/*
+ * 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: "FlacDecoderTest",
+ gtest: true,
+
+ srcs: [
+ "FlacDecoderTest.cpp",
+ ],
+
+ shared_libs: [
+ "liblog",
+ ],
+
+ static_libs: [
+ "libstagefright_flacdec",
+ "libFLAC",
+ ],
+
+ header_libs: [
+ "libstagefright_foundation_headers",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ },
+}
diff --git a/media/libstagefright/flac/dec/test/AndroidTest.xml b/media/libstagefright/flac/dec/test/AndroidTest.xml
new file mode 100644
index 0000000..bebba8e
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Test module config for flac decoder unit tests">
+ <option name="test-suite-tag" value="FlacDecoderTest" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="FlacDecoderTest->/data/local/tmp/FlacDecoderTest/" />
+ <option name="push-file"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/flac/dec/test/FlacDecoder.zip?unzip=true"
+ value="/data/local/tmp/FlacDecoderTestRes/" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="FlacDecoderTest" />
+ <option name="native-test-flag" value="-P /data/local/tmp/FlacDecoderTestRes/" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp b/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp
new file mode 100644
index 0000000..34f12db
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp
@@ -0,0 +1,270 @@
+/*
+ * 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 "FlacDecoderTest"
+
+#include <utils/Log.h>
+#include <fstream>
+
+#include "FLACDecoder.h"
+
+#include "FlacDecoderTestEnvironment.h"
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/FlacDecoderOutput.raw"
+#define CODEC_CONFIG_FLAG 32
+
+constexpr uint32_t kMaxCount = 10;
+constexpr int32_t kMaxBlockSize = 4096;
+
+using namespace android;
+
+struct FrameInfo {
+ int32_t bytesCount;
+ uint32_t flags;
+ int64_t timestamp;
+};
+
+static FlacDecoderTestEnvironment *gEnv = nullptr;
+
+class FLACDecoderTest : public ::testing::TestWithParam<tuple<string, string, bool>> {
+ public:
+ FLACDecoderTest() : mFLACDecoder(nullptr), mHasStreamInfo(false), mInputBufferCount(0) {}
+
+ ~FLACDecoderTest() {
+ if (mEleStream.is_open()) mEleStream.close();
+ if (mFLACDecoder) delete mFLACDecoder;
+ mFLACDecoder = nullptr;
+ }
+
+ virtual void SetUp() override {
+ mFLACDecoder = FLACDecoder::Create();
+ ASSERT_NE(mFLACDecoder, nullptr) << "initDecoder: failed to create FLACDecoder";
+ }
+
+ int32_t processFlacDecoder(vector<FrameInfo> Info, int32_t offset, int32_t range,
+ bool outputFloat, ofstream &ostrm);
+
+ FLACDecoder *mFLACDecoder;
+ FLAC__StreamMetadata_StreamInfo mStreamInfo;
+
+ bool mHasStreamInfo;
+ int32_t mInputBufferCount;
+ ifstream mEleStream;
+};
+
+void getInfo(string infoFileName, vector<FrameInfo> &Info) {
+ ifstream eleInfo;
+ eleInfo.open(infoFileName);
+ ASSERT_EQ(eleInfo.is_open(), true);
+ int32_t bytesCount = 0;
+ uint32_t flags = 0;
+ uint32_t timestamp = 0;
+ while (1) {
+ if (!(eleInfo >> bytesCount)) break;
+ eleInfo >> flags;
+ eleInfo >> timestamp;
+ Info.push_back({bytesCount, flags, timestamp});
+ }
+ if (eleInfo.is_open()) eleInfo.close();
+}
+
+int32_t FLACDecoderTest::processFlacDecoder(vector<FrameInfo> Info, int32_t offset, int32_t range,
+ bool outputFloat, ofstream &ostrm) {
+ memset(&mStreamInfo, 0, sizeof(mStreamInfo));
+
+ int32_t frameID = offset;
+ if (range + offset > Info.size() || range < 0 || offset > Info.size() - 1 || offset < 0) {
+ ALOGE("Invalid offset or range or both passed for decoding");
+ ALOGE("offset = %d \t range = %d \t Info.size() = %zu", offset, range, Info.size());
+ return -1;
+ }
+
+ while (1) {
+ if (frameID == Info.size() || frameID == (offset + range)) break;
+ int64_t flags = (Info)[frameID].flags;
+ int32_t size = (Info)[frameID].bytesCount;
+ if (size < 0) {
+ ALOGE("Size for the memory allocation is negative");
+ return -1;
+ }
+ char *data = (char *)malloc(size);
+ if (!data) {
+ ALOGE("Insufficient memory to read frame");
+ return -1;
+ }
+
+ mEleStream.read(data, size);
+ if (mEleStream.gcount() != size) {
+ if (data) {
+ free(data);
+ data = nullptr;
+ }
+ ALOGE("Invalid size read, requested: %d and read: %zu", size, mEleStream.gcount());
+ return -1;
+ }
+
+ if (flags == CODEC_CONFIG_FLAG && mInputBufferCount == 0) {
+ status_t decoderErr = mFLACDecoder->parseMetadata((uint8_t *)data, size);
+ if (decoderErr == WOULD_BLOCK) {
+ ALOGV("process: parseMetadata is Blocking, Continue %d", decoderErr);
+ } else if (decoderErr == OK) {
+ mStreamInfo = mFLACDecoder->getStreamInfo();
+ if (mStreamInfo.sample_rate && mStreamInfo.max_blocksize && mStreamInfo.channels) {
+ mHasStreamInfo = true;
+ }
+ ALOGV("decoder configuration : %d Hz, %d channels, %d samples,"
+ " %d block size",
+ mStreamInfo.sample_rate, mStreamInfo.channels,
+ (int32_t)mStreamInfo.total_samples, mStreamInfo.max_blocksize);
+ } else {
+ ALOGE("FLACDecoder parseMetaData returns error %d", decoderErr);
+ if (data) {
+ free(data);
+ data = nullptr;
+ }
+ return decoderErr;
+ }
+ } else {
+ const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(int16_t);
+ size_t outSize = mHasStreamInfo
+ ? mStreamInfo.max_blocksize * mStreamInfo.channels * sampleSize
+ : kMaxBlockSize * FLACDecoder::kMaxChannels * sampleSize;
+
+ void *out_buf = malloc(outSize);
+ if (!out_buf) {
+ if (data) {
+ free(data);
+ data = nullptr;
+ }
+ ALOGE("Output buffer allocation failed");
+ return -1;
+ }
+ status_t decoderErr = mFLACDecoder->decodeOneFrame((uint8_t *)data, size, out_buf,
+ &outSize, outputFloat);
+ if (decoderErr != OK) {
+ ALOGE("decodeOneFrame returns error %d", decoderErr);
+ if (data) {
+ free(data);
+ data = nullptr;
+ }
+ if (out_buf) {
+ free(out_buf);
+ out_buf = nullptr;
+ }
+ return decoderErr;
+ }
+ ostrm.write(reinterpret_cast<char *>(out_buf), outSize);
+ free(out_buf);
+ out_buf = nullptr;
+ }
+ mInputBufferCount++;
+ frameID++;
+ free(data);
+ data = nullptr;
+ }
+ ALOGV("frameID=%d", frameID);
+ return 0;
+}
+
+TEST_F(FLACDecoderTest, CreateDeleteTest) {
+ if (mFLACDecoder) delete mFLACDecoder;
+ mFLACDecoder = nullptr;
+
+ for (int32_t i = 0; i < kMaxCount; i++) {
+ mFLACDecoder = FLACDecoder::Create();
+ ASSERT_NE(mFLACDecoder, nullptr) << "FLACDecoder Creation Failed";
+ if (mFLACDecoder) delete mFLACDecoder;
+ mFLACDecoder = nullptr;
+ }
+}
+
+TEST_P(FLACDecoderTest, FlushTest) {
+ tuple<string /* InputFileName */, string /* InfoFileName */, bool /* outputfloat */> params =
+ GetParam();
+
+ string inputFileName = gEnv->getRes() + get<0>(params);
+ string infoFileName = gEnv->getRes() + get<1>(params);
+ bool outputFloat = get<2>(params);
+
+ vector<FrameInfo> Info;
+ getInfo(infoFileName, Info);
+
+ mEleStream.open(inputFileName, ifstream::binary);
+ ASSERT_EQ(mEleStream.is_open(), true);
+
+ ofstream ostrm;
+ ostrm.open(OUTPUT_FILE_NAME, std::ofstream::binary);
+ ASSERT_EQ(ostrm.is_open(), true);
+
+ int32_t status = processFlacDecoder(Info, 0, Info.size() / 3, outputFloat, ostrm);
+ ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+ mFLACDecoder->flush();
+ mHasStreamInfo = false;
+ status = processFlacDecoder(Info, (Info.size() / 3), Info.size() - (Info.size() / 3),
+ outputFloat, ostrm);
+ ostrm.close();
+ Info.clear();
+ ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+}
+
+TEST_P(FLACDecoderTest, DecodeTest) {
+ tuple<string /* InputFileName */, string /* InfoFileName */, bool /* outputfloat */> params =
+ GetParam();
+
+ string inputFileName = gEnv->getRes() + get<0>(params);
+ string infoFileName = gEnv->getRes() + get<1>(params);
+ bool outputFloat = get<2>(params);
+
+ vector<FrameInfo> Info;
+ getInfo(infoFileName, Info);
+
+ mEleStream.open(inputFileName, ifstream::binary);
+ ASSERT_EQ(mEleStream.is_open(), true);
+
+ ofstream ostrm;
+ ostrm.open(OUTPUT_FILE_NAME, std::ofstream::binary);
+ ASSERT_EQ(ostrm.is_open(), true);
+
+ int32_t status = processFlacDecoder(Info, 0, Info.size(), outputFloat, ostrm);
+ ostrm.close();
+ Info.clear();
+ ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+}
+
+// TODO: Add remaining tests
+INSTANTIATE_TEST_SUITE_P(
+ FLACDecoderTestAll, FLACDecoderTest,
+ ::testing::Values(make_tuple("bbb_flac_stereo_680kbps_48000hz.flac",
+ "bbb_flac_stereo_680kbps_48000hz.info", true),
+ make_tuple("bbb_flac_stereo_680kbps_48000hz.flac",
+ "bbb_flac_stereo_680kbps_48000hz.info", false),
+ make_tuple("bbb_flac_stereo_600kbps_44100hz.flac",
+ "bbb_flac_stereo_600kbps_44100hz.info", true),
+ make_tuple("bbb_flac_stereo_600kbps_44100hz.flac",
+ "bbb_flac_stereo_600kbps_44100hz.info", false)));
+
+int main(int argc, char **argv) {
+ gEnv = new FlacDecoderTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGV("Flac Decoder Test Result = %d\n", status);
+ }
+ return status;
+}
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h b/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h
new file mode 100644
index 0000000..1334bba
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.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 __FLAC_DECODER_TEST_ENVIRONMENT_H__
+#define __FLAC_DECODER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class FlacDecoderTestEnvironment : public ::testing::Environment {
+ public:
+ FlacDecoderTestEnvironment() : res("/data/local/tmp/") {}
+
+ // Parses the command line arguments
+ int initFromOptions(int argc, char **argv);
+
+ void setRes(const char *_res) { res = _res; }
+
+ const string getRes() const { return res; }
+
+ private:
+ string res;
+};
+
+int FlacDecoderTestEnvironment::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 // __FLAC_DECODER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/flac/dec/test/README.md b/media/libstagefright/flac/dec/test/README.md
new file mode 100644
index 0000000..4d194cd
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/README.md
@@ -0,0 +1,40 @@
+## Media Testing ##
+---
+#### FlacDecoder :
+The FlacDecoder Test Suite validates the FlacDecoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m FlacDecoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/FlacDecoderTest/FlacDecoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/FlacDecoderTest/FlacDecoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/flac/dec/test/FlacDecoder.zip).
+Download, unzip and push these files into device for testing.
+
+```
+adb push FlacDecoder /data/local/tmp/
+```
+
+usage: FlacDecoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/FlacDecoderTest -P /data/local/tmp/FlacDecoder/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest FlacDecoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/id3/test/AndroidTest.xml b/media/libstagefright/id3/test/AndroidTest.xml
new file mode 100644
index 0000000..6c6697d
--- /dev/null
+++ b/media/libstagefright/id3/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Test module config for ID3 unit tests">
+ <option name="test-suite-tag" value="ID3Test" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="ID3Test->/data/local/tmp/ID3Test" />
+ <option name="push-file"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test.zip?unzip=true"
+ value="/data/local/tmp/ID3TestRes/" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="ID3Test" />
+ <option name="native-test-flag" value="-P /data/local/tmp/ID3TestRes/" />
+ </test>
+</configuration>
diff --git a/media/libstagefright/id3/test/README.md b/media/libstagefright/id3/test/README.md
index 72f730c..7fd8901 100644
--- a/media/libstagefright/id3/test/README.md
+++ b/media/libstagefright/id3/test/README.md
@@ -22,13 +22,19 @@
adb push ${OUT}/data/nativetest/ID3Test/ID3Test /data/local/tmp/
```
-The resource file for the tests is taken from [here](https://drive.google.com/drive/folders/1pt5HFVSysbqfyqY1sVJ9MTupZKCdqjYZ). Push these files into device for testing.
-Download ID3 folder and push all the files in this folder to /data/local/tmp/ID3 on the device.
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test.zip ).
+Download, unzip and push these files into device for testing.
+
```
-adb push ID3/. /data/local/tmp/ID3
+adb push ID3Test /data/local/tmp/
```
usage: ID3Test -P \<path_to_folder\>
```
adb shell /data/local/tmp/ID3Test -P /data/local/tmp/ID3/
```
+Alternatively, the test can also be run using atest command.
+
+```
+atest ID3Test -- --enable-module-dynamic-download=true
+```
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/Android.bp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/Android.bp
index c72eb55..3e5e4c8 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/Android.bp
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/Android.bp
@@ -1,5 +1,6 @@
cc_test_library {
name: "libmediabenchmark_jni",
+ sdk_version: "current",
defaults: [
"libmediabenchmark_common-defaults",
diff --git a/media/tests/benchmark/src/native/common/Android.bp b/media/tests/benchmark/src/native/common/Android.bp
index f8ea25c..d4389da 100644
--- a/media/tests/benchmark/src/native/common/Android.bp
+++ b/media/tests/benchmark/src/native/common/Android.bp
@@ -46,6 +46,8 @@
cc_defaults {
name: "libmediabenchmark-defaults",
+ sdk_version: "current",
+ stl: "c++_shared",
shared_libs: [
"libmediandk",
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index fa5bc4a..765ac99 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -14,6 +14,7 @@
"libbase",
"libcodec2_hidl@1.0",
"libcodec2_vndk",
+ "libhidlbase",
"libutils",
],
diff --git a/services/mediacodec/registrant/CodecServiceRegistrant.cpp b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
index 706ebee..7f7ceca 100644
--- a/services/mediacodec/registrant/CodecServiceRegistrant.cpp
+++ b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
@@ -18,21 +18,411 @@
#define LOG_TAG "CodecServiceRegistrant"
#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <C2Component.h>
#include <C2PlatformSupport.h>
#include <codec2/hidl/1.0/ComponentStore.h>
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/1.0/types.h>
+#include <hidl/HidlSupport.h>
#include <media/CodecServiceRegistrant.h>
+namespace /* unnamed */ {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using namespace ::android::hardware::media::c2::V1_0;
+using namespace ::android::hardware::media::c2::V1_0::utils;
+
+constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
+
+// Converter from IComponentStore to C2ComponentStore.
+class H2C2ComponentStore : public C2ComponentStore {
+protected:
+ sp<IComponentStore> mStore;
+ sp<IConfigurable> mConfigurable;
+public:
+ explicit H2C2ComponentStore(sp<IComponentStore> const& store)
+ : mStore{store},
+ mConfigurable{[store]() -> sp<IConfigurable>{
+ if (!store) {
+ return nullptr;
+ }
+ Return<sp<IConfigurable>> transResult =
+ store->getConfigurable();
+ return transResult.isOk() ?
+ static_cast<sp<IConfigurable>>(transResult) :
+ nullptr;
+ }()} {
+ if (!mConfigurable) {
+ LOG(ERROR) << "Preferred store is corrupted.";
+ }
+ }
+
+ virtual ~H2C2ComponentStore() override = default;
+
+ virtual c2_status_t config_sm(
+ std::vector<C2Param*> const ¶ms,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures
+ ) override {
+ Params hidlParams;
+ if (!createParamsBlob(&hidlParams, params)) {
+ LOG(ERROR) << "config -- bad input.";
+ return C2_TRANSACTION_FAILED;
+ }
+ c2_status_t status{};
+ Return<void> transResult = mConfigurable->config(
+ hidlParams,
+ true,
+ [&status, ¶ms, failures](
+ Status s,
+ const hidl_vec<SettingResult> f,
+ const Params& o) {
+ status = static_cast<c2_status_t>(s);
+ if (status != C2_OK && status != C2_BAD_INDEX) {
+ LOG(DEBUG) << "config -- call failed: "
+ << status << ".";
+ }
+ size_t i = failures->size();
+ failures->resize(i + f.size());
+ for (const SettingResult& sf : f) {
+ if (!objcpy(&(*failures)[i++], sf)) {
+ LOG(ERROR) << "config -- "
+ << "invalid SettingResult returned.";
+ return;
+ }
+ }
+ if (!updateParamsFromBlob(params, o)) {
+ LOG(ERROR) << "config -- "
+ << "failed to parse returned params.";
+ status = C2_CORRUPTED;
+ }
+ });
+ if (!transResult.isOk()) {
+ LOG(ERROR) << "config -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
+ return status;
+ };
+
+ virtual c2_status_t copyBuffer(
+ std::shared_ptr<C2GraphicBuffer>,
+ std::shared_ptr<C2GraphicBuffer>) override {
+ LOG(ERROR) << "copyBuffer -- not supported.";
+ return C2_OMITTED;
+ }
+
+ virtual c2_status_t createComponent(
+ C2String, std::shared_ptr<C2Component> *const component) override {
+ component->reset();
+ LOG(ERROR) << "createComponent -- not supported.";
+ return C2_OMITTED;
+ }
+
+ virtual c2_status_t createInterface(
+ C2String, std::shared_ptr<C2ComponentInterface> *const interface) {
+ interface->reset();
+ LOG(ERROR) << "createInterface -- not supported.";
+ return C2_OMITTED;
+ }
+
+ virtual c2_status_t query_sm(
+ const std::vector<C2Param *> &stackParams,
+ const std::vector<C2Param::Index> &heapParamIndices,
+ std::vector<std::unique_ptr<C2Param>> *const heapParams) const
+ override {
+ hidl_vec<ParamIndex> indices(
+ stackParams.size() + heapParamIndices.size());
+ size_t numIndices = 0;
+ for (C2Param* const& stackParam : stackParams) {
+ if (!stackParam) {
+ LOG(WARNING) << "query -- null stack param encountered.";
+ continue;
+ }
+ indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
+ }
+ size_t numStackIndices = numIndices;
+ for (const C2Param::Index& index : heapParamIndices) {
+ indices[numIndices++] =
+ static_cast<ParamIndex>(static_cast<uint32_t>(index));
+ }
+ indices.resize(numIndices);
+ if (heapParams) {
+ heapParams->reserve(heapParams->size() + numIndices);
+ }
+ c2_status_t status;
+ Return<void> transResult = mConfigurable->query(
+ indices,
+ true,
+ [&status, &numStackIndices, &stackParams, heapParams](
+ Status s, const Params& p) {
+ status = static_cast<c2_status_t>(s);
+ if (status != C2_OK && status != C2_BAD_INDEX) {
+ LOG(DEBUG) << "query -- call failed: "
+ << status << ".";
+ return;
+ }
+ std::vector<C2Param*> paramPointers;
+ if (!parseParamsBlob(¶mPointers, p)) {
+ LOG(ERROR) << "query -- error while parsing params.";
+ status = C2_CORRUPTED;
+ return;
+ }
+ size_t i = 0;
+ for (auto it = paramPointers.begin();
+ it != paramPointers.end(); ) {
+ C2Param* paramPointer = *it;
+ if (numStackIndices > 0) {
+ --numStackIndices;
+ if (!paramPointer) {
+ LOG(WARNING) << "query -- null stack param.";
+ ++it;
+ continue;
+ }
+ for (; i < stackParams.size() && !stackParams[i]; ) {
+ ++i;
+ }
+ if (i >= stackParams.size()) {
+ LOG(ERROR) << "query -- unexpected error.";
+ status = C2_CORRUPTED;
+ return;
+ }
+ if (stackParams[i]->index() != paramPointer->index()) {
+ LOG(WARNING) << "query -- param skipped: "
+ "index = "
+ << stackParams[i]->index() << ".";
+ stackParams[i++]->invalidate();
+ continue;
+ }
+ if (!stackParams[i++]->updateFrom(*paramPointer)) {
+ LOG(WARNING) << "query -- param update failed: "
+ "index = "
+ << paramPointer->index() << ".";
+ }
+ } else {
+ if (!paramPointer) {
+ LOG(WARNING) << "query -- null heap param.";
+ ++it;
+ continue;
+ }
+ if (!heapParams) {
+ LOG(WARNING) << "query -- "
+ "unexpected extra stack param.";
+ } else {
+ heapParams->emplace_back(
+ C2Param::Copy(*paramPointer));
+ }
+ }
+ ++it;
+ }
+ });
+ if (!transResult.isOk()) {
+ LOG(ERROR) << "query -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
+ return status;
+ }
+
+ virtual c2_status_t querySupportedParams_nb(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
+ c2_status_t status;
+ Return<void> transResult = mConfigurable->querySupportedParams(
+ std::numeric_limits<uint32_t>::min(),
+ std::numeric_limits<uint32_t>::max(),
+ [&status, params](
+ Status s,
+ const hidl_vec<ParamDescriptor>& p) {
+ status = static_cast<c2_status_t>(s);
+ if (status != C2_OK) {
+ LOG(DEBUG) << "querySupportedParams -- call failed: "
+ << status << ".";
+ return;
+ }
+ size_t i = params->size();
+ params->resize(i + p.size());
+ for (const ParamDescriptor& sp : p) {
+ if (!objcpy(&(*params)[i++], sp)) {
+ LOG(ERROR) << "querySupportedParams -- "
+ << "invalid returned ParamDescriptor.";
+ return;
+ }
+ }
+ });
+ if (!transResult.isOk()) {
+ LOG(ERROR) << "querySupportedParams -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
+ return status;
+ }
+
+ virtual c2_status_t querySupportedValues_sm(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const {
+ hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
+ for (size_t i = 0; i < fields.size(); ++i) {
+ if (!objcpy(&inFields[i], fields[i])) {
+ LOG(ERROR) << "querySupportedValues -- bad input";
+ return C2_TRANSACTION_FAILED;
+ }
+ }
+
+ c2_status_t status;
+ Return<void> transResult = mConfigurable->querySupportedValues(
+ inFields,
+ true,
+ [&status, &inFields, &fields](
+ Status s,
+ const hidl_vec<FieldSupportedValuesQueryResult>& r) {
+ status = static_cast<c2_status_t>(s);
+ if (status != C2_OK) {
+ LOG(DEBUG) << "querySupportedValues -- call failed: "
+ << status << ".";
+ return;
+ }
+ if (r.size() != fields.size()) {
+ LOG(ERROR) << "querySupportedValues -- "
+ "input and output lists "
+ "have different sizes.";
+ status = C2_CORRUPTED;
+ return;
+ }
+ for (size_t i = 0; i < fields.size(); ++i) {
+ if (!objcpy(&fields[i], inFields[i], r[i])) {
+ LOG(ERROR) << "querySupportedValues -- "
+ "invalid returned value.";
+ status = C2_CORRUPTED;
+ return;
+ }
+ }
+ });
+ if (!transResult.isOk()) {
+ LOG(ERROR) << "querySupportedValues -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
+ return status;
+ }
+
+ virtual C2String getName() const {
+ C2String outName;
+ Return<void> transResult = mConfigurable->getName(
+ [&outName](const hidl_string& name) {
+ outName = name.c_str();
+ });
+ if (!transResult.isOk()) {
+ LOG(ERROR) << "getName -- transaction failed.";
+ }
+ return outName;
+ }
+
+ virtual std::shared_ptr<C2ParamReflector> getParamReflector() const
+ override {
+ struct SimpleParamReflector : public C2ParamReflector {
+ virtual std::unique_ptr<C2StructDescriptor> describe(
+ C2Param::CoreIndex coreIndex) const {
+ hidl_vec<ParamIndex> indices(1);
+ indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
+ std::unique_ptr<C2StructDescriptor> descriptor;
+ Return<void> transResult = mBase->getStructDescriptors(
+ indices,
+ [&descriptor](
+ Status s,
+ const hidl_vec<StructDescriptor>& sd) {
+ c2_status_t status = static_cast<c2_status_t>(s);
+ if (status != C2_OK) {
+ LOG(DEBUG) << "SimpleParamReflector -- "
+ "getStructDescriptors() failed: "
+ << status << ".";
+ descriptor.reset();
+ return;
+ }
+ if (sd.size() != 1) {
+ LOG(DEBUG) << "SimpleParamReflector -- "
+ "getStructDescriptors() "
+ "returned vector of size "
+ << sd.size() << ". "
+ "It should be 1.";
+ descriptor.reset();
+ return;
+ }
+ if (!objcpy(&descriptor, sd[0])) {
+ LOG(DEBUG) << "SimpleParamReflector -- "
+ "getStructDescriptors() returned "
+ "corrupted data.";
+ descriptor.reset();
+ return;
+ }
+ });
+ return descriptor;
+ }
+
+ explicit SimpleParamReflector(sp<IComponentStore> base)
+ : mBase(base) { }
+
+ sp<IComponentStore> mBase;
+ };
+
+ return std::make_shared<SimpleParamReflector>(mStore);
+ }
+
+ virtual std::vector<std::shared_ptr<const C2Component::Traits>>
+ listComponents() override {
+ LOG(ERROR) << "listComponents -- not supported.";
+ return {};
+ }
+};
+
+bool ionPropertiesDefined() {
+ using namespace ::android::base;
+ std::string heapMask =
+ GetProperty("ro.com.android.media.swcodec.ion.heapmask", "undefined");
+ std::string flags =
+ GetProperty("ro.com.android.media.swcodec.ion.flags", "undefined");
+ std::string align =
+ GetProperty("ro.com.android.media.swcodec.ion.align", "undefined");
+ if (heapMask != "undefined" ||
+ flags != "undefined" ||
+ align != "undefined") {
+ LOG(INFO)
+ << "Some system properties for mediaswcodec ION usage are set: "
+ << "heapmask = " << heapMask << ", "
+ << "flags = " << flags << ", "
+ << "align = " << align << ". "
+ << "Preferred Codec2 store is defaulted to \"software\".";
+ return true;
+ }
+ return false;
+}
+
+} // unnamed namespace
+
extern "C" void RegisterCodecServices() {
- using namespace ::android::hardware::media::c2::V1_0;
+ using ComponentStore = ::android::hardware::media::c2::V1_0::utils::
+ ComponentStore;
LOG(INFO) << "Creating software Codec2 service...";
- android::sp<IComponentStore> store =
- new utils::ComponentStore(
- android::GetCodec2PlatformComponentStore());
+ sp<ComponentStore> store =
+ new ComponentStore(::android::GetCodec2PlatformComponentStore());
if (store == nullptr) {
LOG(ERROR) <<
"Cannot create software Codec2 service.";
} else {
+ if (!ionPropertiesDefined()) {
+ std::string preferredStoreName = "default";
+ sp<IComponentStore> preferredStore =
+ IComponentStore::getService(preferredStoreName.c_str());
+ if (preferredStore) {
+ ::android::SetPreferredCodec2ComponentStore(
+ std::make_shared<H2C2ComponentStore>(preferredStore));
+ LOG(INFO) <<
+ "Preferred Codec2 store is set to \"" <<
+ preferredStoreName << "\".";
+ } else {
+ LOG(INFO) <<
+ "Preferred Codec2 store is defaulted to \"software\".";
+ }
+ }
if (store->registerAsService("software") != android::OK) {
LOG(ERROR) <<
"Cannot register software Codec2 service.";